End EvalGhostR.
(****************************************************)
(* Automating the selection of which lemma to apply *)
(* (the hstep tactic made as an overloaded lemma    *)
(****************************************************)
(* Need to case-split on bnd_, try_, or a val_ lemma. *)
(* Hence, three classes of canonical structures.      *)
Structure val_form A i r (p : Prop):=
ValForm {val_pivot :> spec A;
_ : p -> verify val_pivot i r}.
Structure bnd_form A B i (s : A -> spec B) r (p : Prop) :=
BndForm {bnd_pivot :> spec A;
_ : p -> verify (bind_s bnd_pivot s) i r}.
Structure try_form A B i (s1 : A -> spec B)
(s2 : exn -> spec B) r (p : Prop) :=
TryForm {try_pivot :> spec A;
_ : p -> verify (try_s try_pivot s1 s2) i r}.
(* The main lemma which triggers the selection. *)
Definition hstep A i (r : cont A) p (e : val_form i r p) : p -> verify e i r :=
let: ValForm _ pf := e in pf.
(* First check if matching on bnd_ or try_. If so, switch to searching *)
(* for bnd_ or try_form, respectively. Otherwise, fall through, and    *)
(* continue searching for a val_form. *)
Definition hstep_bnd A B i (s : A -> spec B) r p (e : bnd_form i s r p)
: p -> verify (bind_s e s) i r
:= let: BndForm _ pf := e in pf.
Canonical Structure
bnd_case_form A B i (s : A -> spec B) r p (e : bnd_form i s r p) :=
ValForm (hstep_bnd e).

(* Specifications: *)
Lemma try_case_pf A B i (s1 : A -> spec B) (s2 : exn -> spec B) r p
(e : try_form i s1 s2 r p) :
p -> verify (try_s e s1 s2) i r.