(* Needs Equations plugin to work. *) From Coq Require Import Arith Omega Program. From Equations Require Import Equations. Require Import Bvector. Module Equations. Equations neg (b : bool) : bool := neg true := false ; neg false := true. Lemma neg_inv : forall b, neg (neg b) = b. Proof. intros b. funelim (neg b); now simp neg. Defined. Inductive list {A} : Type := nil : list | cons : A -> list -> list. Arguments list : clear implicits. Notation "x :: l" := (cons x l). Equations tail {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. Equations tail' {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. (* The cases inside { } are recognized as record fields, which from an indentation perspective is OK *) Equations filter {A} (l : list A) (p : A -> bool) : list A := filter nil p := nil; filter (cons a l) p with p a => { | true := a :: filter l p ; | false := filter l p }. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { | true := a :: filter' l p ; | false := filter' l p }; filter' nil p := nil. Equations filter'' {A} (l : list A) (p : A -> bool) : list A := filter'' (cons a l) p with p a => { | true := a :: filter'' l p ; | false := filter'' l p }; filter'' nil p := nil. Equations unzip {A B} (l : list (A * B)) : list A * list B := unzip nil := (nil, nil) ; unzip (cons p l) with unzip l => { unzip (cons (pair a b) l) (pair la lb) := (a :: la, b :: lb) }. Equations equal (n m : nat) : { n = m } + { n <> m } := equal O O := left eq_refl ; equal (S n) (S m) with equal n m := { equal (S n) (S ?(n)) (left eq_refl) := left eq_refl ; equal (S n) (S m) (right p) := right _ } ; equal x y := right _. End Equations.