Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch : master
http://hackage.haskell.org/trac/ghc/changeset/96a37685b4a16fda2a53a3130c69e05e4daff91d >--------------------------------------------------------------- commit 96a37685b4a16fda2a53a3130c69e05e4daff91d Author: Ross Paterson <[email protected]> Date: Tue Jun 12 13:29:10 2012 +0100 tweak documentation of mdo/rec >--------------------------------------------------------------- docs/users_guide/glasgow_exts.xml | 43 +++++++++++++++++++++--------------- 1 files changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index 73310c6..bccb1f9 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -866,7 +866,12 @@ To disable it, you can use the <option>-XNoTraditionalRecordSyntax</option> flag <para> It turns out that such recursive bindings do indeed make sense for a variety of monads, but not all. In particular, recursion in this sense requires a fixed-point operator for the underlying - monad, captured by the <literal>mfix</literal> method of the <literal>MonadFix</literal> class. Haskell's + monad, captured by the <literal>mfix</literal> method of the <literal>MonadFix</literal> class, defined in <literal>Control.Monad.Fix</literal> as follows: +<programlisting> +class Monad m => MonadFix m where + mfix :: (a -> m a) -> m a +</programlisting> + Haskell's <literal>Maybe</literal>, <literal>[]</literal> (list), <literal>ST</literal> (both strict and lazy versions), <literal>IO</literal>, and many other monads have <literal>MonadFix</literal> instances. On the negative side, the continuation monad, with the signature <literal>(a -> r) -> r</literal>, does not. @@ -876,8 +881,9 @@ To disable it, you can use the <option>-XNoTraditionalRecordSyntax</option> flag For monads that do belong to the <literal>MonadFix</literal> class, GHC provides an extended version of the do-notation that allows recursive bindings. The <option>-XRecursiveDo</option> (language pragma: <literal>RecursiveDo</literal>) - provides the necessary syntactic support, introducing the keyword <literal>mdo</literal>. Unlike - bindings in a <literal>do</literal> expression, those introduced by <literal>mdo</literal> + provides the necessary syntactic support, introducing the keywords <literal>mdo</literal> and + <literal>rec</literal> for higher and lower levels of the notation respectively. Unlike + bindings in a <literal>do</literal> expression, those introduced by <literal>mdo</literal> and <literal>rec</literal> are recursively defined, much like in an ordinary let-expression. Due to the new keyword <literal>mdo</literal>, we also call this notation the <emphasis>mdo-notation</emphasis>. </para> @@ -889,6 +895,12 @@ To disable it, you can use the <option>-XNoTraditionalRecordSyntax</option> flag justOnes = mdo { xs <- Just (1:xs) ; return (map negate xs) } </programlisting> +or equivalently +<programlisting> +{-# LANGUAGE RecursiveDo #-} +justOnes = do { rec { xs <- Just (1:xs) } + ; return (map negate xs) } +</programlisting> As you can guess <literal>justOnes</literal> will evaluate to <literal>Just [-1,-1,-1,...</literal>. </para> @@ -896,8 +908,8 @@ As you can guess <literal>justOnes</literal> will evaluate to <literal>Just [-1, GHC's implementation the mdo-notation closely follows the original translation as described in the paper <ulink url="https://sites.google.com/site/leventerkok/recdo.pdf">A recursive do for Haskell</ulink>, which in turn is based on the work <ulink url="http://sites.google.com/site/leventerkok/erkok-thesis.pdf">Value Recursion - in Monadic Computations</ulink>. Furthermore, GHC extends the syntax described in the former paper by the - additional <literal>rec</literal> keyword, as we describe next. + in Monadic Computations</ulink>. Furthermore, GHC extends the syntax described in the former paper + with a lower level syntax flagged by the <literal>rec</literal> keyword, as we describe next. </para> <sect3> @@ -939,9 +951,9 @@ rec { b <- f a c ===> (b,c) <- mfix (\~(b,c) -> do { b <- f a c </para> <para> - Note in particular that the translation for a <literal>rec</literal> block only involves wrapping around a call - to <literal>mfix</literal>: otherwise it does not perform any other analysis on the bindings at all. The latter is the task - for the <literal>mdo</literal> notation, as we describe next. + Note in particular that the translation for a <literal>rec</literal> block only involves wrapping a call + to <literal>mfix</literal>: it performs no other analysis on the bindings. The latter is the task + for the <literal>mdo</literal> notation, which is described next. </para> </sect3> @@ -950,11 +962,11 @@ rec { b <- f a c ===> (b,c) <- mfix (\~(b,c) -> do { b <- f a c <para> A <literal>rec</literal>-block tells the compiler where precisely the recursive knot should be tied. It turns out that - the placement of the recursive knots can be rather delicate: In particular, we would like the knots to be wrapped - around as minimal groups as possible. This process is known as <emphasis>segmentation</emphasis>, an is described + the placement of the recursive knots can be rather delicate: in particular, we would like the knots to be wrapped + around as minimal groups as possible. This process is known as <emphasis>segmentation</emphasis>, and is described in detail in Secton 3.2 of <ulink url="https://sites.google.com/site/leventerkok/recdo.pdf">A recursive do for Haskell</ulink>. Segmentation improves polymorphism and reduces the size of the recursive knot. Most importantly, it avoids - unnecessary interference caused by a fundamental issue with the so called <emphasis>right-shrinking</emphasis> + unnecessary interference caused by a fundamental issue with the so-called <emphasis>right-shrinking</emphasis> axiom for monadic recursion. In brief, most monads of interest (IO, strict state, etc.) do <emphasis>not</emphasis> have recursion operators that satisfy this axiom, and thus not performing segmentation can cause unnecessary interference, changing the termination behavior of the resulting translation. @@ -974,7 +986,7 @@ rec { b <- f a c ===> (b,c) <- mfix (\~(b,c) -> do { b <- f a c </para> <para> - Here's an example <literal>mdo</literal>-expression, and its translation to <literal>rec</literal> blocks: + Here is an example <literal>mdo</literal>-expression, and its translation to <literal>rec</literal> blocks: <programlisting> mdo { a <- getChar ===> do { a <- getChar ; b <- f a c ; rec { b <- f a c @@ -995,12 +1007,7 @@ would expect. <literal>rec</literal> blocks to wrap over minimal recursive groups. Then, each resulting <literal>rec</literal> is desugared, using a call to <literal>Control.Monad.Fix.mfix</literal> as described in the previous section. The original <literal>mdo</literal>-expression typechecks exactly when the desugared - version would do so. The <literal>mfix</literal> function is defined in the <literal>MonadFix</literal> - class, in <literal>Control.Monad.Fix</literal>, thusly: -<programlisting> -class Monad m => MonadFix m where - mfix :: (a -> m a) -> m a -</programlisting> + version would do so. </para> <para> _______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
