[Haskell-cafe] Grokking monads by not overlooking concatMap

Achim Schneider barsoap at web.de
Mon May 5 07:39:20 EDT 2008


guard True = return ()
guard False = []


-- the textbook example
f = do
    x <- [1..4]
    y <- [2..8]
    guard (x*y==8)
    return (x,y)

-- the translation.
f' = [1..4] >>= (\x ->
     [2..8] >>= (\y ->
     (if (x*y == 8) then return () else []) >>
     return (x,y)))

-- another one. note that we can move the final 
-- return out of the parens. It would even work without it, but we'd
-- get a list containing many empty lists: concat fixes that. 
f'' = [1..4] >>= (\x ->
      [2..8] >>= (\y ->
      if (x*y == 8) then [(x,y)] else [] >>= return ))

-- bind desugared. Actually, it seems to be impossible to
-- write this in monadic notation and I'm getting quite confused.
f''' = concatMap 
       (\x -> concatMap 
            (\y -> if x*y == 8 then [(x,y)] else [])
            [2..8])
       [1..4]

-- That's the one I've been looking for. Remember that
-- return e = [e]
f'''' = concatMap 
        (\x -> concatMap 
            (\y -> concatMap 
                (\_ -> [(x,y)])
                (if x*y == 8 then [()] else []))
            [2..8])
        [1..4]

Morale: Premature term elimination is the root of all misunderstanding.

Haskell wins the wickedness of design contest by using [()] and [] as
truth values.

-- 
(c) this sig last receiving data processing entity. Inspect headers for
past copyright information. All rights reserved. Unauthorised copying,
hiring, renting, public performance and/or broadcasting of this
signature prohibited. 



More information about the Haskell-Cafe mailing list