Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally building a list

I want to build a list of command line args from a bunch of other pre-defined variables in Haskell. As is the nature of many command line parameters, those are either present or not.

Is there a common idiom for conditionally building a list in Haskell? The if–then–else approach feels rather tedious:

import Control.Monad
join [ if opt1 then [a] else []
     , if opt2 then [b] else []
     , if opt3 then [c] else [] ]

-- gives me back [a, c] or something like that.

I have something like

onlyIf :: MonadPlus m => a -> Bool -> m a
onlyIf a p = if p then return a else mzero

or

mwhen :: Monoid a => Bool -> a -> a
mwhen p a = if p then a else mempty

in mind, which could then be used like

a `onlyIf` opt1 <>
b `onlyIf` opt2 <>
c `onlyIf` opt3

or

mwhen opt1 [a] <>
mwhen opt2 [b] <>
mwhen opt3 [c]

Hoogle is not really helpful here and of course, there may be a much better (/more common) way of doing this stuff.

like image 661
Debilski Avatar asked Jul 31 '14 11:07

Debilski


2 Answers

I like using concat with list comprehensions in that case:

concat
  [ [a | opt1]
  , [b | opt2]
  , [c | opt3]
  ]

[a | opt1] is the empty list if opt1 is False, otherwise it is a singleton list containing only a.

You can also do it using <$ and guard:

concat
  [ a <$ guard opt1
  , b <$ guard opt2
  , c <$ guard opt3
  ]

I don't think there exists a onlyIf function anywhere in base.

like image 129
bennofs Avatar answered Sep 30 '22 10:09

bennofs


You can use a Writer (see this question) and use when instead of Maybe. However using Maybe instead of condition,result can be better.

like image 33
mb14 Avatar answered Sep 30 '22 10:09

mb14