module PropLogicCore (
PropForm (..),
stringToProp,
PropAlg (..),
) where
import qualified Data.List as L
import qualified TextDisplay as D
import qualified Olist as O
data PropForm a
= A a
| F
| T
| N (PropForm a)
| CJ [PropForm a]
| DJ [PropForm a]
| SJ [PropForm a]
| EJ [PropForm a]
deriving (Show, Read, Eq)
class Ord a => PropAlg a p | p -> a where
at :: a -> p
false :: p
true :: p
neg :: p -> p
conj :: [p] -> p
disj :: [p] -> p
subj :: [p] -> p
equij :: [p] -> p
valid :: p -> Bool
satisfiable :: p -> Bool
contradictory :: p -> Bool
subvalent :: p -> p -> Bool
equivalent :: p -> p -> Bool
covalent :: p -> p -> Bool
disvalent :: p -> p -> Bool
properSubvalent :: p -> p -> Bool
properDisvalent :: p -> p -> Bool
atoms :: p -> O.Olist a
redAtoms :: p -> O.Olist a
irrAtoms :: p -> O.Olist a
nullatomic :: p -> Bool
subatomic :: p -> p -> Bool
equiatomic :: p -> p -> Bool
coatomic :: p -> p -> Bool
disatomic :: p -> p -> Bool
properSubatomic :: p -> p -> Bool
properDisatomic :: p -> p -> Bool
ext :: p -> [a] -> p
infRed :: p -> [a] -> p
supRed :: p -> [a] -> p
infElim :: p -> [a] -> p
supElim :: p -> [a] -> p
biequivalent :: p -> p -> Bool
pointwise :: (p -> Bool) -> [p] -> Bool
pairwise :: (p -> p -> Bool) -> [p] -> Bool
toPropForm :: p -> PropForm a
fromPropForm :: PropForm a -> p
pointwise = all
pairwise property pL =
case pL of
[] -> True
[x] -> True
(x:xL) -> (all (property x) xL) && (pairwise property xL)
contradictory p = not (satisfiable p)
satisfiable p = not (contradictory p)
covalent p1 p2 = not (disvalent p1 p2)
disvalent p1 p2 = not (covalent p1 p2)
nullatomic p = O.isEmpty (atoms p)
subatomic p1 p2 = O.included (atoms p1) (atoms p2)
equiatomic p1 p2 = O.equal (atoms p1) (atoms p2)
coatomic p1 p2 = not (disatomic p1 p2)
disatomic p1 p2 = O.disjunct (atoms p1) (atoms p2)
properSubatomic p1 p2 = O.properlyIncluded (atoms p1) (atoms p2)
properDisatomic p1 p2 = O.disjunct aL1 aL2 && not (O.isEmpty aL1) && not (O.isEmpty aL2)
where aL1 = atoms p1
aL2 = atoms p2
biequivalent p1 p2 = equiatomic p1 p2 && equivalent p1 p2
instance D.Display a => D.Display (PropForm a) where
textFrame form =
let falseSymbol = "false"
trueSymbol = "true"
negSymbol = "-"
conjSymbol = "*"
disjSymbol = "+"
subjSymbol = "->"
equijSymbol = "<->"
multiJuncTextFrame symb pL = case pL of
[] -> ["[" ++ symb ++ "]"]
[p] -> D.textFrameBracket (D.plainMerge (D.normalTextFrameTable
[[[symb ++ " "], D.textFrame p]]))
pL -> D.textFrameBracket (D.plainMerge (D.normalTextFrameTable
[(L.intersperse [" " ++ symb ++ " "] (map D.textFrame pL))]))
in case form of
A x -> D.textFrame x
F -> [falseSymbol]
T -> [trueSymbol]
N p -> D.plainMerge (D.normalTextFrameTable [[[negSymbol], D.textFrame p]])
CJ pL -> multiJuncTextFrame conjSymbol pL
DJ pL -> multiJuncTextFrame disjSymbol pL
SJ pL -> multiJuncTextFrame subjSymbol pL
EJ pL -> multiJuncTextFrame equijSymbol pL
type Parser a = String -> [(a, String)]
parseProp :: Parser (PropForm String)
parseProp = parseAtom `plus` parseFalse `plus` parseTrue `plus` parseNeg `plus`
parseConj `plus` parseDisj `plus` parseSubj `plus` parseEquij
where
parseAtom = \ inp -> [ (A out',inp') | (out',inp') <- (skipWhite atomToken) inp ]
parseFalse = \ inp -> [ (F, inp') | (out', inp') <- (skipWhite falseToken) inp ]
parseTrue = \ inp -> [ (T, inp') | (out', inp') <- (skipWhite trueToken) inp ]
parseNeg = \ inp -> [ (N out2, inp2) | (out1, inp1) <- (skipWhite negToken) inp,
(out2, inp2) <- (skipWhite parseProp) inp1 ]
parseConj = parseJunction CJ conjToken
parseDisj = parseJunction DJ disjToken
parseSubj = parseJunction SJ subjToken
parseEquij = parseJunction EJ equijToken
parseJunction :: ([PropForm String] -> PropForm String) -> Parser String -> Parser (PropForm String)
parseJunction junc token = \ inp ->
[ (junc [], i3) | (o1,i1) <- (skipWhite leftToken) inp,
(o2,i2) <- (skipWhite token) i1,
(o3,i3) <- (skipWhite rightToken) i2 ]
++
[ (junc [o3], i4) | (o1,i1) <- (skipWhite leftToken) inp,
(o2,i2) <- (skipWhite token) i1,
(o3,i3) <- (skipWhite parseProp) i2,
(o4,i4) <- (skipWhite rightToken) i3 ]
++
[ (junc (o2:o4:o5), i6) | (o1,i1) <- (skipWhite leftToken) inp,
(o2,i2) <- (skipWhite parseProp) i1,
(o3,i3) <- (skipWhite token) i2,
(o4,i4) <- (skipWhite parseProp) i3,
(o5,i5) <- tokenPropSeq i4,
(o6,i6) <- (skipWhite rightToken) i5]
where tokenPropSeq :: Parser [PropForm String]
tokenPropSeq = \ inp -> case (skipWhite token) inp of
[] -> [([],inp)]
[(t,inp')] -> [ (o1:o2, i2) | (o1,i1) <- (skipWhite parseProp) inp',
(o2,i2) <- (skipWhite tokenPropSeq) i1 ]
atomToken = \ inp -> [ (out',inp') | (out',inp') <- (grab1 isAlphanum) inp,
out' /= "false", out' /= "true" ]
leftToken = string "[" :: Parser String
rightToken = string "]" :: Parser String
falseToken = string "false" :: Parser String
trueToken = string "true" :: Parser String
negToken = string "-" :: Parser String
conjToken = string "*" :: Parser String
disjToken = string "+" :: Parser String
subjToken = string "->" :: Parser String
equijToken = string "<->" :: Parser String
string :: String -> Parser String
string s = \ inp -> let (s1,s2,s3) = iter (s,inp,[])
in if null s2
then [(s1,s3)]
else []
where iter ([],y,z) = (reverse z,[],y)
iter (x,[],z) = (reverse z,x,[])
iter (x:xL,y:yL,z) = if x == y
then iter (xL, yL, x:z)
else (reverse z, x:xL, y:yL)
grab :: (Char -> Bool) -> Parser String
grab chf = \ inp -> iter ("",inp)
where iter (xL, []) = [(reverse xL, [])]
iter (xL, y:yL) = if chf y
then iter (y:xL, yL)
else [(reverse xL, y:yL)]
grab1 :: (Char -> Bool) -> Parser String
grab1 chf = \ inp -> filter (\ (x,y) -> not (null x)) (grab chf inp)
plus :: Parser a -> Parser a -> Parser a
p `plus` q = \ inp -> (p inp ++ q inp)
isDigit c = '0' <= c && c <= '9'
isLower c = 'a' <= c && c <= 'z'
isUpper c = 'A' <= c && c <= 'Z'
isLetter c = isLower c || isUpper c
isAlphanum c = isDigit c || isLetter c
isWhite c = c == ' '
|| c == '\n'
|| c == '\t'
|| c == '\v'
|| c == '\f'
|| c == '\r'
whiteSpace :: Parser String
whiteSpace = grab isWhite
skipWhite :: Parser a -> Parser a
skipWhite p = \ inp -> [ (out1, inp1) | (out0, inp0) <- whiteSpace inp, (out1, inp1) <- p inp0 ]
stringToProp :: String -> PropForm String
stringToProp inp = case parseProp inp of
[] -> error ("stringToProp -- input is not a proper fancy formula:\n" ++ inp)
[(form,inp')] -> form
_ -> error ("stringToProp -- Fatal error! Input doesn't parse unambiguously:\n" ++ inp)