FW: MonadFix

Simon Marlow simonmar@microsoft.com
Fri, 1 Feb 2002 10:41:18 -0000


Folks,=20

Levent has some comments and suggestions for the MonadFix library, which
is currently Control.Monad.Fix in the hierarchical libraries (see
below).  Does anyone else have any opinions?   Should this module be
renamed to Control.Monad.Rec, or kept as it is?

I'm agnostic on the naming issue.  Point 2: I don't think we should
remove the export of 'fix', as we're generally moving in the direction
of encouraging the use of qualified names.  Points 3 & 4: sure.

Cheers,
	Simon

-----Original Message-----
From: Levent Erkok [mailto:erkok@cse.ogi.edu]=20
Sent: 31 January 2002 10:26
To: Simon Marlow; Ross Paterson; cvs-hslibs@haskell.org
Cc: John Launchbury
Subject: Re: MonadFix


On Thursday 31 January 2002 12:44 pm, Simon Marlow wrote:
> Having said that, I just checked and the new hierarchical libraries
are
> already rearranged as you suggested.  Control.Monad.Fix and
> Control.Monad.Identity are both marked "portable" which means they
don't
> rely on any Haskell extensions.

That's wonderful. I've four suggestions:

1. Let's rename MonadFix to MonadRec: both the name of the class and the
library
file: I really think we should concentrate on "recursive bindings" than
fixed
point operators. Much like "letrec-let" correspondence, we should have
"MonadRec-Monad"
correspondence. This should amount to just a search and replace in a
bunch of files,
so it requires little effort to go for this change.

2. (Debatable) Remove the export of the function "fix" from the library:
fix is too=20
common a name to export: likely to cause trouble. MonadRec.lhs should
just export=20
the class MonadRec and it's only method mfix.

3. Add the following list instance to the library:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
instance MonadRec [] where
    mfix f =3D case fix (f . head) of
               []    -> []
               (x:_) -> x : mfix (tail . f)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

4. Replace the confusing error message in the Maybe instance with
something else.
Currently it looks like:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
instance MonadFix Maybe where
        mfix f =3D let
                a =3D f $ case a of
                        Just x -> x
                        _      -> error "empty mfix argument"
                in a
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

This definition, although correct, is misleading. Let f be the function:

      const Nothing

then, the result of mfix is Nothing (correctly), but it looks as if it's
going
to be bound to an error value, just confusing the reader. In fact, one
can show that '
if the second branch of the case expression is taken, then f should be
the function=20
"const Nothing" (by monotonicity). So, I suggest the following shorter
form:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
instance MonadRec Maybe where
    mfix f =3D let a =3D f (unJust a) in a
             where unJust (Just x) =3D x
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Thanks,

-Levent.