Haskell如何知道你指的是哪个类型类实例?

时间:2009-05-03 16:47:15

标签: haskell type-inference typeclass

在阅读关于应用函子的优秀的学习你的哈斯克尔的新章节时,出现了这个问题。

Applicative类型作为Maybe实例的定义的一部分:

pure = Just

如果我只是去GHCi并导入Control.Applicative,并执行:

pure (3+)

我没有得到任何东西(有道理)。但如果我在表达式的一部分中使用它:

pure (3+) <*> Just 4

我得到的只是7.我想这也就不足为奇了,但是我错过了关于类型类如何工作的不可或缺的一点,我认为,这里对pure的调用没有任何歧义。

如果我的困惑有道理,任何人都能解释一下详细情况吗?

4 个答案:

答案 0 :(得分:7)

这只是类型推断。 (<*>)运算符要求两个参数都使用相同的Applicative实例。右侧是Maybe,因此左侧也必须是Maybe。这就是它如何确定这里使用的实例。您可以通过键入:t expression来查看解释器中任何表达式的类型,也许如果您只是浏览每个子表达式并查看推断出的类型,您将更好地了解正在发生的事情。< / p>

答案 1 :(得分:3)

值得查看编译器推断pure (3+)的类型:

Prelude Control.Applicative> :t pure (3+)
pure (3+) :: (Num a, Applicative f) => f (a -> a)

此术语的类型已重载,关于数字类和应用类的决定会延迟到稍后。但您可以使用注释强制特定类型,例如:

*Showfun Control.Applicative> pure (3+) :: Maybe (Double -> Double)
Just <function>

(这是有效的,因为Showfun有一个实例声明,可以将函数值打印为<function>。)

这只是编译器何时积累了足够的信息才能做出决定的问题。

答案 2 :(得分:2)

为了扩展newacct的答案,如果没有足够的信息来推断实际类型,编译器可能(在某些情况下)尝试选择默认类型,仅限于满足相关类型约束的类型。在这种情况下,对于某些难以确定的Num =&gt;的实例,推断的类型是IO(n - > n)。 ñ。然后GHCi对其进行评估并抛弃返回值,但没有明显效果。

答案 3 :(得分:1)

这是一个有趣的SO thread on type inference。不是特定的Haskell,而是很多关于函数式语言中类型推断的好链接和东西。