wiki:MonadComprehensions

Version 7 (modified by nsch, 3 years ago) (diff)

--

Monad comprehensions

Monad comprehensions were added to the main GHC repository on the 4th May 2011. See ticket #4370.

Translation rules

Variables    : x and y
Expressions  : e, f and g
Patterns     : w
Qualifiers   : p, q and r

The main translation rule for monad comprehensions.

[ e | q ] = [| q |] >>= (return . (\q_v -> e))

(.)_v rules. Note that _v is a postfix rule application.

(w <- e)_v = w
(let w = d)_v = w
(g)_v = ()
(p , q)_v = (p_v,q_v)
(p | v)_v = (p_v,q_v)
(q, then f)_v = q_v
(q, then f by e)_v = q_v
(q, then group by e using f)_v = q_v
(q, then group using f)_v = q_v

[|.|] rules.

[| w <- e |] = e
[| let w = d |] = return d
[| g |] = guard g
[| p, q |] = ([| p |] >>= (return . (\p_v ->  [| q |] >>= (return . (\q_v -> (p_v,q_v)))))) >>= id
[| p | q |] = mzip [| p |] [| q |]
[| q, then f |] = f [| q |]
[| q, then f by e |] = f (\q_v -> e) [| q |]
[| q, then group by e using f |] = (f (\q_v -> e) [| q |]) >>= (return . (unzip q_v))
[| q, then group using f |] = (f [| q |]) >>= (return . (unzip q_v))

unzip (.) rules. Note that unzip is a desugaring rule (i.e., not a function to be included in the generated code).

unzip () = id
unzip x  = id
unzip (w1,w2) = \e -> ((unzip w1) (e >>= (return .(\(x,y) -> x))), (unzip w2) (e >>= (return . (\(x,y) -> y))))

Examples

Some translation examples using the do notation to avoid things like pattern matching failures are:

[ x+y | x <- Just 1, y <- Just 2 ]

-- translates to:
do x <- Just 1
   y <- Just 2
   return (x+y)

Transform statements:

[ x | x <- [1..], then take 10 ]

-- translates to:
take 10 (do
  x <- [1..]
  return x)

Grouping statements (note the change of types):

[ (x :: [Int]) | x <- [1,2,1,2], then group by x ] :: [[Int]]

-- translates to:
do x <- mgroupWith (\x -> x) [1,2,1,2]
   return x

Parallel statements:

[ x+y | x <- [1,2,3]
      | y <- [4,5,6] ]

-- translates to:
do (x,y) <- mzip [1,2,3] [4,5,6]
   return (x+y)

Note that the actual implementation is not using the do-Notation, it's only used here to give a basic overview about how the translation works.

Implementation details

Monad comprehensions had to change the StmtLR data type in the hsSyn/HsExpr.lhs file in order to be able to lookup and store all functions required to desugare monad comprehensions correctly (e.g. return, (>>=), guard etc). Renaming is done in rename/RnExpr.lhs and typechecking in typecheck/TcMatches.lhs. The main desugaring is done in deSugar/DsListComp.lhs. If you want to start hacking on monad comprehensions I'd look at those files first.

Some things you might want to be aware of:

[todo]