Hello everyone,
recently I have run into problems with dependencies preventing me from destructing terms I match on when the branches of the match use the equality generated by the match.
For example I have something like the following scenario:
I have types function
and type
as well as functions get_type
and has_type
that infer a type for a function (if possible) and check that a function has a given type.
I also have a lemma get_type_correct
that relates get_type
and has_type
.
Hypothesis function: Type.
Hypothesis type: Type.
Hypothesis get_type: function -> option type.
Hypothesis has_type: function -> type -> Prop.
Hypothesis get_type_correct: forall f t, get_type f = Some t -> has_type f t.
I have then defined an inductive type typed_function
that packages a function together with its type and a proof that the type is correct. I have also defined two functions converting between typed and untyped functions.
Inductive typed_function : Type :=
TR f t: has_type f t -> typed_function.
Definition untype_function (tf: typed_function):=
match tf with
| TR f _ _ => f
end.
Definition type_function (f: function) : option typed_function.
destruct (get_type f) eqn:E.
- exact (Some (TR _ _ (get_type_correct _ _ E))).
- exact None.
Defined.
Note that type_function
needs the equation E generated by the case analysis of (get_type f)
to construct the proof needed by the TR
constructor.
The actual definition generated by Coq from my tactics is the following:
type_function =
fun f : function =>
let o := get_type f in
let E : get_type f = o := eq_refl in
match o as o0 return (get_type f = o0 -> option typed_function) with
| Some a => (fun (t : type) (E0 : get_type f = Some t) => Some (TR f t (get_type_correct f t E0))) a
| None => fun _ : get_type f = None => None
end E
: function -> option typed_function
I would like to prove that removing the types from a term that has been successfully typed via type_function
results in the original term. However, as far as I can tell, this would require me to do case analysis on get_type f
, which Coq will not let me do because it results in wrong types in the return branches.
Lemma untype_of_type_eq f tf: type_function f = Some tf -> untype_function tf = f.
Proof.
unfold type_function. intros eq.
Fail destruct (get_type f).
The command has indeed failed with message:
Abstracting over the term “o” leads to a term
fun o0 : option type =>
match o0 as o1 return (o0 = o1 → option typed_function) with
| Some a => fun E : o0 = Some a => Some (TR f a (get_type_correct f a E))
| None => fun _ : o0 = None => None
end eq_refl = Some tf → untype_function tf = f
which is ill-typed.
Reason is: Illegal application:
The term “get_type_correct” of type
“forall (f : function) (t : type), get_type f = Some t → has_type f t”
cannot be applied to the terms
“f” : “function”
“a” : “type”
“E” : “o0 = Some a”
The 3rd term has type “o0 = Some a” which should be coercible to “get_type f = Some a”.
Even dependent destruction does not work:
pose (gf := get_type f). fold gf in eq.
Fail dependent destruction gf.
The command has indeed failed with message:
gf is used in hypothesis eq.
I have not been able to figure out how to deal with such situations and would be very happy about any help.
Cheers,
Jan.