[Haskell-beginners] Re: Non-recursive binding expression

Brent Yorgey byorgey at seas.upenn.edu
Sat Feb 28 13:01:56 EST 2009


On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote:
>  <j.romildo <at> gmail.com> writes:
> 
> > 
> > Hello.
> > 
> > Is there any non-recursive binding expression in Haskell?
> > 
> > Something that would allow me to write, for instance,
> > 
> >   test = let' xs = [] in
> >          let' xs = 3 : xs in
> >          let' xs = 8 : xs in
> >          let' xs = 7 : xs in
> >          xs
> 
> Well, it's not a nice thing to do (probably), but you can write
> 
> test = head $ 
>   do xs <- [ [] ]
>      xs <- [ 3:xs ]
>      xs <- [ 8:xs ]
>      xs <- [ 7:xs ]
>      return xs
> 

The correct answer is no.  Life is pain.  Anyone who says otherwise is
selling something. ;)

Assignment in Haskell is not destructive update---it assigns a name to
a value, and they become one flesh, until parted by death (i.e. the
end of their lexical scope).  The only reason Will's code works is
that each line creates a new lexical scope, and each xs shadows the
previous one.

To do what you want, you have to give each thing a new name, something
like this:

test = let xs = []
           xs' = 3 : xs
	   xs'' = 8 : xs'
	   xs''' = 7 : xs''
       in xs'''

"But this is horribly painful!" you cry.  Of course it is!  Giving
names to things you don't want to keep is always painful (like when
your child names the almost-dead raccoon you find in the street, which
is just going to die or be given to an animal shelter anyway).

So, why not just avoid naming things you don't want?

test = (7:) . (8:) . (3:) $ []

Ah, that's better!  We just thread some intermediate values through a
chain of composed functions.  Each function does its little bit of
modification and passes the intermediate value along to the next
function, and the intermediate values are never given names.

-Brent


More information about the Beginners mailing list