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