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

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.

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

```