{-# LANGUAGE MultiParamTypeClasses #-}
class Coerce a b where coerce :: a -> b
instance Coerce a a where coerce a = a现在,这将无法工作:coerce 0 :: Int,但是如果实例被替换为此,则表达式工作:
instance a ~ b => Coerce a b where coerce x = x为什么?
发布于 2014-07-03 10:09:23
我可以告诉你为什么第一个不起作用。
可以为任何可能的类型定义Coerce。coerce 0 :: Int被解析为(coerce 0) :: Int。因此,您已经用类型注释来修复coerce :: a -> 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的任何可能调用(因此您不能编写任何其他不重叠的实例)。只有在选择实例之后才应用a ~ b约束。
因为您有一个与任何内容匹配的实例,所以为coerce 0 :: Int选择一个实例是没有问题的,尽管我们仍然存在不知道0是什么类型的问题。但是在实例选择之后,我们现在有了附加的约束a ~ Int,它允许为所有事物分配明确的类型。
https://stackoverflow.com/questions/24550088
复制相似问题