Grokking monads by not overlooking concatMap

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.

Achim Schneider wrote:
-- 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.
Maybe you wanted to say: "... by using [()] as True value and [] as False value" ... which does not seem that wicked (at least to me). Peter.

Peter Hercek wrote:
Achim Schneider wrote:
Haskell wins the wickedness of design contest by using [()] and [] as truth values.
Maybe you wanted to say: "... by using [()] as True value and [] as False value" ... which does not seem that wicked (at least to me).
Oops sorry, missed you say "truth" and not "true" :-D Still not more wicked as 0 meaning False and non-zero meaning True in C.

Peter Hercek
Achim Schneider wrote:
-- 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.
Maybe you wanted to say: "... by using [()] as True value and [] as False value" ... which does not seem that wicked (at least to me).
Strangely enough, it reads exactly the same to me. IMHO, not working like filter is the thing that makes this wicked: guard doesn't care about what is returned, you could as well say (\_ -> [("foo","bar")]) -- (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.

Achim Schneider wrote:
Peter Hercek
wrote: Haskell wins the wickedness of design contest by using [()] and [] as truth values. Maybe you wanted to say: "... by using [()] as True value and [] as False value" ... which does not seem that wicked (at least to me).
Strangely enough, it reads exactly the same to me. IMHO, not working like filter is the thing that makes this wicked: guard doesn't care about what is returned, you could as well say (\_ -> [("foo","bar")])
Right, should be a list with one element in it to represent True. So maybe it is a bit worse than C since list with two elements gives you two True values :-D On the other side it is nice that guard works the expected way (using the same implementation) with other MonadPlus-es too.

Peter Hercek
Achim Schneider wrote:
Peter Hercek
wrote: Haskell wins the wickedness of design contest by using [()] and [] as truth values. Maybe you wanted to say: "... by using [()] as True value and [] as False value" ... which does not seem that wicked (at least to me).
Strangely enough, it reads exactly the same to me. IMHO, not working like filter is the thing that makes this wicked: guard doesn't care about what is returned, you could as well say (\_ -> [("foo","bar")])
Right, should be a list with one element in it to represent True. So maybe it is a bit worse than C since list with two elements gives you two True values :-D On the other side it is nice that guard works the expected way (using the same implementation) with other MonadPlus-es too.
Yes ;) You can actually do stuff like f'''' = concatMap (\x -> concatMap (\y -> concatMap (\_ -> [(x,y)]) (if x*y == 8 then replicate (x+y) () else [])) [2..8]) [1..4] , resulting in [(1,8),(1,8),(1,8),(1,8),(1,8),(1,8),(1,8),(1,8),(1,8),(2,4),(2,4), (2,4),(2,4),(2,4),(2,4),(4,2),(4,2),(4,2),(4,2),(4,2),(4,2)] or Prelude> "Hello World" >>= (\c -> if (c == 'o') then replicate 10 c else [c]) "Helloooooooooo Woooooooooorld" -- (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.
participants (2)
-
Achim Schneider
-
Peter Hercek