
On 8/30/07, Peter Hercek
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