Since the code snippet doesn't work I will assume that you are trying to construct an equality type on dependent types.
Hypothesis A: nat -> Type.
Hypothesis B: Type.
Definition foo (n: nat) (a: A n) : B. Admitted.
Definition rang (b: B) : nat. Admitted.
Definition bar (b: B) : A (rang b). Admitted.
You now have
Theorem thm1: forall (b: B), foo (rang b) (bar b) = b.
Proof. Admitted.
Theorem thm2: forall (n: nat) (a: A n), rang (foo n a) = n.
Proof. Admitted.
You have difficulty writing this:
Theorem thm3: forall (n:nat) (a: A n), bar (foo n a) = a.
which gives you the error:
In environment
n : nat
a : A n
The term "a" has type "A n" while it is expected to have type
"A (rang (foo n a))".
Is this what you want? Well, in that case, the root problem is that to construct a type =
you have to let Coq know that the types of two terms must be the same, but since you have wrapped $n$ inside some functions, Coq has no idea whether rang (foo n a) = n
. You can check how eq
is constructed:
Check eq.
eq
: ?A -> ?A -> Prop
where
?A : [ |- Type]
This is checked syntactically, which means propositional equality won't simply work in your case (even though you can prove that rang (foo n a) = n
). This is also known as heterogenous equality. Also, by checking the recursion rule of eq
you will know more about this:
Check eq_rect.
------------------------
eq_rect
: forall (A : Type) (x : A) (P : A -> Type),
P x -> forall y : A, x = y -> P y
It says you will obtain a new term of type $ P y $ if you can provide a proof which states that $x = y$ holds (this is actually the Leibniz rule). So the trick to type check is using transport
or type cast as suggested by @djao.
A,
B,
foo,
rang` etc. are concrete types or variables. As written, without knowing more about them, you cannot prove the desired equalities. There is information that you are not communicating. $\endgroup$