|
1 | 1 | {-# LANGUAGE ViewPatterns, PatternSynonyms #-}
|
2 |
| - |
3 |
| -module Minimal ( |
4 |
| - Formula(..), |
5 |
| - (#&), (#|), (#>), |
6 |
| - bot, |
7 |
| - pattern Bottom, |
8 |
| - pattern Not, |
9 |
| - Deduction(..), |
10 |
| - Proof(..), |
11 |
| - runProof, evalProof, throwError, |
12 |
| - assume, |
13 |
| - implIntro, implElim, |
14 |
| - conjIntro, leftConjElim, rightConjElim, |
15 |
| - disjElim, leftDisjIntro, rightDisjIntro, |
16 |
| - ) where |
| 2 | +{-# LANGUAGE DeriveFunctor #-} |
| 3 | + |
| 4 | +module Minimal where |
| 5 | +--module Minimal ( |
| 6 | +-- Formula(..), |
| 7 | +-- (#&), (#|), (#>), |
| 8 | +-- bot, |
| 9 | +-- pattern Bottom, |
| 10 | +-- pattern Not, |
| 11 | +-- Deduction(..), |
| 12 | +-- Proof(..), |
| 13 | +-- runProof, evalProof, throwError, |
| 14 | +-- assume, |
| 15 | +-- implIntro, implElim, |
| 16 | +-- conjIntro, leftConjElim, rightConjElim, |
| 17 | +-- disjElim, leftDisjIntro, rightDisjIntro, |
| 18 | +-- ) where |
17 | 19 |
|
18 | 20 | import Control.Monad.Except
|
| 21 | +import Control.Monad.Free |
19 | 22 | import Data.Set (Set, (\\))
|
20 | 23 | import qualified Data.Set as Set
|
21 | 24 | import Text.Printf (printf)
|
@@ -52,73 +55,33 @@ instance Show Formula where
|
52 | 55 | show (Disjunction a b) = printf "(%s \x2228 %s)" (show a) (show b)
|
53 | 56 | show (Implication a b) = printf "(%s \x2192 %s)" (show a) (show b)
|
54 | 57 |
|
55 |
| -data Deduction = Deduction { assumptions :: Set Formula |
56 |
| - , conclusion :: Formula |
57 |
| - } deriving (Show) |
58 |
| - |
59 |
| --- Except is like Either (sum type) but explicitly for representing errors. |
60 |
| -type Proof = Except String Deduction |
61 |
| - |
62 |
| -runProof :: Proof -> Either String Deduction |
63 |
| -runProof = runExcept |
64 |
| - |
65 |
| -evalProof :: Proof -> Deduction |
66 |
| -evalProof p = case runProof p of |
67 |
| - (Right d) -> d |
68 |
| - _ -> error "evalProof run on invalid Proof" |
69 |
| - |
70 |
| --- The quoted versions of these functions are ones that can't fail, so return |
71 |
| --- Deduction instead of Proof. Unquoted versions are defined below that return |
72 |
| --- a Proof for consistency. |
73 |
| - |
74 |
| -assume :: Formula -> Proof |
75 |
| -assume f = return (Deduction (Set.singleton f) f) |
76 |
| - |
77 |
| -implIntro :: Formula -> Deduction -> Proof |
78 |
| -implIntro f d = return (Deduction (Set.delete f a) (f #> c)) |
79 |
| - where a = assumptions d |
80 |
| - c = conclusion d |
81 |
| - |
82 |
| -implElim :: Deduction -> Deduction -> Proof |
83 |
| -implElim (Deduction aA a') (Deduction aAtoB (Implication a b)) |
84 |
| - | (a' == a) = return (Deduction (Set.union aA aAtoB) b) |
85 |
| - | otherwise = throwError "conclusion of first argument must be the antecedent of the conclusion of the second argument" |
86 |
| -implElim _ _ = throwError "second argument to implElim must be an implication" |
87 |
| - |
88 |
| -conjIntro :: Deduction -> Deduction -> Proof |
89 |
| -conjIntro l r = return (Deduction (Set.union al ar) (cl #& cr)) |
90 |
| - where al = assumptions l |
91 |
| - ar = assumptions r |
92 |
| - cl = conclusion l |
93 |
| - cr = conclusion r |
94 |
| - |
95 |
| -leftDisjIntro :: Formula -> Deduction -> Proof |
96 |
| -leftDisjIntro f d = return (Deduction (assumptions d) (f #| r)) |
97 |
| - where r = conclusion d |
98 |
| - |
99 |
| -rightDisjIntro :: Deduction -> Formula -> Proof |
100 |
| -rightDisjIntro d f = return (Deduction (assumptions d) (l #| f)) |
101 |
| - where l = conclusion d |
102 |
| - |
103 |
| -leftConjElim :: Deduction -> Proof |
104 |
| -leftConjElim d = case (conclusion d) of |
105 |
| - (Conjunction _ r) -> return d { conclusion = r } |
106 |
| - _ -> throwError "argument must be a conjunction" |
107 |
| - |
108 |
| -rightConjElim :: Deduction -> Proof |
109 |
| -rightConjElim d = case (conclusion d) of |
110 |
| - (Conjunction l _) -> return d { conclusion = l } |
111 |
| - _ -> throwError "argument must be a conjunction" |
112 |
| - |
113 |
| -disjElim :: Deduction -> Deduction -> Deduction -> Proof |
114 |
| --- matches if the conclusion of the first argument is a disjunction. |
115 |
| --- then binds the whole deduction to `aOrB'. |
116 |
| -disjElim aOrB@(conclusion -> (Disjunction a b)) aToC bToC |
117 |
| - | conclusion aToC == conclusion bToC = return (Deduction assums conc) |
118 |
| - | otherwise = throwError "conclusion of second arg and conclusion of third arg must be equal" |
119 |
| - where aAorB = assumptions aOrB |
120 |
| - aAtoC = a `Set.delete` assumptions aToC |
121 |
| - aBtoC = b `Set.delete` assumptions bToC |
122 |
| - assums = Set.unions [aAorB, aAtoC, aBtoC] |
123 |
| - conc = conclusion aToC |
124 |
| -disjElim _ _ _ = throwError "conclusion of first arg must be a disjunction" |
| 58 | +data Proof = Proof { assumptions :: Set Formula |
| 59 | + , conclusion :: Formula |
| 60 | + } deriving (Show) |
| 61 | + |
| 62 | +data DeductionF next |
| 63 | + = Assume Formula (Proof -> next) |
| 64 | + | ImplElim Proof Proof (Proof -> next) |
| 65 | + | ImplIntro Formula Proof (Proof -> next) |
| 66 | + deriving (Functor) |
| 67 | + |
| 68 | +type Deduction = Free DeductionF |
| 69 | + |
| 70 | +assume :: Formula -> Deduction Proof |
| 71 | +assume f = liftF (Assume f id) |
| 72 | + |
| 73 | +implElim :: Proof -> Proof -> Deduction Proof |
| 74 | +implElim maj min = liftF (ImplElim maj min id) |
| 75 | + |
| 76 | +implIntro :: Formula -> Proof -> Deduction Proof |
| 77 | +implIntro f prem = liftF (ImplIntro f prem id) |
| 78 | + |
| 79 | +blah :: Deduction Proof |
| 80 | +blah = do |
| 81 | + dA <- assume (Proposition "A") |
| 82 | + dNA <- assume (Not (Proposition "A")) |
| 83 | + dB <- implElim dNA dA |
| 84 | + implIntro (Not (Proposition "A")) dB |
| 85 | + |
| 86 | +showDeduction :: (Show a, Show r) => Free (DeductionF a) r -> String |
| 87 | +showDeduction (Free (Assume f x)) = printf "assume %s\n %s" |
0 commit comments