Reputation: 17968
The following line works as expected, but I am a little concerned why:
getLine >>= \x-> getLine >>= \y-> return [x, y]
Consider the addition of parenthesis to scope the lambda expressions:
getLine >>= (\x-> getLine) >>= (\y-> return [x, y])
The second line is errorneous because x
is not in scope when used in the return
, and I am happy with this. What concerns me this that in the first line the scope of x
appears to have 'leaked' out.
Is this 'leaking' considered bad practice? I am confused as to how it has remained in scope and not been lost immediately after the \x -> getLine
expression.
Upvotes: 4
Views: 1635
Reputation: 5117
Haskell syntax follows the "maximal munch" rule: each syntax elements extends as far as it possibly can until extending it any further would result in an error. Since it works fine to extend the scope of the "\x ->
" all the way to the end, that's what it does.
Upvotes: 2
Reputation: 49218
You parentheses are simply set wrong. The correct parentheses are
getLine >>= (\x -> getLine >>= (\y -> return [x, y]))
And therefore, x
is of course defined in the body.
Note that this feature is particularly useful since you can format code like this:
getLine >>= \x ->
getLine >>= \y ->
return [x, y]
which is almost
do
x <- getLine
y <- getLine
return [x, y]
but without any special syntax.
Upvotes: 12
Reputation: 12077
The reference to x
in the return
expression is known as a closure. It's a typical feature of functional programming languages. In a pure functional programming language, like Haskell, there is no cause for concern. It's a very nice feature. In 'hybrid' functional programming languages like F# (and C# these days), closures can indeed result in unexpected behavior sometimes.
Upvotes: 1
Reputation: 370367
If you parenthesize your first line correctly according to haskell's precedence rules, you get:
getLine >>= (\x-> getLine >>= (\y-> return [x, y]))
This makes it obvious that the second lambda is inside the first, so there's no problem with it accessing the variables of the first lambda.
Upvotes: 13