Haskell 多参数类型类和非法实例声明
我制作了一个版本的敞篷车,如下所示:Haskell 多参数类型类和非法实例声明,haskell,typeclass,Haskell,Typeclass,我制作了一个版本的敞篷车,如下所示: class Convertible a b where convert :: a -> b instance (Convertible a b, Functor f) => Convertible (f a) (f b) where convert = fmap convert 然而,如果我想将两个转换串在一起,我就必须创建一个新实例,这让我感到很恼火。因此,我尝试添加以下内容: instance (Convertible a b,
class Convertible a b where
convert :: a -> b
instance (Convertible a b, Functor f) => Convertible (f a) (f b) where
convert = fmap convert
然而,如果我想将两个转换串在一起,我就必须创建一个新实例,这让我感到很恼火。因此,我尝试添加以下内容:
instance (Convertible a b, Convertible b c) => Convertible a c where
convert = convert . convert
编译器对此表示不满:
Variable ‘b’ occurs more often than in the instance head
in the constraint: Convertible a b
(Use UndecidableInstances to permit this)
In the instance declaration for ‘Convertible a c’
Variable ‘b’ occurs more often than in the instance head
in the constraint: Convertible b c
(Use UndecidableInstances to permit this)
In the instance declaration for ‘Convertible a c’
在这一点上,我理解了编译器为什么对我抱怨,我真的不想打开不可判定的实例。按照我目前设置实例的方式,每个a只有一个可转换a b实例。我希望添加函数依赖项a->b可以缓解这种情况,但现在编译器正在抱怨functor实例:
Illegal instance declaration for ‘Convertible (f a) (f b)’
The coverage condition fails in class ‘Convertible’
for functional dependency: ‘a -> b’
Reason: lhs type ‘f a’ does not determine rhs type ‘f b’
Using UndecidableInstances might help
In the instance declaration for ‘Convertible (f a) (f b)’
你有没有想过如何让它工作?或者,如果有必要,可能是更好的设计?我在想,我可能只能满足于明确说明转换的路径。我认为这需要
不可判定的实例
:
instance (Convertible a b, Convertible b c) => Convertible a c where
给定a
,由于函数依赖性,我们可以计算ab
。但是,不能保证这样的b
比a
小/简单!例如,b~[[a]]
,在这种情况下,我们将检查可转换a c
的问题简化为检查可转换a c
。这很容易导致在实例搜索期间不终止,因为类参数没有减少
相关说明:如果满足函数依赖性,则只有一种类型b
可以转换为a
。在这种情况下,为什么需要及物性?没有任何其他a
可以转换为。换句话说,在及物性的情况下,你需要有c~b
,或者你会让a
同时决定b
和c
,违反函数依赖关系。(我猜您毕竟并不真正想要函数依赖关系。)
不相关的注意事项:还要注意实例重叠——上面的实例看起来相当麻烦。您可能还必须使用
重叠实例
和/或不连贯性
,这两种情况都会导致头痛。虽然这不太可能帮助您完成您想做的事情,但您绝对应该阅读Breitner等人的《绝对不连贯》。只要你必须应用两次及物性,GHC就会宣布不连贯,而这肯定不是造成这场混乱的唯一原因。这就是GHC的强制机制需要使用自己的专门实例创建机制的原因之一,这与通常的机制完全不同。