packages feed

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)))