diff --git a/heap_lang/lang.v b/heap_lang/lang.v index ecc53ff13c8b24dd7dc3f0a61b0760904c085131..1b934de7b5724fb620f12cb1d8c929615f888b5c 100644 --- a/heap_lang/lang.v +++ b/heap_lang/lang.v @@ -32,8 +32,16 @@ Proof. destruct mx; rewrite /= ?elem_of_cons; naive_solver. Qed. +(** A typeclass for whether a variable is bound in a given + context. Making this a typeclass means we can use tpeclass search + to program solving these constraints, so this becomes extensible. + Also, since typeclass search runs *after* unification, Coq has already + inferred the X for us; if we were to go for embedded proof terms ot + tactics, Coq would do things in the wrong order. *) Class VarBound (x : string) (X : list string) := var_bound : bool_decide (x ∈ X). +(* FIXME shouldn't this have this Hint to only perfom search of x and X + are not evars? *) Hint Extern 0 (VarBound _ _) => vm_compute; exact I : typeclass_instances. Instance var_bound_proof_irrel x X : ProofIrrel (VarBound x X). @@ -46,6 +54,13 @@ Qed. Inductive expr (X : list string) := (* Base lambda calculus *) + (* Var is the only place where the terms contain a proof. The fact that they + contain a proof at all is suboptimal, since this means two seeminlgy + convertible terms could differ in their proofs. However, this also has + some advantages: + * We can make the [X] an index, so we can do non-dependent match. + * In expr_weaken, we can push the proof all the way into Var, making + sure that proofs never block computation. *) | Var (x : string) `{VarBound x X} | Rec (f x : binder) (e : expr (f :b: x :b: X)) | App (e1 e2 : expr X)