[Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]
Edward Z. Yang
ezyang at MIT.EDU
Wed Jul 10 10:01:04 CEST 2013
In my opinion, when you are rebinding a variable with the same name,
there is usually another way to structure your code which eliminates
the variable.
If you would like to write:
let x = foo input in
let x = bar x in
let x = baz x in
instead, write
baz . bar . foo $ input
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.
Clearly this will not work in all cases, but it goes pretty far,
in my experience.
Edward
Excerpts from Andreas Abel's message of Wed Jul 10 00:47:48 -0700 2013:
> Hi Oleg,
>
> just now I wrote a message to haskell-prime at haskell.org to propose a
> non-recursive let. Unfortunately, the default let is recursive, so we
> only have names like let' for it. I also mentioned the ugly workaround
> (<- return $) that I was shocked to see the first time, but use myself
> sometimes now.
>
> Cheers,
> Andreas
>
> On 10.07.2013 09:34, oleg at okmij.org wrote:
> > Andreas wrote:
> >> The greater evil is that Haskell does not have a non-recursive let.
> >> This is source of many non-termination bugs, including this one here.
> >> let should be non-recursive by default, and for recursion we could have
> >> the good old "let rec".
> >
> > Hear, hear! In OCaml, I can (and often do) write
> >
> > let (x,s) = foo 1 [] in
> > let (y,s) = bar x s in
> > let (z,s) = baz x y s in ...
> >
> > In Haskell I'll have to uniquely number the s's:
> >
> > let (x,s1) = foo 1 [] in
> > let (y,s2) = bar x s1 in
> > let (z,s3) = baz x y s2 in ...
> >
> > and re-number them if I insert a new statement. BASIC comes to mind. I
> > tried to lobby Simon Peyton-Jones for the non-recursive let a couple
> > of years ago. He said, write a proposal. It's still being
> > written... Perhaps you might want to write it now.
> >
> > In the meanwhile, there is a very ugly workaround:
> >
> > test = runIdentity $ do
> > (x,s) <- return $ foo 1 []
> > (y,s) <- return $ bar x s
> > (z,s) <- return $ baz x y s
> > return (z,s)
> >
> > After all, bind is non-recursive let.
> >
> >
> >
>
More information about the Haskell-Cafe
mailing list