I have the following:
type Name = String
data Prop
= Var Name
| F
| T
| Not Prop
| Prop :|: Prop
| Prop :&: Prop
deriving (Eq, Read)
infixr 2 :|:
the type Prop represents a propositional formula. The propositional variables, such as p and q can be represented by Var "p" and Var "q".
F and T are the constant booleans for False and True.
Not represents the negation (~ or ¬)
:|: and :&: represent the disjunction (/) and conjuction (/\)
We can write logical propositions:
( Var "p" :|: Var "q") :&: ( Not (Var "p") :&: Var "q")
What I have to do is: replace Not, :|: and :&: with ~, / and /\ by making Prop an instance of the class Show, so that the following will be true:
test_ShowProp :: Bool
test_ShowProp =
show (Not (Var "P") :&: Var "Q") == "((~P)/\Q)"
This is my implementation so far:
instance Show Prop where
show (Var p) = p
show (Not (Var p)) = "(~" ++ p ++ ")"
show (Var p :|: Var q) = p ++ "\\/" ++ q
show (Var p :&: Var q) = p ++ "/\\" ++ q
But this doesn't cover all the cases, just the basic ones. How should I continue the implementation so that it tackles any propositional formula, not just the hardcoded ones? Because at the moment
(Var "p" :&: Var "q")
outputs: p/\q
but
Not (Var "p" :&: Var "q")
outputs: Non-exhaustive patterns in function show
You should match only one "layer" of your formula, i.e. only one constructor, and exploit recursion for subformulae. For instance,
show (Not f) = "(~" ++ show f ++ ")"
will apply to any formula starting with a negation, even if there is a non variable subformula under that negation.
Getting parentheses right might be tricky. You'll need to either be generous with parentheses or define showsPrec. If you are a beginner, I'd recommend the former, which does not need to cope with precedence levels.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With