类别101:GHC太“渴望”派生实例?

时间:2015-07-23 14:38:33

标签: haskell instances

给出以下代码:

class C a where
  foo :: a -> a

f :: (C a) => a -> a
f = id

p :: (C a) => (a -> a) -> a -> a
p g = foo . g

现在,如果我尝试调用p f,GHC会抱怨:

> p f
No instance for (C a0) arising from a use of `p'
In the expression: p f
In an equation for `it': it = p f

我发现有点令人惊讶,因为f只接受一个必须是类型类C的实例的“a”。这是什么原因?

编辑:我知道我没有为C定义任何实例,但不应该是“正确的”响应:

p f :: (C a) => a -> a 

2 个答案:

答案 0 :(得分:8)

当你将一个简单的表达式放入ghci时,它基本上是试图print,所以

> p f

与在文件中具有以下内容大致相同

main :: IO ()
main = print $ p f

正如您所指出的,p f :: (C a) => a -> a。为了print $ p f GHC需要评估p f。 GHC无法在不选择要传入的字典的情况下使用类型类上下文来评估值。为此,它需要为所有C a找到一个a实例,它不会退出。它还需要为Show找到a -> a个实例。无法找到这两种结果导致两个错误

No instance for (Show (a -> a)) arising from a use of `print'
No instance for (C a) arising from a use of `p'

答案 1 :(得分:4)

这是可怕的monomorphism restriction。默认情况下,如果推断类型具有类约束,GHC不允许我们具有没有类型注释的顶级值定义。

可以解决问题

a。)通过在源代码顶部添加{-# LANGUAGE NoMonomorphismRestriction #-}来关闭限制。

b。)向受影响的顶级绑定添加类型注释:

foo :: C a => a -> a
foo = p f

c。)扩展功能定义(如果可能):

foo x = p f x