Haskell 导入GHC.TypeLits中SingI类的实例
玩弄GHC.TypeLits我制作了这个代码Haskell 导入GHC.TypeLits中SingI类的实例,haskell,Haskell,玩弄GHC.TypeLits我制作了这个代码 data A (a :: Symbol) = A type B a (b :: Symbol) (c :: Symbol) = A a class AC a where af :: (String, a) -- instance SingI a => AC (A a) where -- af = (fromSing (sing :: Sing a), A) instance (SingI a, SingI b, SingI c)
data A (a :: Symbol) = A
type B a (b :: Symbol) (c :: Symbol) = A a
class AC a where
af :: (String, a)
-- instance SingI a => AC (A a) where
-- af = (fromSing (sing :: Sing a), A)
instance (SingI a, SingI b, SingI c) => AC (B a b c) where
af = (fromSing (sing :: Sing c), A)
如果我尝试在某个地方调用af时出现以下错误,则无法编译:
No instance for (SingI Symbol c) arising from a use of `af'
Possible fix: add an instance declaration for (SingI Symbol c)
In the second argument of `($)', namely
`(af :: (String, B "a" "b" "c"))'
In the second argument of `($)', namely
`fst $ (af :: (String, B "a" "b" "c"))'
In a stmt of a 'do' block:
print $ fst $ (af :: (String, B "a" "b" "c"))
对于instance SingI a=>AC(a)
它仍然可以正常工作。很明显,它与类型同义词有关,但我找不到对此的任何解释。我很高兴听到为什么它是这样工作的,有没有可能在类型同义词中添加一些标记之王
扩展,用于编译:
DataKinds,
KindSignatures,
TypeSynonymInstances,
ScopedTypeVariables,
-- MultiParamTypeClasses,
UndecidableInstances
从GHC用户指南,第节: 使用-XTypeSynonymInstances标志,实例头可以使用类型同义词。一如既往,使用类型同义词是编写类型同义词定义的RHS的简写 将此规则应用于实例声明将导致:
instance (SingI a, SingI b, SingI c) => AC (A a) where
af = (fromSing (sing :: Sing c), A)
请注意,这与您为“A”编写的实例相同,但对c
和b
有约束,现在这些约束甚至不会出现在实例头中。当您尝试使用该实例时:
print $ fst $ (af :: (String, B "a" "b" "c"))
这就转化为
print $ fst $ (af :: (String, A "a"))
编译器抱怨没有SingI符号c的
实例,因为它不知道c
是什么。要编译此代码,您必须提供一个适用于所有c语言的实例SingI(c::Symbol)
(您可以使用FlexibleInstances
编写这样的实例,但它不会有用,因为您无法根据c
进行选择)。如果不希望出现这种行为,可以使用新类型 来自GHC用户指南,章节:
使用-XTypeSynonymInstances标志,实例头可以使用类型同义词。一如既往,使用类型同义词是编写类型同义词定义的RHS的简写
将此规则应用于实例声明将导致:
instance (SingI a, SingI b, SingI c) => AC (A a) where
af = (fromSing (sing :: Sing c), A)
请注意,这与您为“A”编写的实例相同,但对c
和b
有约束,现在这些约束甚至不会出现在实例头中。当您尝试使用该实例时:
print $ fst $ (af :: (String, B "a" "b" "c"))
这就转化为
print $ fst $ (af :: (String, A "a"))
编译器抱怨没有SingI符号c的实例,因为它不知道c
是什么。要编译此代码,您必须提供一个适用于所有c语言的实例SingI(c::Symbol)
(您可以使用FlexibleInstances
编写这样的实例,但它不会有用,因为您无法根据c
进行选择)。如果不希望出现这种行为,可以使用新类型 谢谢,现在清楚了。我在这里使用同义词的唯一原因是为了保持与原始类型的兼容性,对于原始类型,我已经有一些类的实例,但希望向该类型添加一些附加信息。谢谢,现在已经清楚了。我在这里使用同义词的唯一原因是保持与原始类型的兼容性,对于原始类型,我已经有一些类的实例,但希望向该类型添加一些附加信息。