5

return "abc"在 ghci 中打印时的类型是什么?

问题的关键在于它在单子中是多态的:

ghci> :t return "abc"
return "abc" :: (Monad m) => m [Char]

打印的内容取决于选择了哪个 monad:

ghci> return "abc" :: Maybe String
Just "abc"

ghci> return "abc" :: [] String
["abc"]

但这是实际打印的内容:

ghci> return "abc"
"abc"
4

2 回答 2

7

当您在 GHCi 中键入表达式时expr,会发生以下情况:

  • 表达式经过类型检查。如果出现错误,GHCi 会告诉您错误并放弃。
  • 否则,sayexpr被发现有 type t;GHC 尝试t匹配IO a.
  • 如果成功,则执行类似it <- expr, 然后 ifaShow且不是的实例(),则执行print it
  • 如果它失败了,并且t它本身是 的一个实例Show,GHCi 会执行类似于let it = exprthen的操作print it
  • 否则,它会抱怨。

本质上,您需要在 GHCi 提示符处运行 IO 操作并获取它们返回的值,以及使用纯值并查看您得到的值。这就是 GHCi 的行为方式的原因:如果您似乎正在使用 IO 操作,GHCi 会执行此操作,然后如果该操作的结果可以显示并且有趣(即不是()),那么它会显示结果给你。如果它无法向您显示结果,那没什么大不了的,因为您可能只是想运行 IO 操作;如果你想要结果,你会用<-. 另一方面,如果你的表达式看起来不是一个 IO 动作,GHCi 会计算它并显示给你,如果它不能显示,那么 GHCi 就不能做任何有用的事情(这次没有副作用) ,

在这种情况下,return "abc"类型检查为IO String, 并且String是 的一个实例Show,因此 GHCi 执行类似的操作

it <- return "abc"
print it

根据单子定律,这与做的完全一样

print "abc"

因此结果。

于 2012-08-13T17:25:21.383 回答
4

Haskell 有一套稍微令人费解的规则来决定涉及数字的表达式类型。您可以看到关于模糊类型和默认实例的报告部分。所以一般问题的答案很复杂。但是在 GHCi 中,如果你输入一个表达式e,你可以依靠这些规则来应用:

  • 如果表达式e可以被键入IO T为 some type T,并且如果T有一个Show实例,GHCi 将运行计算并打印 type 的结果值T。这就是您的第三个示例中发生的情况。

  • 如果表达式e *cannot* 可以在IOmonad 中输入,那么默认实例规则就会发挥作用,GHCi 将根据这些规则选择类型。如果该类型有一个Show实例,GHCi 将打印show e。这就是前两个示例中发生的情况:Maybe String并且[String]是带有Show实例的纯值。

    如果e的类型没有实例Show,那么 GHCi 会报错。如果您键入类似的表达式,就会发生这种情况flip take

于 2012-08-13T17:04:32.737 回答