Nested recursion and `Program Fixpoint` or `Function`

后端 未结 3 1555
借酒劲吻你
借酒劲吻你 2020-12-31 16:14

I’d like to define the following function using Program Fixpoint or Function in Coq:

Require Import Coq.Lists.List.
Import ListNota         


        
3条回答
  •  悲哀的现实
    2020-12-31 17:17

    In general, it might be advisable to avoid this problem. But if one really wants to obtain the proof obligation that Isabelle gives you, here is a way:

    In Isabelle, we can give an external lemma that stats that map applies its arguments only to members of the given list. In Coq, we cannot do this in an external lemma, but we can do it in the type. So instead of the normal type of map

    forall A B, (A -> B) -> list A -> list B
    

    we want the type to say “f is only ever applied to elements of the list:

    forall A B (xs : list A), (forall x : A, In x xs -> B) -> list B
    

    (It requires reordering the argument so that the type of f can mention xs).

    Writing this function is not trivial, and I found it easier to use a proof script:

    Definition map {A B} (xs : list A) (f : forall (x:A), In x xs -> B) : list B.
    Proof.
      induction xs.
      * exact [].
      * refine (f a _ :: IHxs _).
        - left. reflexivity.
        - intros. eapply f. right. eassumption.
    Defined.
    

    But you can also write it “by hand”:

    Fixpoint map {A B} (xs : list A) : forall (f : forall (x:A), In x xs -> B), list B :=
      match xs with
       | [] => fun _ => []
       | x :: xs => fun f => f x (or_introl eq_refl) :: map xs (fun y h => f y (or_intror h))
      end.
    

    In either case, the result is nice: I can use this function in mapTree, i.e.

    Program Fixpoint mapTree (f : nat -> nat) (t : Tree)  {measure (height t)} : Tree :=
      match t with 
        Node x ts => Node (f x) (map ts (fun t _ => mapTree f t))
      end.
    Next Obligation.
    

    and I don’t have to do anything with the new argument to f, but it shows up in the the termination proof obligation, as In t ts → height t < height (Node x ts) as desired. So I can prove that and define mapTree:

      simpl.
      apply Lt.le_lt_n_Sm.
      induction ts; inversion_clear H.
      - subst. apply PeanoNat.Nat.le_max_l.
      - rewrite IHts by assumption.
        apply PeanoNat.Nat.le_max_r.
    Qed.
    

    It only works with Program Fixpoint, not with Function, unfortunately.

提交回复
热议问题