Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
(* Inductive bool := true | false. Inductive nat := O : nat | S : nat -> nat. Inductive list A := nil : list A | cons : A -> list A -> list A. *) Definition negb b := match b with | true => false | false => true end. Eval vm_compute in (negb true). Eval vm_compute in (negb false). Eval vm_compute in (negb (negb true)). (* Definition wrong_negb b := match b with | true => false end. Error: Non exhaustive pattern-matching: no clause found for pattern false *) (* Definition wrong_negb b := match b with | true => false | true => true | false => true end. Error: This clause is redundant. *) (* Beware of the misspelling : ttrue below is read as a pattern variable! Definition wrong_negb b := match b with | ttrue => false | false => true end. *) Definition pred x := match x with | S x => x | O => O end. Definition iszero x := match x with | O => true | _ => false (* or: | S _ => false *) end. Definition istwo x := match x with | S (S O) => true (* or: | 2 => true *) | _ => false end. Unset Printing Matching. (* prevent Coq attempts to pretty-print things *) Print istwo. Definition andb b1 b2 := match b1, b2 with | true, true => true | _, _ => false end. Print andb. (* Exercise: write andb with only one simple match *) Definition simplier_andb (b1 b2:bool) := if b1 then b2 else false. (** Recursion *) Fixpoint div2 n := match n with | S (S n') => S (div2 n') (* (n'+2)/2 = n'/2+1 *) | _ => O (* n is 0 or 1 *) end. (*Fixpoint div2_ko n := if leb n 1 then 0 else S (div2_ko (n-2)).*) Eval vm_compute in (div2 13). Fixpoint plus n m := match n with | O => m | S n' => S (plus n' m) (* (n+1)+m = (n+m)+1 *) end. Eval vm_compute in (plus 5 6). (* Exercise: - define an div2sup function that return ceil(n/2) instead of floor(n/2) - check experimentally that for all n below 1000, plus (div2 n) (div2sup n) is n - how could we write a div3 ? Is it possible to write a div this way ? *) Fixpoint div2sup n := match n with | S (S n') => S (div2sup n') | n => n end. (* or *) Definition div2sup' n := div2 (S n). Eval vm_compute in (div2sup 3). Fixpoint check_forall_below (f:nat->bool)(n:nat) := match n with | 0 => true | S n' => andb (f n') (check_forall_below f n') end. Require Import EqNat Eval vm_compute in check_forall_below (fun n => beq_nat (div2sup' n) (div2sup n)) 1000. Eval vm_compute in check_forall_below (fun n => beq_nat n (div2 n + div2sup n)) 1000. (** Later, you'll be able to _prove_ these kind of statements for all numbers. *) Require Import Omega. Lemma div2sup_equiv : forall n, div2sup n = div2sup' n. Proof. induction n using lt_wf_ind. destruct n. reflexivity. unfold div2sup'. simpl. destruct n. reflexivity. f_equal. apply H; auto. Qed. Lemma div2_plus_div2sup : forall n, div2 n + div2sup n = n. Proof. induction n using lt_wf_ind. destruct n. reflexivity. destruct n. reflexivity. simpl. rewrite <- plus_n_Sm. do 2 f_equal. apply H; auto. Qed. (** More functions about numbers: *) Fixpoint mult n m := match n with | O => O | S n' => plus m (mult n' m) end. Fixpoint minus n m := match n with | O => O | S n' => match m with | O => n | S m' => minus n' m' end end. Fixpoint minus_bis n m := match n, m with | S n', S m' => minus_bis n' m' | _, _ => n end. Fixpoint nat_beq n m := match n, m with | O, O => true | S n', S m' => nat_beq n' m' | _, _ => false end. Fixpoint leb n m := match n, m with | O, _ => true | _, O => false | S n', S m' => leb n' m' end. (** Recursion over lists *) Open Scope list_scope. (* for having :: *) Set Implicit Arguments. Fixpoint length A (l : list A) := match l with | nil => O | _ :: l' => S (length l') end. (** NB: without Implicit Arguments, we should write (lenght A l') even if type A can be inferred automatically. *) Fixpoint app A (l1 l2 : list A) := match l1 with | nil => l2 | a :: l1' => a :: (app l1' l2) end. (** With fold_right, computation starts at the end of the list: fold_right f init (a::b::c::nil) = f a (f b (f c init)) *) Fixpoint fold_right A B (f:B->A->A) (init:A) (l:list B) : A := match l with | nil => init | x :: l' => f x (fold_right f init l') end. Eval vm_compute in fold_right plus 0 (1::2::3::nil). (* = (1+(2+(3+0))) *) Eval vm_compute in fold_right (fun x l => x::l) nil (1::2::3::nil). (* = 1::2::3::nil *) (** With fold_left, computation starts at the top of the list: fold_left f (a::b::c::nil) init = f (f (f init a) b) c *) Fixpoint fold_left A B (f:A->B->A) (l:list B) (init:A) : A := match l with | nil => init | x :: l' => fold_left f l' (f init x) end. Eval vm_compute in fold_left plus (1::2::3::nil) 0. (* = (((0+1)+2)+3) *) Eval vm_compute in fold_left (fun l x => x::l) (1::2::3::nil) nil. (* = 3::2::1::nil *) (* Exercise : define map filter seq rev combine *) (* Exercise : give an alternate definition of vec_prod (of session 1) without using fold_right or combine. *) Fixpoint vec_prod l1 l2 := match l1, l2 with | x1::l1', x2::l2' => x1 * x2 + vec_prod l1' l2' | _, _ => 0 end. (* Conversely, write map filter rev by using fold_right or fold_left *) (** Merge sort *) Fixpoint split A (l : list A) : list A * list A := match l with | nil => (nil, nil) | a::nil => (a::nil, nil) | a::b::l' => let (l1, l2) := split l' in (a::l1, b::l2) end. Eval vm_compute in split (1::2::3::4::5::nil). (** Exercise : what is length (fst (dispatch l)) ? Same for snd ? *) Definition merge A (less:A->A->bool) : list A -> list A -> list A := fix merge l1 := match l1 with | nil => fun l2 => l2 | x1::l1' => fix merge_l1 l2 := match l2 with | nil => l1 | x2::l2' => if less x1 x2 then x1 :: merge l1' l2 else x2 :: merge_l1 l2' end end. Definition mergeloop A (less:A->A->bool) := fix loop (l:list A) (n:nat) := match n with | O => nil | S n => match l with | nil => l | _::nil => l | _ => let (l1,l2) := split l in merge less (loop l1 n) (loop l2 n) end end. (** Invariant above: n >= length l *) Definition mergesort A less (l:list A) := mergeloop less l (length l). Eval vm_compute in mergesort leb (4::2::6::3::9::1::nil). (** Exercise: what happen if we remove the "| _::nil => l" in mergeloop ? *) (** Exercise: define a nat_iter ? a nat_rect ? give the intuition that all recursion/matching over nat can be done via nat_rect... *)