Compare commits
	
		
			2 Commits
		
	
	
		
			6a7a2eab19
			...
			930a05c951
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 930a05c951 | |||
| 545416fce0 | 
| @ -12,8 +12,10 @@ to generate this file without the comments in this block. | ||||
| -} | ||||
| { name = "bergamot" | ||||
| , dependencies = | ||||
|   [ "bifunctors" | ||||
|   [ "arrays" | ||||
|   , "bifunctors" | ||||
|   , "control" | ||||
|   , "either" | ||||
|   , "foldable-traversable" | ||||
|   , "lazy" | ||||
|   , "lists" | ||||
| @ -21,7 +23,9 @@ to generate this file without the comments in this block. | ||||
|   , "maybe" | ||||
|   , "newtype" | ||||
|   , "ordered-collections" | ||||
|   , "parsing" | ||||
|   , "prelude" | ||||
|   , "strings" | ||||
|   , "transformers" | ||||
|   , "tuples" | ||||
|   , "unifyt" | ||||
|  | ||||
							
								
								
									
										57
									
								
								src/Language/Bergamot/Parser.purs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/Language/Bergamot/Parser.purs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| module Language.Bergamot.Parser where | ||||
| 
 | ||||
| import Prelude | ||||
| 
 | ||||
| 
 | ||||
| import Language.Bergamot.Syntax (Expr(..)) | ||||
| import Language.Bergamot.Rules (Rule(..), Metavariable) | ||||
| 
 | ||||
| import Control.Apply (lift2) | ||||
| import Control.Lazy (defer) | ||||
| import Parsing (Parser, runParser) | ||||
| import Parsing.String (char, eof, string) | ||||
| import Parsing.String.Basic (digit, letter, space) | ||||
| import Parsing.Combinators (many, many1, sepBy, (<|>)) | ||||
| import Data.Array (fromFoldable) | ||||
| import Data.Either (hush) | ||||
| import Data.List (List(..)) | ||||
| import Data.List.NonEmpty (NonEmptyList) | ||||
| import Data.Maybe (Maybe) | ||||
| import Data.String (codePointFromChar, fromCodePointArray) | ||||
| 
 | ||||
| charsToString :: NonEmptyList Char -> String | ||||
| charsToString = fromCodePointArray <<< fromFoldable <<< map codePointFromChar | ||||
| 
 | ||||
| whitespace :: Parser String Unit | ||||
| whitespace = void $ many space | ||||
| 
 | ||||
| identifier :: Parser String String | ||||
| identifier = (charsToString <$> many1 (letter <|> digit <|> char '_')) <* whitespace | ||||
| 
 | ||||
| expr :: Parser String (Expr Metavariable) | ||||
| expr = (defer $ \_ -> atom) <|> (defer $ \_ -> metavariable) | ||||
| 
 | ||||
| atom :: Parser String (Expr Metavariable) | ||||
| atom = lift2 Atom (identifier <* whitespace) (args <|> pure Nil) | ||||
|     where args = char '(' *> sepBy (defer $ \_ -> expr) (char ',' *> whitespace) <* char ')' <* whitespace | ||||
| 
 | ||||
| metavariable :: Parser String (Expr Metavariable) | ||||
| metavariable = Var <$> (char '?' *> identifier <* whitespace) | ||||
| 
 | ||||
| rule :: Parser String (Rule Metavariable) | ||||
| rule = map MkRule $ pure { head: _, tail: _ } <*> expr <*> (args <|> pure Nil) <* char ';' <* whitespace | ||||
|     where | ||||
|         arrow = (void (char '←') <|> void (string "<-")) <* whitespace | ||||
|         args = arrow *> sepBy expr (char ',' *> whitespace) <* whitespace | ||||
| 
 | ||||
| rules :: Parser String (List (Rule Metavariable)) | ||||
| rules = many rule | ||||
| 
 | ||||
| parseRule :: String -> Maybe (Rule Metavariable) | ||||
| parseRule s = hush $ runParser s (rule <* eof) | ||||
| 
 | ||||
| parseRules :: String -> Maybe (List (Rule Metavariable)) | ||||
| parseRules s = hush $ runParser s (rules <* eof) | ||||
| 
 | ||||
| parseQuery :: String -> Maybe (Expr Metavariable) | ||||
| parseQuery s = hush $ runParser s (expr <* eof) | ||||
							
								
								
									
										43
									
								
								src/Language/Bergamot/Rules.purs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/Language/Bergamot/Rules.purs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| module Language.Bergamot.Rules where | ||||
| 
 | ||||
| import Prelude | ||||
| 
 | ||||
| import Language.Bergamot.Syntax (Expr) | ||||
| 
 | ||||
| import Control.Monad.State.Trans (runStateT) | ||||
| import Control.Monad.State.Class (class MonadState, gets, modify) | ||||
| import Control.Monad.Unify.Class (class MonadUnify, fresh) | ||||
| import Data.List (List) | ||||
| import Data.Traversable (class Traversable, traverse) | ||||
| import Data.Foldable (class Foldable) | ||||
| import Data.Map (Map, lookup, insert) | ||||
| import Data.Map as Map | ||||
| import Data.Tuple (fst) | ||||
| import Data.Newtype (class Newtype) | ||||
| import Data.Maybe (Maybe(..)) | ||||
| 
 | ||||
| newtype Rule k = MkRule { head :: Expr k, tail :: List (Expr k) } | ||||
| derive instance Newtype (Rule k) _ | ||||
| derive instance Functor Rule | ||||
| derive instance Foldable Rule | ||||
| derive instance Traversable Rule | ||||
| 
 | ||||
| type Metavariable = String | ||||
| type Metavariables k = Map Metavariable k | ||||
| 
 | ||||
| newtype ProofTree k = MkProofTree { claim :: Expr k, rule :: Rule Metavariable, witnesses :: List (ProofTree k) } | ||||
| derive instance Functor ProofTree | ||||
| 
 | ||||
| metavariable :: forall k f m. MonadState (Metavariables k) m => MonadUnify k f m => Metavariable -> m k | ||||
| metavariable s = do | ||||
|     r <- gets (lookup s) | ||||
|     case r of | ||||
|         Just v -> pure v | ||||
|         Nothing -> do | ||||
|            v <- fresh | ||||
|            modify (insert s v) *> pure v | ||||
| 
 | ||||
| -- note: unification expression ef not the same as functor-to-instantiate f, this way we can instantiate | ||||
| -- things that contain expression etc. | ||||
| instantiate :: forall k f ef m. Traversable f => MonadUnify k ef m => f Metavariable -> m (f k) | ||||
| instantiate f = map fst $ runStateT (traverse metavariable f) Map.empty | ||||
| @ -2,39 +2,11 @@ module Language.Bergamot.Syntax where | ||||
| 
 | ||||
| import Prelude | ||||
| 
 | ||||
| import Control.Plus (class Plus, empty) | ||||
| import Control.Monad (class Monad) | ||||
| import Control.Monad.State.Trans (StateT, runStateT) | ||||
| import Control.Monad.State.Class (class MonadState, gets, modify) | ||||
| import Control.Apply (class Apply, apply, lift2) | ||||
| import Control.Alt (class Alt, alt) | ||||
| import Control.Alternative (class Alternative) | ||||
| import Control.Applicative (class Applicative, pure, (*>)) | ||||
| import Control.Bind (class Bind, bind, join, (>>=)) | ||||
| import Control.MonadPlus (class MonadPlus) | ||||
| import Control.Monad.Reader.Class (class MonadReader, class MonadAsk, local, ask, asks) | ||||
| import Control.Monad.Logic.Class (class MonadLogic, msplit, interleave) | ||||
| import Control.Monad.Unify.Class (class MonadUnify, class Unifiable, class UnificationVariable, Stream(..), squash, alongside, ComparisonAction(..), fresh, unify, reify) | ||||
| import Control.Monad.Reader.Trans (ReaderT, runReaderT) | ||||
| import Control.Monad.Unify.Trans (UnifyT(..), runUnifyT) | ||||
| import Control.Monad.Logic.Trans (SFKT(..), runSFKTOnce) | ||||
| import Control.Monad.State.Trans (StateT(..), runStateT) | ||||
| import Data.List (List(..), (:), fromFoldable) | ||||
| import Data.Functor (class Functor, (<$>), map) | ||||
| import Data.Eq (class Eq) | ||||
| import Data.Ord (class Ord) | ||||
| import Data.Traversable (class Traversable, sequence, traverse, oneOf) | ||||
| import Data.Foldable (class Foldable, foldr, foldl, foldMap, any, intercalate) | ||||
| import Data.Monoid ((<>), mempty) | ||||
| import Data.Map (Map, lookup, insert) | ||||
| import Data.Map as Map | ||||
| import Data.Set (Set, singleton, union) | ||||
| import Data.Tuple (Tuple(..), fst) | ||||
| import Data.Tuple.Nested ((/\)) | ||||
| import Data.Lazy (Lazy, defer, force) | ||||
| import Data.Newtype (class Newtype, un, over2) | ||||
| import Data.Maybe (Maybe(..), fromMaybe, isJust) | ||||
| import Data.Bifunctor (rmap) | ||||
| import Control.Monad.Unify.Class (class Unifiable, class UnificationVariable, Stream(..), squash, alongside, ComparisonAction(..)) | ||||
| import Data.Foldable (class Foldable) | ||||
| import Data.Traversable (class Traversable) | ||||
| import Data.Lazy (defer) | ||||
| import Data.List (List(..), (:)) | ||||
| 
 | ||||
| data Expr v | ||||
|     = Var v | ||||
| @ -67,83 +39,3 @@ instance UnificationVariable k => Unifiable k Expr where | ||||
|           combine (_:_) Nil = (Var Fail) : Nil | ||||
|           combine Nil (_:_) = (Var Fail) : Nil | ||||
|           combine (x:xs) (y:ys) = alongside x y : combine xs ys | ||||
| 
 | ||||
| -- note: unification expression ef not the same as functor-to-instantiate f, this way we can instantiate | ||||
| -- things that contain expression etc. | ||||
| instantiate :: forall k f ef m. Traversable f => MonadUnify k ef m => f Metavariable -> m (f k) | ||||
| instantiate f = map fst $ runStateT (traverse metavariable f) Map.empty | ||||
| 
 | ||||
| newtype Rule k = MkRule { name :: String, head :: Expr k, tail :: List (Expr k) } | ||||
| derive instance Newtype (Rule k) _ | ||||
| derive instance Functor Rule | ||||
| derive instance Foldable Rule | ||||
| derive instance Traversable Rule | ||||
| 
 | ||||
| type UnifierEnv = { rules :: Array (Rule Metavariable), fuel :: Int } | ||||
| newtype Unifier a = MkUnifier (UnifyT IntVar Expr (ReaderT UnifierEnv (SFKT Maybe)) a) | ||||
| 
 | ||||
| derive instance Newtype (Unifier a) _ | ||||
| derive newtype instance Functor Unifier | ||||
| derive newtype instance Apply Unifier | ||||
| derive newtype instance Applicative Unifier | ||||
| derive newtype instance Alt Unifier | ||||
| derive newtype instance Plus Unifier | ||||
| derive newtype instance Alternative Unifier | ||||
| derive newtype instance Bind Unifier | ||||
| derive newtype instance Monad Unifier | ||||
| derive newtype instance MonadPlus Unifier | ||||
| derive newtype instance MonadUnify IntVar Expr Unifier | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadAsk UnifierEnv Unifier where | ||||
|     ask = MkUnifier $ MkUnifyT ask | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadReader UnifierEnv Unifier where | ||||
|     local f m = MkUnifier $ MkUnifyT $ StateT $ \s -> local f (runStateT (un MkUnifyT $ un MkUnifier m) s) | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadLogic Unifier where | ||||
|     msplit m = MkUnifier $ MkUnifyT $ map (map (rmap (MkUnifier <<< MkUnifyT))) $ msplit $ un MkUnifyT $ un MkUnifier m | ||||
|     interleave = over2 MkUnifier (over2 MkUnifyT interleave) | ||||
| 
 | ||||
| spend :: forall a. Unifier a -> Unifier a | ||||
| spend m = do | ||||
|     n <- asks _.fuel | ||||
|     if n > 0 then local (_ { fuel = n - 1}) m else empty | ||||
| 
 | ||||
| type Metavariable = String | ||||
| type Metavariables k = Map Metavariable k | ||||
| 
 | ||||
| metavariable :: forall k f m. MonadState (Metavariables k) m => MonadUnify k f m => Metavariable -> m k | ||||
| metavariable s = do | ||||
|     r <- gets (lookup s) | ||||
|     case r of | ||||
|         Just v -> pure v | ||||
|         Nothing -> do | ||||
|            v <- fresh | ||||
|            modify (insert s v) *> pure v | ||||
| 
 | ||||
| 
 | ||||
| newtype ProofTree k = MkProofTree { claim :: Expr k, rule :: Rule Metavariable, witnesses :: List (ProofTree k) } | ||||
| 
 | ||||
| match :: Array (Rule Metavariable) -> Expr IntVar -> Unifier (ProofTree IntVar) | ||||
| match rs e = oneOf $ map (matchSingle e) rs | ||||
|     where | ||||
|       matchSingle e' rule = spend $ do | ||||
|          MkRule {head, tail} <- instantiate rule | ||||
|          _ <- unify e' head | ||||
|          witnesses <- traverse (match rs) tail | ||||
|          pure $ MkProofTree { claim: e, rule: rule, witnesses: witnesses } | ||||
| 
 | ||||
| reifyProofTree :: ProofTree IntVar -> Unifier (ProofTree IntVar) | ||||
| reifyProofTree (MkProofTree {claim, rule, witnesses}) = do | ||||
|     claim' <- reify claim | ||||
|     witnesses' <- traverse reifyProofTree witnesses | ||||
|     pure $ MkProofTree $ { claim: claim', rule: rule, witnesses: witnesses' } | ||||
| 
 | ||||
| query :: Expr Metavariable -> Unifier (ProofTree IntVar) | ||||
| query e = (join $ lift2 match (asks _.rules) (instantiate e)) >>= reifyProofTree | ||||
| 
 | ||||
| runUnifier :: forall a. Array (Rule Metavariable) -> Unifier a -> Maybe a | ||||
| runUnifier rs m = runSFKTOnce (fst <$> (runReaderT (runUnifyT $ un MkUnifier m) { rules: rs, fuel: 10 })) | ||||
|  | ||||
							
								
								
									
										78
									
								
								src/Language/Bergamot/Unifier.purs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/Language/Bergamot/Unifier.purs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| module Language.Bergamot.Unifier where | ||||
| 
 | ||||
| import Prelude | ||||
| 
 | ||||
| import Language.Bergamot.Rules (Metavariable, ProofTree(..), Rule(..), instantiate) | ||||
| import Language.Bergamot.Syntax (Expr, IntVar) | ||||
| 
 | ||||
| import Control.Plus (class Plus, empty) | ||||
| import Control.Apply (lift2) | ||||
| import Control.Alt (class Alt) | ||||
| import Control.Alternative (class Alternative) | ||||
| import Control.MonadPlus (class MonadPlus) | ||||
| import Control.Monad.Reader.Class (class MonadReader, class MonadAsk, local, ask, asks) | ||||
| import Control.Monad.Logic.Class (class MonadLogic, msplit, interleave) | ||||
| import Control.Monad.Unify.Class (class MonadUnify, unify, reify) | ||||
| import Control.Monad.Reader.Trans (ReaderT, runReaderT) | ||||
| import Control.Monad.Unify.Trans (UnifyT(..), runUnifyT) | ||||
| import Control.Monad.Logic.Trans (SFKT, runSFKTOnce) | ||||
| import Control.Monad.State.Trans (StateT(..), runStateT) | ||||
| import Data.Traversable (traverse, oneOf) | ||||
| import Data.Tuple (fst) | ||||
| import Data.Newtype (class Newtype, un, over2) | ||||
| import Data.Maybe (Maybe) | ||||
| import Data.Bifunctor (rmap) | ||||
| 
 | ||||
| type UnifierEnv = { rules :: Array (Rule Metavariable), fuel :: Int } | ||||
| newtype Unifier a = MkUnifier (UnifyT IntVar Expr (ReaderT UnifierEnv (SFKT Maybe)) a) | ||||
| 
 | ||||
| derive instance Newtype (Unifier a) _ | ||||
| derive newtype instance Functor Unifier | ||||
| derive newtype instance Apply Unifier | ||||
| derive newtype instance Applicative Unifier | ||||
| derive newtype instance Alt Unifier | ||||
| derive newtype instance Plus Unifier | ||||
| derive newtype instance Alternative Unifier | ||||
| derive newtype instance Bind Unifier | ||||
| derive newtype instance Monad Unifier | ||||
| derive newtype instance MonadPlus Unifier | ||||
| derive newtype instance MonadUnify IntVar Expr Unifier | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadAsk UnifierEnv Unifier where | ||||
|     ask = MkUnifier $ MkUnifyT ask | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadReader UnifierEnv Unifier where | ||||
|     local f m = MkUnifier $ MkUnifyT $ StateT $ \s -> local f (runStateT (un MkUnifyT $ un MkUnifier m) s) | ||||
| 
 | ||||
| -- >:( | ||||
| instance MonadLogic Unifier where | ||||
|     msplit m = MkUnifier $ MkUnifyT $ map (map (rmap (MkUnifier <<< MkUnifyT))) $ msplit $ un MkUnifyT $ un MkUnifier m | ||||
|     interleave = over2 MkUnifier (over2 MkUnifyT interleave) | ||||
| 
 | ||||
| spend :: forall a. Unifier a -> Unifier a | ||||
| spend m = do | ||||
|     n <- asks _.fuel | ||||
|     if n > 0 then local (_ { fuel = n - 1}) m else empty | ||||
| 
 | ||||
| match :: Array (Rule Metavariable) -> Expr IntVar -> Unifier (ProofTree IntVar) | ||||
| match rs e = oneOf $ map (matchSingle e) rs | ||||
|     where | ||||
|       matchSingle e' rule = spend $ do | ||||
|          MkRule {head, tail} <- instantiate rule | ||||
|          _ <- unify e' head | ||||
|          witnesses <- traverse (match rs) tail | ||||
|          pure $ MkProofTree { claim: e, rule: rule, witnesses: witnesses } | ||||
| 
 | ||||
| reifyProofTree :: ProofTree IntVar -> Unifier (ProofTree IntVar) | ||||
| reifyProofTree (MkProofTree {claim, rule, witnesses}) = do | ||||
|     claim' <- reify claim | ||||
|     witnesses' <- traverse reifyProofTree witnesses | ||||
|     pure $ MkProofTree $ { claim: claim', rule: rule, witnesses: witnesses' } | ||||
| 
 | ||||
| query :: Expr Metavariable -> Unifier (ProofTree IntVar) | ||||
| query e = (join $ lift2 match (asks _.rules) (instantiate e)) >>= reifyProofTree | ||||
| 
 | ||||
| runUnifier :: forall a. Array (Rule Metavariable) -> Unifier a -> Maybe a | ||||
| runUnifier rs m = runSFKTOnce (fst <$> (runReaderT (runUnifyT $ un MkUnifier m) { rules: rs, fuel: 10 })) | ||||
| @ -2,37 +2,19 @@ module Test.Main where | ||||
| 
 | ||||
| import Prelude | ||||
| import Language.Bergamot.Syntax | ||||
| import Language.Bergamot.Rules | ||||
| import Language.Bergamot.Unifier | ||||
| import Language.Bergamot.Parser | ||||
| import Control.Apply | ||||
| import Control.Monad.Logic.Trans | ||||
| import Control.Monad.Logic.Class | ||||
| import Control.Monad.Unify.Trans | ||||
| import Control.Monad.Unify.Class | ||||
| import Data.List | ||||
| import Data.List (List(..), (:)) | ||||
| import Data.Array (fromFoldable) | ||||
| import Data.Foldable | ||||
| import Data.Maybe | ||||
| 
 | ||||
| rules :: Array (Rule Metavariable) | ||||
| rules = | ||||
|     [ MkRule { name: "TInt", head: tType tIntExpr tInt, tail: Nil } | ||||
|     , MkRule { name: "TString", head: tType tStringExpr tString, tail: Nil } | ||||
|     , MkRule { name: "TPlusInt", head: tType (tPlusExpr (Var "e1") (Var "e2")) tInt, tail: fromFoldable | ||||
|         [ tType (Var "e1") tInt | ||||
|         , tType (Var "e2") tInt | ||||
|         ] } | ||||
|     , MkRule { name: "TPlusString", head: tType (tPlusExpr (Var "e1") (Var "e2")) tString, tail: fromFoldable | ||||
|         [ tType (Var "e1") tString | ||||
|         , tType (Var "e2") tString | ||||
|         ] } | ||||
|     , MkRule { name: "TPair", head: tType (tProdExpr (Var "e1") (Var "e2")) (tProd (Var "t1") (Var "t2")), tail: fromFoldable | ||||
|         [ tType (Var "e1") (Var "t1") | ||||
|         , tType (Var "e2") (Var "t2") | ||||
|         ] } | ||||
|     , MkRule { name: "TFst", head: tType (tFstExpr (Var "e")) (Var "t1"), tail: fromFoldable | ||||
|         [ tType (Var "e") (tProd (Var "t1") (Var "t2")) | ||||
|         ] } | ||||
|     , MkRule { name: "TSnd", head: tType (tSndExpr (Var "e")) (Var "t2"), tail: fromFoldable | ||||
|         [ tType (Var "e") (tProd (Var "t1") (Var "t2")) | ||||
|         ] } | ||||
|     ] | ||||
|            | ||||
| tType et tt = Atom "type" $ et : tt : Nil | ||||
| tInt = Atom "int" Nil                                       | ||||
| tString = Atom "string" Nil                                 | ||||
| @ -44,11 +26,11 @@ tProdExpr et1 et2 = Atom "pair" $ et1 : et2 : Nil | ||||
| tFstExpr et = Atom "fst" $ et : Nil | ||||
| tSndExpr et = Atom "snd" $ et : Nil | ||||
| 
 | ||||
| toLatexExpr :: Expr IntVar -> String | ||||
| toLatexExpr :: Expr String -> String | ||||
| toLatexExpr (Atom "type" (t1 : t2 : Nil)) = toLatexExpr t1 <> " : " <> toLatexExpr t2 | ||||
| toLatexExpr (Atom "int" Nil) = "\\text{int}" | ||||
| toLatexExpr (Atom "string" Nil) = "\\text{string}" | ||||
| toLatexExpr (Atom "prod" (t1 : t2 : Nil)) = toLatexExpr t1 <> "\\times" <> toLatexExpr t2 | ||||
| toLatexExpr (Atom "prod" (t1 : t2 : Nil)) = toLatexExpr t1 <> "\\times " <> toLatexExpr t2 | ||||
| toLatexExpr (Atom "n" Nil) = "n" | ||||
| toLatexExpr (Atom "s" Nil) = "s" | ||||
| toLatexExpr (Atom "plus" (t1 : t2 : Nil)) = toLatexExpr t1 <> " + " <> toLatexExpr t2 | ||||
| @ -56,11 +38,14 @@ toLatexExpr (Atom "pair" (t1 : t2 : Nil)) = "(" <> toLatexExpr t1 <> ", " <> toL | ||||
| toLatexExpr (Atom "fst" (t : Nil)) = "\\text{fst}\\ " <> toLatexExpr t | ||||
| toLatexExpr (Atom "snd" (t : Nil)) = "\\text{snd}\\ " <> toLatexExpr t | ||||
| toLatexExpr (Atom s xs) = "\\text{" <> s <> "}(" <> intercalate ", " (toLatexExpr <$> xs) <> ")" | ||||
| toLatexExpr (Var _) = "?" | ||||
| toLatexExpr (Var x) = x | ||||
| 
 | ||||
| toLatexProofTree :: ProofTree IntVar -> String | ||||
| toLatexProofTree (MkProofTree {claim, witnesses}) = "\\cfrac{" <> intercalate "\\quad" (toLatexProofTree <$> witnesses) <> "}{" <> toLatexExpr claim <> "}" | ||||
| toLatexRule :: Rule String -> String | ||||
| toLatexRule (MkRule {head, tail}) = "\\cfrac{" <> intercalate "\\quad " (toLatexExpr <$> tail) <> "}{" <> toLatexExpr head <> "}" | ||||
| 
 | ||||
| main :: Maybe String | ||||
| main = map toLatexProofTree $ runUnifier rules $ query $ tType (Var "e") (tProd tInt (tProd tInt tString)) | ||||
| toLatexProofTree :: ProofTree String -> String | ||||
| toLatexProofTree (MkProofTree {claim, witnesses}) = "\\cfrac{" <> intercalate "\\quad " (toLatexProofTree <$> witnesses) <> "}{" <> toLatexExpr claim <> "}" | ||||
| 
 | ||||
| main :: String -> String -> Maybe String | ||||
| main rs q = map (toLatexProofTree <<< map (const "?")) $ join $ lift2 runUnifier (fromFoldable <$> parseRules rs) (query <$> parseQuery q) | ||||
| -- main = map toLatexProofTree $ runUnifier rules $ query $ tType (tSndExpr (tProdExpr tStringExpr (tPlusExpr tIntExpr tIntExpr))) (Var "T") | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user