Search code examples
coqcoercion

How to use coercion with sig in coq


I have a code like

Definition even := {n : nat | exists k, n = k + k}.

Definition even_to_nat (e : even) : nat.
Admitted.

Coercion even_to_nat : even >-> nat.

Example Ex : forall n : even, exists k, k + k = n.
Admitted.

Example Ex2 : forall k, exists n : even, k + k = n.
Admitted.

How should I remove Admitted in this case?

Also, why does

Example Ex' : forall n : even, exists k, n = k + k

not work even with coercion? Is there a nice way to remove such errors?


Solution

  • This is a definition for the even_to_nat function written in Gallina:

    Definition even := {n : nat | exists k, n = k + k}.
    
    Definition even_to_nat (e : even) : nat :=
      match e with
      | exist _ n _ => n
      end.
    
    Coercion even_to_nat : even >-> nat.
    

    It pattern matches on e to retrieve the wrapped natural number n.

    This is an equivalent implementation using tactics:

    Definition even_to_nat_tac (e : even) : nat.
    destruct e.
    auto.
    Defined.
    

    The destruct tactic essentially pattern matches on e. Then, auto automatically uses the natural number inside to finish the definition.

    Here is a Gallina implementation of your first example:

    Example Ex : forall n : even, exists k, k + k = n :=
      fun n => match n with
      | exist _ n (ex_intro _ k eq) => ex_intro (fun k => k + k = n) k (eq_sym eq)
      end.
    

    Essentially, it pattern matches on n, retrieves the k and the proof that n = k + k, then uses eq_sym to flip the equality.

    Here is an implementation for Ex2:

    Example Ex2 : forall k, exists n : even, k + k = n :=
      fun k =>
      let n := k + k in
      let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
      let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
      ex_intro (fun n => k + k = even_to_nat n) even_nat eq_refl.
    

    exists_k is the proof contained inside an even number stating exists k, n + n = k. even_nat is an even number fulfilling the condition exists n, k + k = n, where n is obviously k + k. Finally, I inhabit the desired type. It seems that I can't use coercions here, so I explicitly use even_to_nat.

    Alternatively, the coercion works if I add a type annotation:

    Example Ex2 : forall k, exists n : even, k + k = n :=
      fun k =>
      let n := k + k in
      let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
      let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
      ex_intro (fun (n : even) => k + k = n) even_nat eq_refl.
    

    For your Ex' example, see the warning in this example from the coercion documentation. Given the coercion Coercion bool_in_nat : bool >-> nat.:

    Note that Check (true = O) would fail. This is "normal" behavior of coercions. To validate true=O, the coercion is searched from nat to bool. There is none.

    You can only coerce on the right side of the equality type, not the left.