Are there things like "type extensions" in Haskell?

I really don't think the term "type extension" officially means what I want, but it's the only term I could think of.

I have a Haskell polymorphic type for representing members in statement logic:

 data PropLogic a = Prop a | Tautology | Contradiction | And (PropLogic a) (PropLogic a)
                | Or (PropLogic a) (PropLogic a) | Implies (PropLogic a) (PropLogic a)
                | Not (PropLogic a)
     deriving (Eq,Show)

      

The problem is that I also need a similar polymorphic type of statement logic with quantification operators:

data PropQuantifiedLogic a = Prop a | Tautology | Contradiction | And (PropQuantifiedLogic a) (PropQuantifiedLogic a)
                | Or (PropQuantifiedLogic a) (PropQuantifiedLogic a) | Implies (PropQuantifiedLogic a) (PropQuantifiedLogic a)
                | Not (PropQuantifiedLogic a) | Forall (PropQuantifiedLogic a)
                | Exists (PropQuantifiedLogic a)
     deriving (Eq,Show)

      

Now I can just add a prefix to the name of each value constructor where both PropLogic

and PropQuantifiedLogic

have conflicting names, but the point is, I want to create many types like this that will have many conflicting value constructors: modal logic type, temporary logic type, and etc ... and creating new prefixes for each one quickly gets ugly.

What I really want to do is something like:

extendtype PropQuantifiedLogic a = PropLogic a | Exists (PropQuantifiedLogic a)
                                 | Forall (PropQuantifiedLogic a)

      

which will be equivalent to the first definition PropQuantifiedLogic

and will check the type.

Is it possible to do something like this in Haskell? If not, how should I handle this situation? This concept of "extension type" would introduce some ambiguity, but I believe that just the type inference methods won't work when using types like this, and I can handle it.

+3


source to share


2 answers


You can always implement this as

 data PropFrame a b = OrF b b | AndF b b ... | Prop a | Top

      

And then

type Prop a = Fix (PropFrame a)

      

Then you can add a new primitive



data QualifiedF a b = All (b -> b) | Exists (b -> b) | LiftProp (PropFrame a b)
type Qualified a = Fix (QualifiedF a)

      

This is a little uglier, but can be completed with -XPatternSynonyms

. The main idea here is to dump the problematic recursive case into an explicit parameter and use the Fix

recursion to recover.

Usage example

qand :: Qualified a -> Qualified a -> Qualified a
qand l r = Fix (LiftProp (AndF l r))

orOrAll :: (Qualified a -> Qualified a) -> Qualified a
orOrAll f = Fix (All f) `qand` Fix (Exists f)

      

+7


source


You can use PropLogic a

and add an additional constructor QuantifiedLogic

:



data PropQuantifiedLogic a =  QuantifiedLogic (PropLogic a)
                            | Exists (PropQuantifiedLogic a)
                            | Forall (PropQuantifiedLogic a)

      

0


source







All Articles