2

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 Answer 1

4

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, I exactly need this for producing AST, so I cannot go the easy way, and thank you so much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.