Haskell:将lambda表达式与bind函数一起使用时的变量范围

duk*_*ave 4 monads lambda haskell scope bind

以下行按预期工作,但我有点担心原因:

getLine >>= \x-> getLine >>= \y-> return [x, y]
Run Code Online (Sandbox Code Playgroud)

考虑添加括号来定义lambda表达式:

getLine >>= (\x-> getLine) >>= (\y-> return [x, y])
Run Code Online (Sandbox Code Playgroud)

第二行是错误的,因为x在使用时不在范围内return,我很满意.令我担心的是,在第一行中,范围x似乎已经"泄露"了.

这种'泄漏'被认为是不好的做法吗?我很困惑它是如何保持在范围内并且在\x -> getLine表达之后不会立即丢失.

sep*_*p2k 14

如果根据haskell的优先规则正确地将第一行括起来,则会得到:

getLine >>= (\x-> getLine >>= (\y-> return [x, y]))
Run Code Online (Sandbox Code Playgroud)

这很明显第二个lambda在第一个lambda中,因此访问第一个lambda的变量没有问题.


Dar*_*rio 12

你的括号只是设置错了.正确的括号是

getLine >>= (\x -> getLine >>= (\y -> return [x, y]))
Run Code Online (Sandbox Code Playgroud)

因此,x当然是在身体中定义的.

请注意,此功能特别有用,因为您可以像这样格式化代码:

getLine >>= \x ->
getLine >>= \y ->
return [x, y]
Run Code Online (Sandbox Code Playgroud)

这几乎是

do
  x <- getLine
  y <- getLine
  return [x, y]
Run Code Online (Sandbox Code Playgroud)

但没有任何特殊的语法.