Coq case analysis and rewrite with function return

2019-05-10 07:02发布

问题:

I was working is this simple exercise about writing certified function using subset types. The idea is to first write a predecessor function

pred : forall  (n : {n : nat | n > 0}), {m : nat | S m = n.1}.

and then using this definition give a funtion

pred2 : forall (n : {n : nat | n > 1}), {m : nat | S (S m) = n.1}.

I have no problem with the first one. Here is my code

Program Definition pred (n : {n : nat | n > 0}) : {m : nat | S m = n.1} :=
  match n with
  | O => _
  | S n' => n'
  end.
Next Obligation. elimtype False. compute in H. inversion H. Qed.

But I cannot workout the second definition. I trying to write these definition

Program Definition pred2 (n : {n : nat | n > 1}) : {m : nat | S (S m) = n.1} 
:= pred (pred n).

I managed to prove the two first obligations

Next Obligation. apply (gt_trans n 1 0). assumption. auto. Qed.
Next Obligation. 
  destruct pred.  
  simpl.
  simpl in e. 
  rewrite <- e in H.
  apply gt_S_n in H; assumption.
Qed.

But for the last obligation I get stuck because when I try to do a case analysis for the return type of pred the new hypotesis are not rewrited in the goal.

I tried the following tactics with no results.

destruct (pred (n: pred2_obligation_1 (n ; H))).

destruct (pred (n; pred2_obligation_1 (n ; H))) eqn:?.
rewrite Heqs.

I know that I can with write pred2 directly, but the idea is to use and compose the function pred.

回答1:

The reason destruct doesn't have any effect is probably because what you're trying to do case analysis on doesn't occur in the goal. The implicit arguments of that term probably don't match the implicit arguments of the term in the goal. Either way, you can't do case analysis on that term without making the goal ill-typed.

But you can prove that obligation by case analysis on n.

Next Obligation.
destruct n.
inversion H.
destruct n.
inversion H.
subst.
inversion H1.
cbn.
eauto.
Qed.

I was also able to prove some helper theorems, but I wasn't able to use them because of all the type dependency.

Theorem T1 : forall s1, S (` (pred s1)) = ` s1.
Proof. intros [[| n1] H1]. inversion H1. cbn. eauto. Qed.

Theorem T2 : forall T1 (P1 : T1 -> Prop) s1 H1, (forall x1 (H1 H2 : P1 x1), H1 = H2) -> exist P1 (` s1) H1 = s1.
Proof. intros ? ? [x1 H1] H2 H3. cbn in *. rewrite (H3 _ H1 H2). eauto. Qed.

I had never seen destruct used on a function. I'm surprised Coq doesn't complain that that function isn't inductively defined.