anaphoric

...now browsing by tag

 
 

Control.Monad.IfElse

Thursday, January 29th, 2009

There’s been some discussion on the mailing list about changing the type of Control.Monad.when.  I had a need a little while back for the old LISP anaphoric-if.  I also had a need for something that turned out to be in Control.Monad already — when (but I didn’t know it at the time).  Since then, I’ve been throwing together miscellaneous useful control flow mechanisms, and I’ve packaged them in Control.Monad.IfElse. In this post, I’ll talk a little bit more about how to use them and when.

First, there’s the anaphoric if, when, and conditional: aif, awhen, and acond.  By anaphoric, we mean to say that the result of the conditional test is used as part of the result.

awhen :: Maybe a -> (a -> m ())
aif :: Maybe a -> (a -> m b) -> m b -> m b
acond :: Monad m => [(Maybe a, a -> m ())] -> m ()

In all cases, if the value of the test is “Just a”, then a gets passed into a clause.  In the case of awhen, the clause takes a and returns an m () (in my case, usually IO or Render).  In the case of aif, there is a parameterless else clause that is evaluated upon a Nothing.  And finally, acond takes a list of pairs where the first element is being tested and the second is the clause that is evaluated for a on a “Just a” There are also lifted variants of these, awhenM, aifM, and acondM, where the Maybe a is encased in a monad.

In addition, the documentation isn’t generated for them, but there are a few operators that exist in the source.  I’ll update the doc to reflect them, but

(>>?) is a synonym for when

and

(>>=?) is a synonym for awhen

Usage for these is:

test >>? clause

atest >>=? (\a -> clause)

In addition, there are liftM2-ed logical and and or, (||^) and (&&^).

The rest are pretty well documented in the Haddock.  There is a cond and condM, which is like an if-else-if chain (and ncond and ncondM are unless else chains).  There’s a whenM counterpart to when, where the test is lifted into the same monad as the clause.  There’s whileM and untilM, which unfold their clauses until the test is False (or True in the case of until).  There’s return’, which is return, but strict in its argument.  And finally there’s “returning,” which is a substitute for “clause >> return a”

That’s most of the library.  Enjoy.