从特定类型泛化为 GADT 中的 class
Generalizing from a specific type to a class in a GADT
我有以下定义
{-# LANGUAGE GADTs, TypeInType, RankNTypes #-}
import Data.Kind
class Character (a :: * -> *) where
showVal :: a b -> b -> String
data ExampleCharacter a where
Variable :: ExampleCharacter String
EqualSign :: ExampleCharacter ()
Deref :: ExampleCharacter ()
instance Character ExampleCharacter where
showVal Variable = id
showVal EqualSign = const "="
showVal Deref = const "*"
data Symbol :: forall a. ExampleCharacter a -> * where
Terminal :: a -> Symbol (b :: ExampleCharacter a)
如您所见,我定义了一个在类型签名中使用 ExampleCharacters 的 Symbol class。示例用法是 let sym = Terminal "xyy" :: Symbol Variable
创建名称为 "xyy"
.
的变量符号
现在,显而易见的下一步是将 ExampleCharacter
推广到 Character c
。我尝试了以下方法:
data Symbol :: (forall c (a :: *). Character c) => c a -> * where
Terminal :: a -> Symbol (b :: c a)
但我收到以下错误:
main.hs:22:20: error:
• Illegal constraint in a type: forall (c :: * -> *) a. Character c
• In the type ‘Symbol (b :: c a)’
In the definition of data constructor ‘Terminal’
In the data declaration for ‘Symbol’
我不太确定这个错误想告诉我什么。为什么 forall (c :: * -> *) a. Character c
是非法约束,怎么会这样?有什么解决办法吗?
来自docs:
As kinds and types are the same, kinds can now (with -XTypeInType)
contain type constraints. Only equality constraints are currently
supported, however. We expect this to extend to other constraints in
the future.
所以原则上你写的是合理的;它根本不受支持(截至撰写本文时,最新的 GHC 是 8.2.2)。
我有以下定义
{-# LANGUAGE GADTs, TypeInType, RankNTypes #-}
import Data.Kind
class Character (a :: * -> *) where
showVal :: a b -> b -> String
data ExampleCharacter a where
Variable :: ExampleCharacter String
EqualSign :: ExampleCharacter ()
Deref :: ExampleCharacter ()
instance Character ExampleCharacter where
showVal Variable = id
showVal EqualSign = const "="
showVal Deref = const "*"
data Symbol :: forall a. ExampleCharacter a -> * where
Terminal :: a -> Symbol (b :: ExampleCharacter a)
如您所见,我定义了一个在类型签名中使用 ExampleCharacters 的 Symbol class。示例用法是 let sym = Terminal "xyy" :: Symbol Variable
创建名称为 "xyy"
.
现在,显而易见的下一步是将 ExampleCharacter
推广到 Character c
。我尝试了以下方法:
data Symbol :: (forall c (a :: *). Character c) => c a -> * where
Terminal :: a -> Symbol (b :: c a)
但我收到以下错误:
main.hs:22:20: error:
• Illegal constraint in a type: forall (c :: * -> *) a. Character c
• In the type ‘Symbol (b :: c a)’
In the definition of data constructor ‘Terminal’
In the data declaration for ‘Symbol’
我不太确定这个错误想告诉我什么。为什么 forall (c :: * -> *) a. Character c
是非法约束,怎么会这样?有什么解决办法吗?
来自docs:
As kinds and types are the same, kinds can now (with -XTypeInType) contain type constraints. Only equality constraints are currently supported, however. We expect this to extend to other constraints in the future.
所以原则上你写的是合理的;它根本不受支持(截至撰写本文时,最新的 GHC 是 8.2.2)。