Haskell - Restrict data parameters

187 Views Asked by At

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?

1

There are 1 best solutions below

1
On BEST ANSWER

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)