Reygoch
Reygoch

Reputation: 1304

Desugaring 'do' blocks

I'm having little trouble translating this do statement :

ex10 :: [Int]
ex10 = do
    num <- [1..20]
    guard (even num)
    guard (num `mod` 3 == 0)
    return num

into some kind of monad syntax like this :

ex10' :: [Int]
ex10' = [1..20] >>= (guard . even) >>= (guard . (==0) . (mod 3)) >>= \r -> return r

This doesn't work, and I'm not quite sure why. I think I might have misunderstood guard but am not sure in what way.

Upvotes: 3

Views: 370

Answers (1)

Lee
Lee

Reputation: 144206

guard has type MonadPlus m => Bool -> m () so your third segment

(guard . (==0) . (mod 3))

receives a value of type () which is not what you want. In do notation

do
  guard (even num)
  guard (num `mod` 3 == 0)

is desugarded into something like

guard (even num) >> guard (num `mod` 3 == 0)

so you can implement ex10' as

 ex10' = [1..20] >>= (\num -> (guard $ even num) >> (guard $ num `mod` 3 == 0) >> return num)

Upvotes: 4

Related Questions