egison-5.0.0: sample/unify.egi
--
-- This file has been auto-generated by egison-translator.
--
def term {a, b} : Matcher (Term a) :=
matcher
| var $ as integer with
| Var i -> [i]
| _ -> []
| compound $ $ as (string, list term) with
| Compound s l -> [(s, l)]
| _ -> []
| unify #$t $ as something with
| s ->
match unify t s as maybe something with
| just $σ -> [σ]
| nothing -> []
| subterm $ $ as (term, something) with
| s -> subterm s
| $ as something with
| tgt -> [tgt]
def var {a} (n: Integer) : Term a := Var n
def app {a} : [a] -> Term a :=
cambda xs ->
match xs as list something with
| $x :: $xs -> Compound x xs
def occur := \v => var ~v | compound _ (_ ++ occur ~v :: _)
def fv :=
\matchAll as (term) with
| occur $v -> v
def tsubst :=
\match as (something, term) with
| ($σ, var $n) ->
match σ as multiset (integer, term) with
| cons (#n, $t) _ -> t
| _ -> Var n
| ($σ, compound $f $xs) -> Compound f (map 1#(tsubst σ $1) xs)
def unify :=
\match as unorderedPair term with
| (var $x, var #x) -> Just []
| ( var $x
, AndPat (PatVar "t") (NotPat (PApplyPat (VarExpr "occur") [ValuePat (VarExpr "x")])) ) ->
Just [(x, t)]
| (compound $f $xs, compound #f $ys) -> unifyList xs ys
| _ -> Nothing
def unifyList :=
\match as (list term, list term) with
| ([], []) -> Just []
| (cons $x $xs, cons $y $ys) ->
match unify x y as maybe something with
| nothing -> Nothing
| just $σ1 ->
match unifyList (map 1#(tsubst σ1 $1) xs) (map 1#(tsubst σ1 $1) ys) as
maybe something with
| nothing -> Nothing
| just $σ2 -> Just JoinExpr (VarExpr "\963\&1") (VarExpr "\963\&2")
| _ -> Nothing
def x := var 0
def y := var 1
def z := var 2
def w := var 3
def a := app "a"
def b := app "b"
def c := app "c"
def d := app "d"
def f := "f"
def g := "g"
def h := "h"
def showΣ $σ := S.concat ["{", showΣ' σ, "}"]
def showΣ' :=
\match as list (something, something) with
| [] -> ""
| cons ($v, $t) [] -> S.concat ["[", showVar v, ", ", showTerm t, "]"]
| cons ($v, $t) $σ ->
S.concat ["[", showVar v, ", ", showTerm t, "], ", showΣ' σ]
def showVar :=
\match as integer with
| #0 -> "x"
| #1 -> "y"
| #2 -> "z"
| #3 -> "w"
def showTerm :=
\match as term with
| var #0 -> "x"
| var #1 -> "y"
| var #2 -> "z"
| var #3 -> "w"
| var $x -> S.concat ["x", show x]
| compound $f #[] -> f
| compound #"+" ((compound #"+" _ & $x) :: $y :: []) ->
S.concat ["(", showTerm x, ") + ", showTerm y]
| compound #"+" ($x :: $y :: []) ->
S.concat [showTerm x, " + ", showTerm y]
| compound #"*" ((compound #"*" _ & $x) :: $y :: []) ->
S.concat ["(", showTerm x, ") * ", showTerm y]
| compound #"*" ($x :: $y :: []) ->
S.concat [showTerm x, " * ", showTerm y]
| compound $f $xs ->
S.concat [f, "(", S.intercalate ", " (map showTerm xs), ")"]
-- Test: showΣ (head (unify (app "+" a b) x)) should be "{[x, a + b]}"
-- Test: showΣ (head (unify x (app "+" y z))) should be "{[x, y + z]}"
-- Test: showΣ (head (unify (app f x (app g y z) (app h x)) (app f a w y))) should be "{[x, a], [w, g(y, z)], [y, h(a)]}"
showΣ (head (unify (app "+" a b) x))
showΣ (head (unify x (app "+" y z)))
showΣ (head (unify (app f x (app g y z) (app h x)) (app f a w y)))