Search code examples
coqcoq-tactic

deriving facts on pattern matching in coq


Consider the following program

Definition useGt0 (n: nat) (witness: n > 0) : nat :=
  10.


Definition createGt0(n: nat) : nat :=
  match n with
  | O => 42
  | S(n') => useGt0 n  (#???)
  end.

Clearly, n > 0 is inhabited, because n = S n'. However, how do I get access to the proof that n = S n'? From n = S n', we can derive that n > 0.

In general, I wish to understand: How do I extract information from a pattern match?


Solution

  • The standard way to define createGt0 function is to use the convoy pattern (you can find several explanations using [coq] [convoy-pattern] search query on Stackoverflow). The standard link is A. Chlipala's CPDT book.

    Here is a solution:

    Definition createGt0 (n : nat) : nat :=
      match n as x return (n = x -> nat) with
      | O => fun _ => 42
      | S n' => fun E => useGt0 n (eq_ind_r (fun n => n > 0) (gt_Sn_O n') E)
      end eq_refl.
    

    Another option is to use Program mechanism, which lets you program in non-dependently-typed style, deferring proof obligations until a later time:

    Require Import Program.
    
    Program Definition createGt0 (n : nat) : nat :=
      match n with
      | O => 42
      | S n' => useGt0 n _
      end.
    Next Obligation. apply gt_Sn_O. Qed.
    

    At last, you could use tactics to build your function:

    Definition createGt0 (n : nat) : nat.
    Proof.
      destruct n eqn:E.
      - exact 42.
      - refine (useGt0 n _).
        rewrite E.
        apply gt_Sn_O.
    Defined.
    

    If you end your function with Qed, Coq will consider it opaque and won't reduce. Try ending the function with both Qed and Defined and execute the following command:

    Compute createGt0 0.