From 9233edfb4bcaebf979f8c1a08e931d993d4cc2e3 Mon Sep 17 00:00:00 2001 From: hi Date: Sun, 10 Aug 2025 13:32:42 +0000 Subject: [PATCH] formal language L --- Logic/Language.hs | 29 +++++++-- Logic/Language/L.hs | 143 ++++++++++++++++++++++++++++++++++++++++++++ Logic/Language/M.hs | 7 ++- 3 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 Logic/Language/L.hs diff --git a/Logic/Language.hs b/Logic/Language.hs index 6be2b16..f79b858 100644 --- a/Logic/Language.hs +++ b/Logic/Language.hs @@ -1,13 +1,30 @@ module Logic.Language where +type List a = [a] + -- Formal language (/grammar/production system/whatever) class (Eq symbol, Show symbol) => Language symbol where - -- If Haskell had dependent types this could be generalized. - -- For now the languages I want to make use at most up to infer3. - infer0 :: [[symbol]] - infer1 :: [[symbol] -> [[symbol]]] - infer2 :: [[symbol] -> [symbol] -> [[symbol]]] - infer3 :: [[symbol] -> [symbol] -> [symbol] -> [[symbol]]] + isWellFormed :: [symbol] -> Bool + + -- If Haskell had dependent types these could be generalized. + + -- axiomN : N wffs -> theorem + axiom0 :: [[symbol]] + axiom1 :: [[symbol] -> [symbol]] + axiom2 :: [[symbol] -> [symbol] -> [symbol]] + axiom3 :: [[symbol] -> [symbol] -> [symbol] -> [symbol]] + + -- inferN : N theorems -> theorem + -- (axiom0 and infer0 would mean the same thing.) + infer1 :: [[symbol] -> List [symbol]] + infer2 :: [[symbol] -> [symbol] -> List [symbol]] + + axiom0 = [] + axiom1 = [] + axiom2 = [] + axiom3 = [] + infer1 = [] + infer2 = [] -- Convenience newtype so strings are less ugly newtype Seq symbol = Seq [symbol] diff --git a/Logic/Language/L.hs b/Logic/Language/L.hs new file mode 100644 index 0000000..452e3a4 --- /dev/null +++ b/Logic/Language/L.hs @@ -0,0 +1,143 @@ +module Logic.Language.L where + +import Logic.Language (Language(..), Seq(..)) +import Logic.Statement (Statement(..)) +import Logic.Parse + ( Parser(..) + , ParseError + , Input(..) + , eof + , expected + , mkInput + , parseToken + ) + +import Control.Applicative (Alternative((<|>))) +import Data.Either (isRight) +import Data.Maybe (fromJust, maybeToList) +import Text.Read (readMaybe) + +-- The language L +data AlphaL + = Arrow + | Tilde + | Open + | Close + | Variable Integer + deriving (Eq, Show) + +type StringL = [AlphaL] + +instance Language AlphaL where + isWellFormed string = isRight $ eof parseL $ mkInput string + + axiom2 = [lAxiom1, lAxiom3] + axiom3 = [lAxiom2] + infer2 = [lRule1] + +-- (A → (B → A)) +lAxiom1 :: StringL -> StringL -> StringL +lAxiom1 wff1 wff2 = + [Open] ++ + wff1 ++ + [Arrow] ++ + [Open] ++ wff2 ++ [Arrow] ++ wff1 ++ [Close] ++ + [Close] + +-- ((A → (B → C)) → ((A → B) → (A → C))) +lAxiom2 :: StringL -> StringL -> StringL -> StringL +lAxiom2 wff1 wff2 wff3 = + [Open] ++ + [Open] ++ + wff1 ++ + [Arrow] ++ + [Open] ++ wff2 ++ [Arrow] ++ wff3 ++ [Close] ++ + [Close] ++ + [Arrow] ++ + [Open] ++ + [Open] ++ wff1 ++ [Arrow] ++ wff2 ++ [Close] ++ + [Arrow] ++ + [Open] ++ wff1 ++ [Arrow] ++ wff3 ++ [Close] ++ + [Close] ++ + [Close] + +-- ((¬A → ¬B) → ((¬A → B) → A)) +lAxiom3 :: StringL -> StringL -> StringL +lAxiom3 wff1 wff2 = + [Open] ++ + [Open, Tilde] ++ wff1 ++ [Arrow, Tilde] ++ wff2 ++ [Close] ++ + [Arrow] ++ + [Open] ++ + [Open, Tilde] ++ wff1 ++ [Arrow] ++ wff2 ++ [Close] ++ + [Arrow] ++ + wff1 ++ + [Close] ++ + [Close] + +{- +ghci> import Logic.Statement.Eval (bucket) +ghci> import Data.Either (fromRight) +ghci> bucket $ fromRight undefined $ eof parseL $ mkInput $ lAxiom1 [Variable 0] [Variable 1] +Tautology +ghci> bucket $ fromRight undefined $ eof parseL $ mkInput $ lAxiom2 [Variable 0] [Variable 1] [Variable 2] +Tautology +ghci> bucket $ fromRight undefined $ eof parseL $ mkInput $ lAxiom3 [Variable 0] [Variable 1] +Tautology +-} + +-- Modus ponens: from (A → B) and A, conclude B. +lRule1 :: StringL -> StringL -> [StringL] +lRule1 theorem1 theorem2 = maybeToList $ do + s1 <- fromEither $ eof parseL $ mkInput theorem1 + s2 <- fromEither $ eof parseL $ mkInput theorem2 + case s1 of + Implies s1a s1b + | s2 == s1a -> Just $ fromJust $ serializeL s1b + | otherwise -> Nothing + _ -> Nothing + where + fromEither = either (const Nothing) Just + +{- +ghci> f x = fromJust $ serializeL $ fromRight undefined $ eof stmt $ mkInput x +ghci> lRule1 (f "(0->1)") (f "0") +[[Variable 1]] +ghci> lRule1 (f "((!0->2)->(!!!!!!!1->1))") (f "(!0->2)") +[[Open,Tilde,Tilde,Tilde,Tilde,Tilde,Tilde,Tilde,Variable 1,Arrow,Variable 1,Close]] +ghci> lRule1 (f "((!0->2)->(!!!!!!!1->1))") (f "(!0->3)") +[] +-} + +parseL :: Parser AlphaL Statement +parseL = Parser variable <|> Parser tilde <|> arrow <|> fail + where + variable :: Input AlphaL -> Either ParseError (Statement, Input AlphaL) + variable input@(Input pos ((Variable n):xs)) = + Right (Atom $ show n, Input (pos + 1) xs) + variable input = Left $ expected "statement variable" input + + tilde :: Input AlphaL -> Either ParseError (Statement, Input AlphaL) + tilde input@(Input pos (Tilde:xs)) = + (\(statement, rest) -> (Not statement, rest)) <$> + runParser parseL (Input (pos + 1) xs) + tilde input = Left $ expected "negation" input + + arrow :: Parser AlphaL Statement + arrow = do + parseToken [Open] + s1 <- parseL + parseToken [Arrow] + s2 <- parseL + parseToken [Close] + return $ Implies s1 s2 + + fail :: Parser AlphaL Statement + fail = Parser $ \input -> Left $ expected "well-formed formula" input + +serializeL :: Statement -> Maybe [AlphaL] +serializeL (Atom label) = (\x -> [x]) <$> Variable <$> readMaybe label +serializeL (Not s) = (Tilde:) <$> serializeL s +serializeL (Implies s1 s2) = do + l1 <- serializeL s1 + l2 <- serializeL s2 + return $ [Open] ++ l1 ++ [Arrow] ++ l2 ++ [Close] diff --git a/Logic/Language/M.hs b/Logic/Language/M.hs index 5d4aa24..b605e05 100644 --- a/Logic/Language/M.hs +++ b/Logic/Language/M.hs @@ -13,15 +13,16 @@ data AlphaM type StringM = [AlphaM] instance Language AlphaM where - infer0 = [[M, I]] + isWellFormed (M:_) = True + isWellFormed _ = False + + axiom0 = [[M, I]] infer1 = [ mRule1 , mRule2 , mRule3 , mRule4 ] - infer2 = [] - infer3 = [] -- RULE I: If you possess a string whose last letter is I, you can add on a U at the end. mRule1 :: StringM -> [StringM]