{-# LANGUAGE MultiParamTypeClasses #-}
class Coerce a b where coerce :: a -> b
instance Coerce a a where coerce a = a
现在,这不起作用:coerce 0 :: Int
但是如果实例替换为this,则表达式可以工作:
instance a ~ b => Coerce a b where coerce x = x
为什么?
答案 0 :(得分:10)
我可以告诉你为什么第一个没有工作。
可能会为任何类型的对定义 Coerce
。 coerce 0 :: Int
被解析为(coerce 0) :: Int
。因此,您已使用类型注释修复b
中的coerce :: a -> b
,而不修复a
。
数字文字是多态的,因此0
的类型为Num a => a
。那不行;没有匹配Coerce a Int
的实例。可能有Coerce Double Int
,Coerce Complex Int
等,因此知道b
为Int
并不足以推断0
是Int
}。我们需要说coerce (0 :: Int) :: Int
来修复这两个类型参数。
我相信第二个可行,因为实例声明的约束不用于帮助解析类型类。 instance a ~ b => Coerce a b
与您编写instance Coerce a b
完全匹配。即这是最常见的实例(用于类型类解析),它可以很好地匹配对coerce
的任何可能调用(因此您不能编写任何其他非重叠实例)。 {/ 1}}约束仅在选择实例后才会应用。
由于您有一个匹配任何内容的实例,因此选择a ~ b
的实例没有问题,即使我们仍然遇到不知道coerce 0 :: Int
的类型的问题。但是在实例选择之后,我们现在有了额外的约束0
,它允许将明确的类型分配给所有内容。