【发布时间】:2017-02-05 15:40:36
【问题描述】:
我有以下代码。 Class1 实例说明一个类的直接超类是什么,SuperClass1 自动遍历 Class1 以查找所有超类。 (我省略了这些类的实际方法,因为它们与我的问题无关。)
{-# LANGUAGE PolyKinds, RankNTypes, ConstraintKinds, FlexibleInstances, UndecidableInstances, MultiParamTypeClasses, FunctionalDependencies #-}
class Class1 b h | h -> b
instance Class1 Functor Applicative
instance Class1 Applicative Monad
class SuperClass1 b h
instance {-# OVERLAPPING #-} SuperClass1 b b
instance {-# OVERLAPPABLE #-} (SuperClass1 b c, Class1 c h) => SuperClass1 b h
这很好用!现在我想这样使用它:
newtype HFree c f a = HFree { runHFree :: forall g. c g => (forall b. f b -> g b) -> g a }
instance SuperClass1 Functor c => Functor (HFree c f)
instance SuperClass1 Applicative c => Applicative (HFree c f)
instance SuperClass1 Monad c => Monad (HFree c f)
test :: (a -> b) -> HFree Monad f a -> HFree Monad f b
test = fmap
(即,只要Functor 是c 的超类,我就可以为Hfree c f 提供Functor 的实例。)
这会在 Applicative 实例中产生此错误(对于 Monad 实例也是如此):
• Overlapping instances for SuperClass1 Functor c1
arising from the superclasses of an instance declaration
Matching instances:
instance [overlappable] forall k k k (b :: k) (c :: k) (h :: k).
(SuperClass1 b c, Class1 c h) =>
SuperClass1 b h
-- Defined at superclass.hs:17:31
instance [overlapping] forall k (b :: k). SuperClass1 b b
-- Defined at superclass.hs:16:30
(The choice depends on the instantiation of ‘c1, k1’
To pick the first instance above, use IncoherentInstances
when compiling the other instance declarations)
• In the instance declaration for ‘Applicative (HFree c f)’
据我了解,Applicative 实例需要 Functor 实例,因此 Applicative 实例还需要来自 Functor 的 SuperClass1 Functor c 约束。事实上,如果我添加这个,错误就会消失。 (这是我目前拥有的:http://hackage.haskell.org/package/free-functors-0.7/docs/Data-Functor-HFree.html)
但不知何故,GHC 足够聪明,可以理解SuperClass1 Applicative c 隐含SuperClass1 Functor c,因为它不会抱怨缺少约束。相反,它会卡在重叠实例错误上。如果有办法修复错误,那就太好了,但我不知道如何解决!
【问题讨论】:
-
该错误与
test无关 -Monad和Applicative实例因重叠错误而失败,因为您的实例重叠严重。编译器在这里能够解决的SuperClass1 a b形式的唯一约束是SuperClass1 a a- 也就是说,当类型是先验已知的相同时。在所有其他情况下,它会给你一个错误。 (另请注意,当c成立时,GHC 甚至不知道SuperClass1 Functor c暗示Functor- 就它而言,SuperClass1实际上不包含任何信息) -
不确定它是否与您的要求有关,但将其作为 Prolog 阅读,
(SuperClass1 b c, Class1 c h) => SuperClass1 b h应该是(Class1 c h, SuperClass1 b c) => SuperClass1 b h。看看这是否改变了什么。在这里黑暗中拍摄。 :)
标签: haskell types monads overlapping-instances