[Haskell-cafe] let and fixed point operator
Brent Yorgey
byorgey at gmail.com
Thu Aug 30 12:37:19 EDT 2007
On 8/30/07, Peter Hercek <peter at syncad.com> wrote:
>
> Hi,
>
> I find the feature that the construct "let x = f x in expr"
> assigns fixed point of f to x annoying. The reason is that
> I can not simply chain mofifications a variable like e.g. this:
>
> f x =
> let x = x * scale in
> let x = x + transform in
> g x
>
> When one is lucky then it results in a compile error; in worse
> cases it results in stack overflow in runtime. The annoying
> part is figuring out new and new variable names for essentially
> the same thing to avoid the search/evaluation of the fixed point.
>
> I suppose Haskell was designed so that it makes sense. The only
> usage I can see is like this:
>
> let fact = \x -> if x == 0 then 1 else x * fact (x-1) in
>
> ... but that is not any shorter than:
>
> let fact x = if x == 0 then 1 else x * fact (x-1) in
>
> So the question is what am I missing? Any nice use cases where
> fixed point search is so good that it is worth the trouble with
> figuring out new and new variable names for essentially the same
> stuff?
>
> Peter.
This is not really about fix points, it is about the very essence of
functional programming. You cannot "modify" variables in the way you are
suggesting; a variable such as x must *always refer to the same thing*
within a given scope. This is not a liability, but rather a very nice
thing: it makes it much easier to reason about programs if a given name
always refers to the same thing. In an imperative language, where you
really can modify the contents of variables, you do not have this
guarantee. The same variable could refer to different values at different
points in the program, which can lead to much confusion.
Now, I do understand your annoyance; it certainly is annoying to type
something like
f x =
let y = x * scale in
let z = y + transform in
g z
where you have to come up with a bunch of different names for the
intermediate values. But it's actually possible to do this in a much nicer
way which is idiomatic in a functional language such as Haskell. Note that
what you are really doing here is sending x through a "pipeline" of
functions which transform it into another value. The way to combine
functions into a pipeline is by using function concatenation:
f = g . (+ transform) . (* scale)
This is exactly the same thing, but no annoying intermediate names in
sight! This simply says that f is the function you get when you first
multiply by scale, then add transform, then finally apply function g. If
you don't like the "point-free" style, you could also write something like
f x = g $ (+ transform) $ (* scale) $ x
(The $ simply lets you avoid writing lots of parentheses.)
Hope this helps,
-Brent
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070830/8afef084/attachment-0001.htm
More information about the Haskell-Cafe
mailing list