diff options
author | simonpj@microsoft.com <unknown> | 2009-11-02 17:22:17 +0000 |
---|---|---|
committer | simonpj@microsoft.com <unknown> | 2009-11-02 17:22:17 +0000 |
commit | 07fae6d68aac2c2c398c010495d9542c1eb9b9b7 (patch) | |
tree | 1e2fc3c4d32ff8198e554b5edc9b05d523643259 /docs | |
parent | 931d450e1f3c601e35f6e2460f721152bd458976 (diff) | |
download | haskell-07fae6d68aac2c2c398c010495d9542c1eb9b9b7.tar.gz |
Improve documentation of 'rec' in do-notation
Merge to 6.12 along with the main DoRec patch
Diffstat (limited to 'docs')
-rw-r--r-- | docs/users_guide/glasgow_exts.xml | 75 |
1 files changed, 46 insertions, 29 deletions
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index f6879febec..098827990e 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -871,8 +871,6 @@ the do-notation. The <option>-XDoRec</option> flag provides the necessary synta Here is a simple (albeit contrived) example: <programlisting> {-# LANGUAGE DoRec #-} -import Control.Monad.Fix - justOnes = do { rec { xs <- Just (1:xs) } ; return (map negate xs) } </programlisting> @@ -883,9 +881,9 @@ The background and motivation for recusrive do-notation is described in <ulink url="http://sites.google.com/site/leventerkok/">A recursive do for Haskell</ulink>, by Levent Erkok, John Launchbury, Haskell Workshop 2002, pages: 29-37. Pittsburgh, Pennsylvania. -This paper is essential reading for anyone making non-trivial use of mdo-notation, -and we do not repeat it here. However, note that GHC uses a different syntax than the one -in the paper. +The theory behind monadic value recursion is explained further in Erkok's thesis +<ulink url="http://sites.google.com/site/leventerkok/erkok-thesis.pdf">Value Recursion in Monadic Computations</ulink>. +However, note that GHC uses a different syntax than the one described in these documents. </para> <sect3> @@ -913,30 +911,54 @@ while <literal>rec</literal> is monadic. (In Haskell <literal>let</literal> is really <literal>letrec</literal>, of course.) </para> <para> -The Control.Monad.Fix library introduces the <literal>MonadFix</literal> class. Its definition is: -</para> +The static and dynamic semantics of <literal>rec</literal> can be described as follows: +<itemizedlist> +<listitem><para> +First, +similar to let-bindings, the <literal>rec</literal> is broken into +minimal recursive groups, a process known as <emphasis>segmentation</emphasis>. +For example: <programlisting> -class Monad m => MonadFix m where - mfix :: (a -> m a) -> m a +rec { a <- getChar ===> a <- getChar + ; b <- f a c rec { b <- f a c + ; c <- f b a ; c <- f b a } + ; putChar c } putChar c </programlisting> -<para> -The function <literal>mfix</literal> -dictates how the required recursion operation should be performed. For example, -<literal>justOnes</literal> desugars as follows: +The details of segmentation are described in Section 3.2 of +<ulink url="http://sites.google.com/site/leventerkok/">A recursive do for Haskell</ulink>. +Segmentation improves polymorphism, reduces the size of the recursive "knot", and, as the paper +describes, also has a semantic effect (unless the monad satisfies the right-shrinking law). +</para></listitem> +<listitem><para> +Then each resulting <literal>rec</literal> is desugared, using a call to <literal>Control.Monad.Fix.mfix</literal>. +For example, the <literal>rec</literal> group in the preceding example is desugared like this: <programlisting> -justOnes = do { xs <- mfix (\xs' -> do { xs <- Just (1:xs'); return xs }) - ; return (map negate xs) } +rec { b <- f a c ===> (b,c) <- mfix (\~(b,c) -> do { b <- f a c + ; c <- f b a } ; c <- f b a + ; return (b,c) }) </programlisting> In general, the statment <literal>rec <replaceable>ss</replaceable></literal> is desugared to the statement <programlisting> - <replaceable>vs</replaceable> <- mfix (\~<replaceable>vs</replaceable> -> do { <replaceable>ss</replaceable>; return <replaceable>vs</replaceable> }) +<replaceable>vs</replaceable> <- mfix (\~<replaceable>vs</replaceable> -> do { <replaceable>ss</replaceable>; return <replaceable>vs</replaceable> }) </programlisting> where <replaceable>vs</replaceable> is a tuple of the variables bound by <replaceable>ss</replaceable>. -Moreover, the original <literal>rec</literal> typechecks exactly -when the above desugared version would do so. (For example, this means that +</para><para> +The original <literal>rec</literal> typechecks exactly +when the above desugared version would do so. For example, this means that the variables <replaceable>vs</replaceable> are all monomorphic in the statements -following the <literal>rec</literal>, because they are bound by a lambda.) +following the <literal>rec</literal>, because they are bound by a lambda. +</para> +<para> +The <literal>mfix</literal> function is defined in the <literal>MonadFix</literal> +class, in <literal>Control.Monad.Fix</literal>, thus: +<programlisting> +class Monad m => MonadFix m where + mfix :: (a -> m a) -> m a +</programlisting> +</para> +</listitem> +</itemizedlist> </para> <para> Here are some other important points in using the recursive-do notation: @@ -958,18 +980,13 @@ for Haskell's internal state monad (strict and lazy, respectively). </para></listitem> <listitem><para> -Unlike ordinary do-notation, but like <literal>let</literal> and <literal>where</literal> bindings, -name shadowing is not allowed; that is, all the names bound in a single <literal>mdo</literal> must +Like <literal>let</literal> and <literal>where</literal> bindings, +name shadowing is not allowed within a <literal>rec</literal>; +that is, all the names bound in a single <literal>rec</literal> must be distinct (Section 3.3 of the paper). </para></listitem> - <listitem><para> -Similar to let-bindings, GHC implements the segmentation technique described in Section 3.2 of -<ulink url="http://sites.google.com/site/leventerkok/">A recursive do for Haskell</ulink>, -to break up a single <literal>rec</literal> statement into a sequence of statements with -<literal>rec</literal> groups of minimal size. This -improves polymorphism, reduces the size of the recursive "knot", and, as the paper -describes, also has a semantic effect (unless the monad satisfies the right-shrinking law). +It supports rebindable syntax (see <xref linkend="rebindable-syntax"/>). </para></listitem> </itemizedlist> </para> @@ -979,7 +996,7 @@ describes, also has a semantic effect (unless the monad satisfies the right-shri <para> GHC used to support the flag <option>-XREecursiveDo</option>, which enabled the keyword <literal>mdo</literal>, precisely as described in -<ulink url="http://citeseer.ist.psu.edu/erk02recursive.html">A recursive do for Haskell</ulink>, +<ulink url="http://sites.google.com/site/leventerkok/">A recursive do for Haskell</ulink>, but this is now deprecated. Instead of <literal>mdo { Q; e }</literal>, write <literal>do { rec Q; e }</literal>. </para> |