IO定义变量的范围
我发现在 Haskell 中进行 IO 时,使用 <-
运算符分配的变量仅在紧随其后的语句的范围内 - 而不是在 where
子句中。
例如:
main :: IO()
main = do
s <- getLine
putStr magic
where
magic = doMagic s
这将不起作用,因为 s
不在范围内。我做了一些研究来证实这一点,并发现这篇文章:
与
let
表达式中变量的作用域涵盖所有定义不同,<-
定义的变量仅在以下语句的作用域内。
那么如何才能使 s
可在 where
子句中使用呢?
I've discovered that when doing IO in Haskell, variables that are assigned using the <-
operator are only in scope for the statements immediately after them - not in where
clauses.
For example:
main :: IO()
main = do
s <- getLine
putStr magic
where
magic = doMagic s
This won't work as s
is not in scope. I did some research to confirm it and found this article:
Unlike a
let
expression where variables are scoped over all definitions, the variables defined by<-
are only in scope in the following statements.
So how can I make s
available for use in the where
clause?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除了一般的 let 形式之外,还有一种特殊的 let 形式可以与 do 语法一起使用,您可以使用它来代替:
magic
在块中的所有以下行中都可用。In addition to the general let form, there's a special let form for use with do syntax you can use instead:
magic
is available in all following lines in the block.嗯,
magic
是一个函数。因此,您可以执行以下操作:或者:
并像这样调用它:
当然,正如您已经研究过的那样,当您可以重用计算的
magic
时,明智的做法是使用let ... 在
表达式中,并嵌套调用:Well,
magic
is a function. Therefore you can do something like:Or:
And call it like so:
Of course, as you already researched, the sensible thing to do when you can reuse your computed
magic
is to use alet ... in
expression, and nest the calls:let
是处理这个问题的实用方法。但也许值得了解一下这里到底发生了什么。do
语句并不是导致范围界定问题的原因。请记住,这
相当于:
如果我们放入一些括号,则为:
这就是
s
的作用域的来源:它是 lambda 表达式的参数,并且仅存在于该 lambda 表达式中。尝试在该 lambda 之外的where
子句中使用它,您会收到“不在范围内”错误。let
之所以有效,是因为let
和where
解析方式不同。为了清楚起见,用括号表示:这就是导致问题的原因;它不是特定于 IO 或
do
语句。let
is the practical way to handle this. But it may be worth unpacking what's really going on here. Thedo
statement isn't what's causing the scoping trouble.Remember that
is equivalent to this:
If we put in some parentheses, this is:
This is where the scope of
s
comes from: it's the argument to a lambda expression, and it only exists within that lambda expression. Try to use it in awhere
clause outside of that lambda, and you get a "not in scope" error.let
works becauselet
andwhere
parse differently. With parentheses for clarity:This is what's causing the problem; it's not specific to IO, or to
do
statements.