I am trying to create the following datatypes:
data ExprValues = ExprNum Int |
ExprIdent String |
ExprChar Char |
ExprString String
deriving(Eq, Show, Read)
data ExprOverall = ExprFunCall ExprValues --correct this to use ExprIdent solely
deriving(Eq, Show, Read)
However, as it is indicated in the comment, I want that ExprValues next to the ExprFuncall to accept ExprIdent String only, not the other ExprValues. How am I able to do it?
First off, if you want to allow only the constructor, why not just “inline” it – store a String
right in ExprOverall
and be done?
But more generally, this sort of restriction can be implemented with GADTs. Often, especially for such AST-like types, you want to express the overall type the expression stands for. There, ExprIdent
might be polymorphic while the others are concrete:
{-# LANGUAGE GADTs #-}
data ExprValues a where
ExprNum :: Int -> ExprValues Int
ExprIdent :: String -> ExprValues a
ExprChar :: Char -> ExprValues Char
ExprString :: String -> ExprValues String
Then, for use in ExprOverall
you select a unique tag-type that is only applicable to the ExprIdent
constructor (because that allows any type variable a
, whereas the others are specific to a concrete type).
data FreeIdentifier
data ExprOverall = ExprFunCall (ExprValues FreeIdentifier)