【发布时间】:2020-01-10 17:17:01
【问题描述】:
我正在通过learnyouahaskell.com 学习 Haskell,并想在完成输入/输出模块之前测试一些概念。不过,尽管这看起来很简单,但我无法通过谷歌搜索或兜售我的方法。
当我尝试运行以下代码时
getName = do
name <- getLine
return name
getName 的输出变为IO String 类型的元素,而不是String,即使名称肯定是String
通过阅读文档和其他 StackVverflow 的问题,我无法弄清楚为什么当我将 getName 声明为函数时会发生这种情况(当我直接在 main 上使用绑定
【问题讨论】:
-
因为
return的类型为Monad m => a -> m a。您不能从IO中“解包”一个值。您可以将IO视为制作String的“配方”,这与字符串不同。 -
如果您有命令式语言的背景,请注意 Haskell 中的
return与那些语言中的return非常不同。return是 Haskell 中的一个函数,在本例中是一个类型为String -> IO String的函数。 -
我明白了。非常感谢,伙计们。我完全忽略了
return在这种情况下的工作原理。 -
如果你进一步阅读 LYAH,你会发现所有这些都得到了解释(在 Monads 的章节中)。 Haskell 中的 IO 和 do 表示法,当第一次遇到“这就是你在 Haskell 中执行 IO 的方式”时,总是看起来有点“神奇”,这些问题是非常自然的。正如我所说,他们稍后会得到答复。
-
另外值得注意的是,
do {x<-foo; return x}与 monad laws 本身完全相同。所以你所有的代码真正要做的就是定义一个新名称getName = getLine。
标签: string haskell io bind monads