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.
source to share
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)
source to share