此代码编译良好:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
type Res a s b :: *
instance Sel a s b where
type Res a s b = (s -> (b,s))
instance Sel a s (b->(c,a)) where
type Res a s (b->(c,a)) = (b -> s -> (c,s))
但是一旦我添加R谓词ghc失败:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
type Res a s b :: *
instance Sel a s b where
type Res a s b = (s -> (b,s))
class R a where
type Rec a :: *
cons :: a -> Rec a
elim :: Rec a -> a
instance Sel a s (b->(c,Rec a)) where
type Res a s (b->(c,Rec a)) = (b -> s -> (c,s))
抱怨:
Illegal type synonym family application in instance:
b -> (c, Rec a)
In the instance declaration for `Sel a s (b -> (c, Rec a))'
它是什么意思和(最重要的)我该如何解决它?
由于
答案 0 :(得分:12)
类型系列是单向的:您可以将Rec a
扩展为其计算类型,但不能(唯一地)从扩展回到Rec a
。这使得类型函数的应用程序不适合签名,因为它们永远不会触发实例应用。
您可以尝试改为:
instance Rec a ~ reca => Sel a s (b->(c,reca))
这意味着别的东西:它表示任何函数b -> (c, reca)
都是一个实例,然后当它不可撤销地匹配时,编译器会检查Rec a ~ reca
。但在你的情况下,这可能足够好了。
答案 1 :(得分:1)
Rec
不是类型构造函数;这是一种类型功能。也许你只能在类型定义的值类型中使用它,而不是在类声明中?我在这里疯狂地猜测;我不了解类型系列的所有规则。
我不知道如何修复它,但有些事情要尝试包括:
摆脱类Sel并定义type family Res a s b :: *
。使用type instance
代替类机制。
使用Rec
制作类型data
几乎不可能有所帮助,但我不这么认为。
缩减到可能有效的最少数量的语言扩展 - 这将使其他人更容易为您提供帮助,它也可能对编译器有所帮助。
答案 2 :(得分:1)
这意味着在声明类型实例时不允许使用类型同义词系列。请参阅GHC手册的"Type families and instance declarations"部分。
你可以解决它的唯一方法是重构,以便不需要它。