【问题标题】:Using variable from outer scope in where in do block [duplicate]在do块中使用外部范围的变量[重复]
【发布时间】:2020-07-31 09:04:02
【问题描述】:

我正在尝试使用wheredo 块中定义的操作中使用外部范围中定义的变量:

module Main where

main :: IO ()
main = do
    outerVar <- return "a"
    doSomething
    where
        doSomething :: IO String
        doSomething = putStrLn ("outerVar: " ++ outerVar)

鉴于这个 sn-p,我试图理解为什么编译器会返回以下错误:

error: Variable not in scope: outerVar :: [Char]
  |
9 |         doSomething = putStrLn ("outerVar: " ++ outerVar)
  |

根据我的理解 - doSomething 函数应该创建某种“闭包”来包含 outerVar 的值(我刚刚发现它被称为 free variable),但这并不发生。

我花了很多时间试图弄清楚为什么会发生这个错误。我很尴尬,即使对于作为 Haskell 新手的我来说,这似乎是一个应该很明显的基本概念,但事实并非如此——希望我错了。搜索“在哪里做块范围”、“在哪里关闭”或类似关键字时,我找不到任何答案。比较letwhereThis page 没有提到我的情况,我发现的最接近的例子是here 的第一段代码,其中涵盖了“Lambda 提升”主题。他们能够在where 中定义的函数内使用外部作用域的n 变量,但它不像我的情况那样在do 块中。

所以我的问题是 - 为什么 outerVar 变量不在 doSomething 的范围内?

【问题讨论】:

  • 是的,这完全是同一个问题。谢谢!我不知道为什么我之前找不到这个问题...
  • (我重新打开了这个问题,然后立即意识到没有必要这样做。对不起,不必要的 ping!)

标签: haskell scope where-clause do-notation


【解决方案1】:

do 块只是使用&gt;&gt;= 和 lambda 函数链接一元值的语法糖。您的块首先由编译器翻译成:

return "a" >>= \outerVar -> doSomething
  where doSomething =...

现在应该很明显,outerVar 不在作为参数的 lambda 范围之外。

【讨论】:

  • 谢谢!我不小心重复的问题的答案中缺少这部分解释。现在更清楚了。
猜你喜欢
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 2013-05-10
  • 2021-08-18
  • 2020-03-11
  • 1970-01-01
相关资源
最近更新 更多