以下行按预期工作,但我有点担心原因:
getLine >>= \x-> getLine >>= \y-> return [x, y]
考虑添加括号来定义lambda表达式:
getLine >>= (\x-> getLine) >>= (\y-> return [x, y])
第二行是错误的,因为x
在return
中使用时不在范围内,我很满意。我担心的是,在第一行中,x
的范围似乎已经“泄露”了。
这种'泄漏'被认为是不好的做法吗?我很困惑它是如何保持在范围内而不是在\x -> getLine
表达后立即丢失。
答案 0 :(得分:14)
如果根据haskell的优先规则正确地为第一行加上括号,则得到:
getLine >>= (\x-> getLine >>= (\y-> return [x, y]))
这很明显第二个lambda在第一个lambda中,因此访问第一个lambda的变量没有问题。
答案 1 :(得分:12)
你的括号根本就是错误的。正确的括号是
getLine >>= (\x -> getLine >>= (\y -> return [x, y]))
因此,x
当然是在身体中定义的。
请注意,此功能特别有用,因为您可以格式化以下代码:
getLine >>= \x ->
getLine >>= \y ->
return [x, y]
几乎是
do
x <- getLine
y <- getLine
return [x, y]
但没有任何特殊语法。
答案 2 :(得分:2)
Haskell语法遵循“最大munch”规则:每个语法元素尽可能地扩展,直到进一步扩展它会导致错误。由于它可以很好地将“\x ->
”的范围一直扩展到最终,这就是它的作用。
答案 3 :(得分:1)
x
表达式中对return
的引用称为closure。这是函数式编程语言的典型特征。在像Haskell这样的纯函数式编程语言中,没有理由担心。这是一个非常好的功能。在“混合”函数式编程语言中,如F#(和C#这些天),闭包确实会导致意外行为。