raw_match

Term.raw_match :
  hol_type list -> term set ->
  term -> term ->
  (term,term) subst * (hol_type,hol_type) subst ->
    ((term,term) subst * term set) *
    ((hol_type,hol_type) subst * hol_type list)

Primitive term matcher.

The most primitive matching algorithm for HOL terms is raw_match. An invocation raw_match avoid_tys avoid_tms pat ob (tmS,tyS), if it succeeds, returns a substitution pair ((TmS,TmID),(TyS,TyID)) such that

   aconv (subst TmS' (inst TyS pat)) ob.

where TmS' is TmS instantiated by TyS. The arguments avoid_tys and avoid_tms specify type and term variables in pat that are not allowed to become redexes in S and T.

The pair (tmS,tyS) is an accumulator argument. This allows raw_match to be folded through lists of terms to be matched. (TmS,TyS) must agree with (tmS,tyS). This means that if there is a {redex,residue} in TmS and also a {redex,residue} in tmS so that both redex fields are equal, then the residue fields must be alpha-convertible. Similarly for types: if there is a {redex,residue} in TyS and also a {redex,residue} in tyS so that both redex fields are equal, then the residue fields must also be equal. If these conditions hold, then the result-pair (TmS,TyS) includes (tmS,tyS).

Finally, note that the result also includes a set (resp. a list) of term and type variables, accompanying the substitutions. These represent identity bindings that have occurred in the process of doing the match. If raw_match is to be folded across multiple problems, these output values will need to be merged with avoid_tms and avoid_tys respectively on the next call so that they cannot be instantiated a second time. Because they are identity bindings, they do not need to be referred to in validating the central identity above.

Failure

raw_match will fail if no TmS and TyS meeting the above requirements can be found. If a match (TmS,TyS) between pat and ob can be found, but elements of avoid_tys would appear as redexes in TyS or elements of avoid_tms would appear as redexes in TmS, then raw_match will also fail.

Example

We first perform a match that requires type instantitations, and also alpha-convertibility.

   > val ((tmS,_),(tyS,_)) =
      raw_match [] empty_varset
                “\x:'a. x = f (y:'b)”
                “\a.    a = ~p” ([],[]);
   val tmS = [{redex = “y”, residue = “p”}, {redex = “f”, residue = “$¬”}]:
      (term, term) Term.subst
   val tyS =
      [{redex = “:β”, residue = “:bool”}, {redex = “:α”, residue = “:bool”}]:
      (hol_type, hol_type) Term.subst

One of the main differences between raw_match and more refined derivatives of it, is that the returned substitutions are un-normalized by raw_match. If one naively applied (tmS,tyS) to \x:'a. x = f (y:'b), type instantiation with tyS would be applied first, yielding \x:bool. x = f (y:bool). Then substitution with tmS would be applied, unsuccessfully, since both f and y in the pattern term have been type instantiated, but the corresponding elements of the substitution haven’t. Thus, higher level operations building on raw_match typically instantiate tmS by tyS to get tmS' before applying (tmS',tyT) to the pattern term. This can be achieved by using norm_subst. However, raw_match exposes this level of detail to the programmer.

Comments

Higher level matchers are generally preferable, but raw_match is occasionally useful when programming inference rules.

See also

Term.match_term, Term.match_terml, Term.norm_subst, Term.subst, Term.inst, Type.raw_match_type, Type.match_type, Type.match_typel, Type.type_subst