[Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]

Ertugrul Söylemez es at ertes.de
Wed Jul 10 11:42:47 CEST 2013

oleg at okmij.org wrote:

> > If you would like to write
> >
> >     let (x,s) = foo 1 [] in
> >     let (y,s) = bar x s in
> >     let (z,s) = baz x y s in
> >
> > instead, use a state monad.
> Incidentally I did write almost exactly this code once. Ironically, it
> was meant as a lead-on to the State monad.
> But there have been other cases where State monad was better
> avoided. For instance, functions like foo and bar are already written
> and they are not in the state monad.

It's fine to use `state` or the StateT constructor here.

> For example, foo may take a non-empty Set and return the minimal
> element and the set without the minimal element. There are several
> such handy functions in Data.Set and Data.Map. Injecting such
> functions into a Set monad for the sake of three lines seems overkill.

Not a Set monad, but a state monad.  Other examples include 'random' and
'randomR', where you can just apply 'state':

    getRandom  = state random
    getRandomR = state . randomR

I do this a lot.

> Also, in the code above s's don't have to have the same type.

For this purpose we have indexed state monads.

> I particularly like repeated lets when I am writing the code to apply
> transformations to it. Being explicit with state passing improves the
> confidence. It is simpler to reason with the pure code.

Really?  I'm more confident that I got the "updates" right when I use a
state monad, possibly together with lenses.  The idea is to disallow
`get` and only allow `modify` and `put`.

The thing is, your code is really imperative, and it exhibits all the
usual effects of imperative programming:  If you mess up the order of
things, you get wrong results.  In fact the let-style makes things worse
by requiring you to renumber your variables all the time.  A
non-recursive let would really just cover up this problem by imposing an
arbitrary constraint on you.  I think we are all aware that shadowing is
a bad idea, no matter whether you do it through Identity or
non-recursive let.

Also if you are serious about this, you would have to make non-recursive
let the default to get OCaml-style behavior, which would be an extremely
invasive change.  We would have to fix pretty much all packages, all
tutorials, all books, all wiki pages, etc.  Otherwise just like you may
forget to renumber your variables, you may just as well forget to add
the "norec" keyword or whatever the syntax would be.

State monads are actually a nice abstraction to limit the number of
things that could go wrong in this setting.  I suggest using them
instead of changing the language.


Not to be or to be and (not to be or to be and (not to be or to be and
(not to be or to be and ... that is the list monad.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130710/a9c74b00/attachment.pgp>

More information about the Haskell-Cafe mailing list