X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fglasgow_exts.xml;h=89198c426412cef1cbeead168df4819c627b6b7c;hb=52cba3c47b25a78402e542ff63dc905fc5b26b62;hp=a5fba51788c7abf19760dae1980a24d057164e51;hpb=87c441135e53edbd6e322677e48e57ba1aec6bd8;p=ghc-hetmet.git
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index a5fba51..89198c4 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -1201,6 +1201,234 @@ output = [ x
+
+
+
+ Monad comprehensions
+ monad comprehensions
+
+
+ Monad comprehesions generalise the list comprehension notation,
+ including parallel comprehensions
+ () and
+ transform comprenensions ()
+ to work for any monad.
+
+
+ Monad comprehensions support:
+
+
+
+
+ Bindings:
+
+
+
+[ x + y | x <- Just 1, y <- Just 2 ]
+
+
+
+ Bindings are translated with the (>>=) and
+ return functions to the usual do-notation:
+
+
+
+do x <- Just 1
+ y <- Just 2
+ return (x+y)
+
+
+
+
+
+ Guards:
+
+
+
+[ x | x <- [1..10], x <= 5 ]
+
+
+
+ Guards are translated with the guard function,
+ which requires a MonadPlus instance:
+
+
+
+do x <- [1..10]
+ guard (x <= 5)
+ return x
+
+
+
+
+
+ Transform statements (as with -XTransformListComp):
+
+
+
+[ x+y | x <- [1..10], y <- [1..x], then take 2 ]
+
+
+
+ This translates to:
+
+
+
+do (x,y) <- take 2 (do x <- [1..10]
+ y <- [1..x]
+ return (x,y))
+ return (x+y)
+
+
+
+
+
+ Group statements (as with -XTransformListComp):
+
+
+
+[ x | x <- [1,1,2,2,3], then group by x ]
+[ x | x <- [1,1,2,2,3], then group by x using GHC.Exts.groupWith ]
+[ x | x <- [1,1,2,2,3], then group using myGroup ]
+
+
+
+ The basic then group by e statement is
+ translated using the mgroupWith function, which
+ requires a MonadGroup instance, defined in
+ Control.Monad.Group:
+
+
+
+do x <- mgroupWith (do x <- [1,1,2,2,3]
+ return x)
+ return x
+
+
+
+ Note that the type of x is changed by the
+ grouping statement.
+
+
+
+ The grouping function can also be defined with the
+ using keyword.
+
+
+
+
+
+ Parallel statements (as with -XParallelListComp):
+
+
+
+[ (x+y) | x <- [1..10]
+ | y <- [11..20]
+ ]
+
+
+
+ Parallel statements are translated using the
+ mzip function, which requires a
+ MonadZip instance defined in
+ Control.Monad.Zip:
+
+
+
+do (x,y) <- mzip (do x <- [1..10]
+ return x)
+ (do y <- [11..20]
+ return y)
+ return (x+y)
+
+
+
+
+
+
+ All these features are enabled by default if the
+ MonadComprehensions extension is enabled. The types
+ and more detailed examples on how to use comprehensions are explained
+ in the previous chapters and . In general you just have
+ to replace the type [a] with the type
+ Monad m => m a for monad comprehensions.
+
+
+
+ Note: Even though most of these examples are using the list monad,
+ monad comprehensions work for any monad.
+ The base package offers all necessary instances for
+ lists, which make MonadComprehensions backward
+ compatible to built-in, transform and parallel list comprehensions.
+
+ More formally, the desugaring is as follows. We write D[ e | Q]
+to mean the desugaring of the monad comprehension [ e | Q]:
+
+Expressions: e
+Declarations: d
+Lists of qualifiers: Q,R,S
+
+-- Basic forms
+D[ e | ] = return e
+D[ e | p <- e, Q ] = e >>= \p -> D[ e | Q ]
+D[ e | e, Q ] = guard e >> \p -> D[ e | Q ]
+D[ e | let d, Q ] = let d in D[ e | Q ]
+
+-- Parallel comprehensions (iterate for multiple parallel branches)
+D[ e | (Q | R), S ] = mzip D[ Qv | Q ] D[ Rv | R ] >>= \(Qv,Rv) -> D[ e | S ]
+
+-- Transform comprehensions
+D[ e | Q then f, R ] = f D[ Qv | Q ] >>= \Qv -> D[ e | R ]
+
+D[ e | Q then f by b, R ] = f b D[ Qv | Q ] >>= \Qv -> D[ e | R ]
+
+D[ e | Q then group using f, R ] = f D[ Qv | Q ] >>= \ys ->
+ case (fmap selQv1 ys, ..., fmap selQvn ys) of
+ Qv -> D[ e | R ]
+
+D[ e | Q then group by b using f, R ] = f b D[ Qv | Q ] >>= \ys ->
+ case (fmap selQv1 ys, ..., fmap selQvn ys) of
+ Qv -> D[ e | R ]
+
+where Qv is the tuple of variables bound by Q (and used subsequently)
+ selQvi is a selector mapping Qv to the ith component of Qv
+
+Operator Standard binding Expected type
+--------------------------------------------------------------------
+return GHC.Base t1 -> m t2
+(>>=) GHC.Base m1 t1 -> (t2 -> m2 t3) -> m3 t3
+(>>) GHC.Base m1 t1 -> m2 t2 -> m3 t3
+guard Control.Monad t1 -> m t2
+fmap GHC.Base forall a b. (a->b) -> n a -> n b
+mgroupWith Control.Monad.Group forall a. (a -> t) -> m1 a -> m2 (n a)
+mzip Control.Monad.Zip forall a b. m a -> m b -> m (a,b)
+
+The comprehension should typecheck when its desugaring would typecheck.
+
+
+Monad comprehensions support rebindable syntax ().
+Without rebindable
+syntax, the operators from the "standard binding" module are used; with
+rebindable syntax, the operators are looked up in the current lexical scope.
+For example, parallel comprehensions will be typechecked and desugared
+using whatever "mzip" is in scope.
+
+
+The rebindable operators must have the "Expected type" given in the
+table above. These types are surprisingly general. For example, you can
+use a bind operator with the type
+
+(>>=) :: T x y a -> (a -> T y z b) -> T x z b
+
+In the case of transform comprehensions, notice that the groups are
+parameterised over some arbitrary type n (provided it
+has an fmap, as well as
+the comprehension being over an arbitrary monad.
+
+
+
@@ -5884,7 +6112,7 @@ type variables, in the annotated expression. For example:
f = runST ( (op >>= \(x :: STRef s Int) -> g x) :: forall s. ST s Bool )
-Here, the type signature forall a. ST s Bool brings the
+Here, the type signature forall s. ST s Bool brings the
type variable s into scope, in the annotated expression
(op >>= \(x :: STRef s Int) -> g x).