问题
I have the following definitions
{-# 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)
as you can see I have defined a Symbol class that uses ExampleCharacters in the type signature. Example usage would be let sym = Terminal "xyy" :: Symbol Variable
creating a variable symbol with the name "xyy"
.
Now, the obvious next step would be to generalize ExampleCharacter
to Character c
. I tried the following:
data Symbol :: (forall c (a :: *). Character c) => c a -> * where
Terminal :: a -> Symbol (b :: c a)
But I get the following error:
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’
I'm not quite sure what the error wants to tell me. Why is forall (c :: * -> *) a. Character c
an illegal constraint and how so? Is there any way around it?
回答1:
From the 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.
So in principle what you've written is sensible; it simply isn't supported yet (as of writing, most recent GHC is 8.2.2).
来源:https://stackoverflow.com/questions/48313174/generalizing-from-a-specific-type-to-a-class-in-a-gadt