打印时选择什么类型的多态表达式?

时间:2012-08-13 16:22:37

标签: haskell ghci

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

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

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"

2 个答案:

答案 0 :(得分:7)

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

  • 表达式已经过类型检查。如果有错误,GHCi会告诉您错误并放弃。
  • 否则,发现expr的类型为t; GHC尝试将tIO a匹配。
  • 如果成功,则会执行类似it <- expr的内容,如果aShow的实例而不是(),则会执行print it
  • 如果失败,而t本身就是Show的实例,则GHCi执行类似let it = expr然后print it的操作。
  • 否则,它会抱怨。

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

在这种情况下,return "abc"类型检查IO StringStringShow的实例,因此GHCi执行类似

的操作
it <- return "abc"
print it

由monad定律与正好相同

print "abc"

因此结果。

答案 1 :(得分:4)

Haskell有一套令人困惑的规则来决定涉及数字的表达式类型;你可以看到Report section on ambiguous types and default instances。所以一般问题的答案很复杂。但是在GHCi中,如果您输入表达式 e ,您可以依赖这些规则来应用:

  • 如果表达式 e 可以为某些类型IO T键入T,并且TShow个实例,GHCi将运行计算并打印类型T的结果值。这就是你的第三个例子中发生的事情。

  • 如果无法在IO monad中输入 e *表达式,则默认实例规则将起作用,GHCi将根据这些规则选择类型规则。如果类型具有Show实例,GHCi将打印show e 。这就是前两个示例中的情况:Maybe String[String]是带有Show个实例的纯值。

    如果 e 的类型Show个实例,那么GHCi会抱怨。如果您键入flip take等表达式,则会发生这种情况。