我有一个类型类,它引入了两种类型之间的函数依赖:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
{-# LANGUAGE GADTs, StandaloneDeriving, UndecidableInstances #-}
class Eq c => Classifiable t c | t -> c where
classification :: t -> c
我有很多这类课程,例如对于对,我们使用该对的“分类”是存储在第一个位置的值:
instance Eq a => Classifiable (a,b) a where
classification = fst
我还有一个使用此类的类型,允许它在其arguemnts中配置类型c
时存储类型为t
的实例,即c
是存在限定的,但是它受到函数依赖的约束,只有一个实际可能的类型由一个可见参数唯一确定,在本例中为t
:
data Symbol t nt s where
Terminal :: (Classifiable t c, Show c, Ord c) =>
c -> Symbol t nt s
NonTerminal :: Classifiable t c =>
nt -> [Production t nt s] -> Symbol t nt s
我的问题是,当我尝试使用它时,GHC显然不知道对于任何具有给定参数的Symbol
对,如果c
,则t
类型必须相同是。因此,如果我尝试为此类型创建Ord
的实例:
deriving instance (Ord c, Ord nt, Classifiable t c) => Ord (Symbol t nt s)
我收到以下错误:
Could not deduce (Eq (Symbol t nt s))
arising from the superclasses of an instance declaration
from the context (Ord c, Ord nt, Classifiable t c)
bound by the instance declaration
at src\Text\Parser\ALLStar.hs:16:1-76
In the instance declaration for `Ord (Symbol t nt s)'
C:\development\haskell\delta-parser-git\delta-parser\src\Text\Parser\ALLStar.hs: 16, 1
Couldn't match expected type `c1' with actual type `c2'
`c2' is a rigid type variable bound by
a pattern with constructor
Terminal :: forall t nt s c.
(Classifiable t c, Show c, Ord c) =>
c -> Symbol t nt s,
in a case alternative
at src\Text\Parser\ALLStar.hs:16:1
`c1' is a rigid type variable bound by
a pattern with constructor
Terminal :: forall t nt s c.
(Classifiable t c, Show c, Ord c) =>
c -> Symbol t nt s,
in a case alternative
at src\Text\Parser\ALLStar.hs:16:1
Relevant bindings include
b1 :: c2 (bound at src\Text\Parser\ALLStar.hs:16:1)
a1 :: c1 (bound at src\Text\Parser\ALLStar.hs:16:1)
In the second argument of `compare', namely `b1'
In the expression: (a1 `compare` b1)
When typechecking the code for `compare'
in a derived instance for `Ord (Symbol t nt s)':
To see the code I am typechecking, use -ddump-deriv
如何说服编译器理解功能依赖需要两个c
绑定是相同的类型?