[Haskell] Mixing monadic and non-monadic functions

Duncan Coutts duncan at coutts.uklinux.net
Tue Mar 23 23:57:55 EST 2004


On Tue, 2004-03-23 at 15:29, Sean E. Russell wrote:

> Here's my base case:
> 
> 	someFunc :: String -> IO [a]
> 	...
> 		ax <- someFunc a
> 		bx <- someFunc b
> 		assertBool "fail" $ length ax == length bx
> 
> I don't like the assignments; the typing is redundant, if I have a lot of 
> asserts like this, and the "variables" are temporary.  What I'd much rather 
> have is:
> 
> 	...
> 		assertBool "fail" $ (length $ someFunc a) == (length $ someFunc b)
> 
> which is more readable, to my eye.
> 
> The only solution which has been suggested that may work is liberal use of the 
> liftM variants, but this gets *really* tedious and obtuse.
> 
> Is there an elegant way to do what I want to do, or am I stuck with 
> procedural-style assignments and bunches of temp vars?

For a project I did which involved a lot of monadic code I used some
combinators which allow you to write in a more applicative/functional
style but still thread the monad state through everything.

Basically instead of writing:

do
  a' <- foo a
  b' <- foo b
  c' <- foo c
  return $ f a' b' c'

you write:
f $> foo a <$> foo b <$> foo c

Unfortunately it doesn't work so well with infix operators, you'd have
to say (==) $> firstThing <$> secondThing
which is not quite so appealing.

Your example would look like so:
assertBool "fail" <$$> (==) $> (length $> someFunc a) <$> (length $> someFunc b)

Here's the little combinator library, it's really just a matter of using
infix versions of standard monad functions and playing with their
left/right associativity and precedence.

import Monad (liftM, ap)

infixl 1  $>, <$>	--same as liftM & ap, but left associative infix
infixr 0  <$$>		--same as =<<, but different precedence

($>) :: Monad m => (a -> b) -> (m a -> m b)
($>) = liftM

(<$>) :: Monad m => m (a -> b) -> (m a -> m b)
(<$>) = ap

(<$$>) :: Monad m => (a -> m b) -> (m a -> m b)
(<$$>) = (=<<)

--
Duncan



More information about the Haskell mailing list