Get a rule search engine working with hardcoded rules
This commit is contained in:
parent
755d514342
commit
a9fc768182
|
@ -104,9 +104,9 @@ let upstream =
|
|||
|
||||
in upstream
|
||||
with logict.repo = "https://dev.danilafe.com/Everything-I-Know-About-Types/logict.git"
|
||||
with logict.version = "24298710fa940bfcf2d272bc6d5c7417f2bfccfe"
|
||||
with logict.version = "c2088a696727d26cb41b2553d24f3909f0525e12"
|
||||
with logict.dependencies = [ "control", "lists", "maybe", "prelude", "transformers", "tuples" ]
|
||||
with unifyt.repo = "https://dev.danilafe.com/Everything-I-Know-About-Types/unifyt.git"
|
||||
with unifyt.version = "d1e227dbed5e5af63510872b95a9417200c0d7c7"
|
||||
with unifyt.version = "014d9b38c8a1742dc3039227f84e3ba06acea51b"
|
||||
with unifyt.dependencies = [ "control", "foldable-traversable", "lazy", "maybe", "newtype", "ordered-collections", "prelude", "transformers", "tuples" ]
|
||||
|
||||
|
|
|
@ -5,23 +5,23 @@ import Prelude (Unit, ($), (<<<), unit, (/=), const, flip, (+))
|
|||
import Control.Plus (class Plus, empty)
|
||||
import Control.Monad (class Monad)
|
||||
import Control.Monad.State.Trans (StateT, runStateT)
|
||||
import Control.Monad.State.Class (gets, modify)
|
||||
import Control.Apply (class Apply, apply)
|
||||
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.Applicative (class Applicative, pure, (*>))
|
||||
import Control.Bind (class Bind, bind, (>>=))
|
||||
import Control.MonadPlus (class MonadPlus)
|
||||
import Control.Monad.Logic.Class (class MonadLogic, msplit, interleave)
|
||||
import Control.Monad.Unify.Class (class MonadUnify, class Unifiable, class UnificationVariable, Stream(..), squash, alongside, ComparisonAction(..))
|
||||
import Control.Monad.Unify.Class (class MonadUnify, class Unifiable, class UnificationVariable, Stream(..), squash, alongside, ComparisonAction(..), fresh, unify, reify)
|
||||
import Control.Monad.Unify.Trans (UnifyT(..), runUnifyT)
|
||||
import Control.Monad.Logic.Trans (SFKT(..), runSFKT)
|
||||
import Data.List (List(..), (:))
|
||||
import Control.Monad.Logic.Trans (SFKT(..), runSFKTOnce)
|
||||
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)
|
||||
import Data.Foldable (class Foldable, foldr, foldl, foldMap, any)
|
||||
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
|
||||
|
@ -39,25 +39,10 @@ data Expr v
|
|||
|
||||
derive instance Eq v => Eq (Expr v)
|
||||
derive instance Functor Expr
|
||||
|
||||
instance Foldable Expr where
|
||||
foldr f b (Var x) = f x b
|
||||
foldr f b (Atom _ xs) = foldr (\x b' -> foldr f b' x) b xs
|
||||
|
||||
foldl f b (Var x) = f b x
|
||||
foldl f b (Atom _ xs) = foldl (foldl f) b xs
|
||||
|
||||
foldMap f (Var x) = f x
|
||||
foldMap f (Atom _ xs) = foldl (<>) mempty (foldMap f <$> xs)
|
||||
|
||||
instance Traversable Expr where
|
||||
sequence (Var f) = Var <$> f
|
||||
sequence (Atom name fs) = Atom name <$> sequence (sequence <$> fs)
|
||||
|
||||
traverse f e = sequence (f <$> e)
|
||||
derive instance Foldable Expr
|
||||
derive instance Traversable Expr
|
||||
|
||||
newtype IntVar = MkIntVar Int
|
||||
|
||||
derive instance Eq IntVar
|
||||
derive instance Ord IntVar
|
||||
|
||||
|
@ -80,22 +65,119 @@ instance UnificationVariable k => Unifiable k Expr where
|
|||
combine Nil (_:_) = (Var Fail) : Nil
|
||||
combine (x:xs) (y:ys) = alongside x y : combine xs ys
|
||||
|
||||
newtype Unifier a = MkUnifier (UnifyT IntVar Expr (SFKT Maybe) a)
|
||||
-- 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
|
||||
|
||||
newtype Unifier a = MkUnifier (UnifyT IntVar Expr (SFKT List) 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
|
||||
|
||||
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
|
||||
|
||||
-- >:(
|
||||
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)
|
||||
|
||||
runUnifier :: forall a. Unifier a -> Maybe a
|
||||
runUnifier m = runSFKT (runUnifyT $ un MkUnifier m) (const <<< Just) Nothing
|
||||
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 = do
|
||||
MkRule {head, tail} <- instantiate rule
|
||||
_ <- unify e' head
|
||||
witnesses <- traverse (match rs) tail
|
||||
pure $ MkProofTree { claim: e, rule: rule, witnesses: witnesses }
|
||||
|
||||
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
|
||||
tProd t1 t2 = Atom "prod" $ t1 : t2 : Nil
|
||||
tIntExpr = Atom "n" Nil
|
||||
tStringExpr = Atom "s" Nil
|
||||
tPlusExpr et1 et2 = Atom "plus" $ et1 : et2 : Nil
|
||||
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 (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 "n" Nil) = "n"
|
||||
toLatexExpr (Atom "s" Nil) = "s"
|
||||
toLatexExpr (Atom "plus" (t1 : t2 : Nil)) = toLatexExpr t1 <> " + " <> toLatexExpr t2
|
||||
toLatexExpr (Atom "pair" (t1 : t2 : Nil)) = "(" <> toLatexExpr t1 <> ", " <> toLatexExpr t2 <> ")"
|
||||
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 _) = "?"
|
||||
|
||||
toLatexProofTree :: ProofTree IntVar -> String
|
||||
toLatexProofTree (MkProofTree {claim, rule, witnesses}) = "\\cfrac{" <> intercalate "\\quad" (toLatexProofTree <$> witnesses) <> "}{" <> toLatexExpr claim <> "}"
|
||||
|
||||
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 = instantiate e >>= match rules >>= reifyProofTree
|
||||
|
||||
runUnifier :: forall a. Unifier a -> List a
|
||||
runUnifier m = runSFKTOnce (fst <$> (runUnifyT $ un MkUnifier m))
|
||||
|
|
|
@ -9,15 +9,5 @@ import Control.Monad.Unify.Class
|
|||
import Data.List
|
||||
import Data.Maybe
|
||||
|
||||
runSomeComputation :: forall m. MonadLogic m => MonadUnify IntVar Expr m => m (Expr IntVar)
|
||||
runSomeComputation = do
|
||||
x1 <- fresh
|
||||
x2 <- fresh
|
||||
let binPred = Atom "hello" $ fromFoldable [variable x1, variable x2]
|
||||
let realBinPred = Atom "hello" $ fromFoldable [Atom "first" $ fromFoldable [], Atom "second" $ fromFoldable []]
|
||||
unify binPred realBinPred
|
||||
(unify (variable x1) (variable x2) >>= const (reify (variable x1))) `interleave` (unify (variable x1) (variable x1) >>= const (reify (variable x2)))
|
||||
|
||||
|
||||
main :: Maybe (Expr IntVar)
|
||||
main = runUnifier runSomeComputation
|
||||
main :: List String
|
||||
main = map toLatexProofTree $ runUnifier $ query $ tType (tSndExpr (tProdExpr tStringExpr (tPlusExpr tIntExpr tIntExpr))) (Var "T")
|
||||
|
|
Loading…
Reference in New Issue
Block a user