(* Keys and map variables are syntactified as indices in the context.    *)
(* Disjoint union is syntactified as concatenation of lists.             *)
(*                                                                       *)
(* Pts n v : syntax for "key indexed the context under number n" \-> v   *)
(* Var n : syntax for "expression indexed in the context under number n" *)
(* In the cancellation algorithms, we iterate over the first              *)
(* expression e1 and remove each of its components from the second        *)
(* expression e2. But, typically, we want to remove only one occurrence   *)
(* of that component.                                                     *)
(*                                                                        *)
(* First, almost always, only one occurrence will exist, lest e2 be       *)
(* undefined. Thus, it's a waste of effort to traverse e2 in full once    *)
(* we've found an occurrence.                                             *)
(*                                                                        *)
(* Second, in some symmetric cancellation problems, e.g., dom_eq e1 e2,   *)
(* we *want* to remove only one occurrence from e2 for each component in  *)
(* e1. Otherwise, we will not produce a sound reduction. E.g.  dom (x \+  *)
(* x) (x \+ x) is valid, since both expressions are undef. However, after *)
(* removing x from the left side, and both x's from the right side, we    *)
(* get dom x Unit, which is not valid.                                    *)
(*                                                                        *)
(* Thus, as a matter of principle, we want a filter that removes just one *)
(* occurrence of a list element.                                          *)
(*                                                                        *)
(* We write it with p pulled out in a section in order to get it to       *)
(* simplify automatically.                                                *)
Section OneShotFilter.
Variables (A : Type) (p : pred A).
Fixpoint rfilter ts : seq A :=
if ts is t :: ts' then if p t then ts' else t :: rfilter ts' else [::].
End OneShotFilter.
(* now for reflection *)
Section Reflection.
Variables (K : ordType) (T : Type) (U : union_map_class K T).
Implicit Type i : ctx U.
Inductive term := Pts of nat & T | Var of nat.
(* interpretation function for elements *)
Definition interp' i t :=
match t with
Pts n v => if onth (keyx i) n is Some k then pts k v else um_undef
| Var n => if onth (varx i) n is Some f then f else um_undef
end.
(* main interpretation function *)
Notation fx i := (fun t f => interp' i t \+ f).
Definition interp i ts := foldr (fx i) Unit ts.

(* Specifications: *)
Lemma fE i ts x  : foldr (fx i) x ts = x \+ interp i ts.
Fixpoint pprint i ts :=
if ts is t :: ts' then
if ts' is [::] then interp' i t else interp' i t \+ pprint i ts'
else Unit.