来自导入GHC.TypeLits的SingI类实例

时间:2013-09-17 12:38:56

标签: 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) => 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 a),很明显它是类型同义词的东西,但我找不到任何解释。很高兴听到它为什么会这样,并且有没有机会添加一些标签之王来输入同义词?

扩展,用于编译:

  DataKinds,
  KindSignatures,
  TypeSynonymInstances,
  ScopedTypeVariables,
  -- MultiParamTypeClasses,
  UndecidableInstances

1 个答案:

答案 0 :(得分:1)

来自GHC用户指南的7.6.3.1. Relaxed rules for the instance head部分:

  

使用-XTypeSynonymInstances标志,实例头可以使用类型同义词。与往常一样,使用类型同义词是只是写入类型同义词定义的RHS 的简写。

将此规则应用于您的实例声明会导致:

instance (SingI a, SingI b, SingI c) => AC (A a) where
  af = (fromSing (sing :: Sing c), A)

请注意,这与您为“A”编写的实例相同,但在cb上有约束,现在甚至不会出现在实例头中。当您尝试使用实例时:

print $ fst $ (af :: (String, B "a" "b" "c")) 

转变为

print $ fst $ (af :: (String, A "a"))

编译器抱怨没有instance for SingI Symbol c,因为它不知道c是什么。要编译此代码,您必须提供一个instance SingI (c :: Symbol),它对所有c 起作用(您可以使用FlexibleInstances编写这样的实例,但它不会是很有用,因为你无法根据c做出选择。如果您不想要此行为,则可以使用newtype。