情報科学概論 第4回 1 Poly 〜多相性と高階関数〜 2 多相性 3 単相的 vs 多相的なリスト Inductive natlist : Type := | nil : natlist | cons : nat → natlist → natlist. Inductive boollist : Type := | bool_nil : boollist | bool_cons : bool → boollist → boollist. : : Inductive list (X:Type) : Type := | nil : list X | cons : X list → list X → list X. は,型 X を取り帰納的な定義を返す関数と考えるとよい 4 多相的なコンストラクタ Check nil. (* ===> nil : ∀X : Type, list X *) Check cons. (* ===> cons : ∀X : Type, X -> list X -> list X *) Check (cons nat 2 (cons nat 1 (nil nat))). 5 多相的な関数の例 Fixpoint length (X:Type) (l:list X) : nat := match l with | nil => 0 | cons h t => S (length X t) end. 型の注釈は あってはならない 適切な型を 引数に与える Example test_length1 : length nat (cons nat 1 (cons nat 2 (nil nat))) = 2. Example test_length2 : length bool (cons bool true (nil bool)) = 1. 前回のリスト上の関数も再定義できる 6 型推論 Fixpoint app (X : Type) (l1 l2 : list X) : (list X) := match l1 with | nil => l2 | cons h t => cons X h (app X t l2) end. 型の注釈を省略 Fixpoint app' X l1 l2 : list X := match l1 with | nil => l2 | cons h t => cons X h (app' X t l2) end. app と app' は同じ型 forall X : Type, list X -> list X -> list X 7 引数の合成と暗黙的引数 Definition list123 := cons nat 1 (cons nat 2 (cons nat 3 (nil nat))). 合成 Definition list123' := cons _ 1 (cons _ 2 (cons _ 3 (nil _))). Arguments nil {X}. 暗黙的引数 Arguments cons {X} _ _. Notation "[ ]" := nil. Notation "[ x , .. , y ]" := (cons x .. (cons y []) ..). Definition list123''' := [1, 2, 3]. 8 練習:多相型リスト Fixpoint repeat (X : Type) (n : X) (count : nat) : list X := match count with | 0 => [] | S count' => n :: repeat _ n count' end. 9 その他の多相的なデータ型(自習) • 組 • オプション 10 データとしての関数 11 高階関数 1. 引数として渡せる 2. 結果として返せる 3. データ構造に格納できる • Coqでは、関数が第1級の市民 • 高階関数:他の関数を処理する関数 Definition doit3times {X:Type} (f:X→X) (n:X) : X := f (f (f n)). Example test_doit3times: doit3times minustwo 9 = 3. Example test_doit3times': doit3times negb true = false. 12 部分適用 Check plus. (* ==> nat -> nat -> nat *) Definition plus3 := plus 3. 適用の結果は 関数 13 高階関数の例:フィルタ Fixpoint filter {X:Type} (test: X→bool) (l:list X) : (list X) := match l with | [] => [] | h :: t => if test h then h :: (filter test t) else filter test t end. Example test_filter1: filter evenb [1,2,3,4] = [2,4]. 偶数か? 14 無名関数 Example test_anon_fun': doit3times (fun n => n * n) 2 = 256. 無名関数 • 高階関数の引数には一度しか使わない関数が頻出する • 一度しか使わない関数には無名関数を使うと良い 15 高階関数の例:map Fixpoint map {X Y:Type} (f:X→Y) (l:list X) : (list Y) := match l with | [] => [] | h :: t => (f h) :: (map f t) end. Example test_map1: map (plus 3) [2,0,2] = [5,3,5]. 16 練習:flat_map flat_map (fun n => [n,n+1,n+2]) [1,5,10] = [1, 2, 3, 5, 6, 7, 10, 11, 12]. Fixpoint concat {X : Type} (l:list (list X)) : (list X) := match l with | [] => [] | h :: t => app h (concat t) end. Fixpoint flat_map {X Y:Type} (f:X→list Y) (l:list X) : (list Y) := concat (map f l). 17 高階関数の例:fold cf. Google's map/reduce Fixpoint fold {X Y:Type} (f: X→Y→Y) (l:list X) (b:Y) : Y := match l with | nil => b | h :: t => f h (fold f t b) end. fold plus [1,2,3,4] 0 → 1 + (2 + (3 + (4 + 0))) 18 関数を構築する関数 定数関数 Definition constfun {X: Type} (x: X) : nat→X := fun (k:nat) => x. 常にtrue Definition ftrue := constfun true. Example constfun_example1 : ftrue 0 = true. Example constfun_example2 : (constfun 5) 99 = 5. 19 関数を構築する関数 Definition override {X: Type} 通常は f (f: nat→X) (k:nat) (x:X) : nat→X:= fun (k':nat) => if beq_nat k k' then x else f k'. 引数が k のときは 何もしない Definition fmostlytrue := override (override ftrue 1 false) 3 false. Example Example Example Example override_example1 override_example2 override_example3 override_example4 : : : : fmostlytrue fmostlytrue fmostlytrue fmostlytrue 0 1 2 3 = = = = true. false. true. false. 20 練習:何を表しているか Theorem override_example : ∀(b:bool), (override (constfun b) 3 true) 2 = b. • 引数が 3 のときはtrue を返す • そうでないときは引数に constfun b を適用する (bを返す) 21 Coq をさらに詳しく 22 apply タクティック Theorem silly1 : ∀(n m o p : nat), n = m → [n,o] = [n,p] → [n,o] = [m,p]. Proof. intros n m o p eq1 eq2. rewrite ← eq1. (* これまでと同様に "rewrite → eq2. reflexivity." で終えられる。 しかし、同じ結果が apply タクティック1つで得られる *) apply eq2. Qed. 23 unfold タクティック Theorem unfold_example : ∀m n, 3 + n = m → plus3 n + 1 = m + 1. Proof. Coq は自動で intros m n H. plus3 を展開しない unfold plus3. rewrite → H. reflexivity. Qed. 24 Inversion タクティック Inductive nat : Type := | O : nat | S : nat → nat. • コンストラクタSは単射 • O と S は disjoint 25 Inversion タクティック 仮定のひとつ c a1 a2 ... an = d b1 b2 ... bm • c = d のとき, a1 = b1, a2 = b2, ... を仮定に追加 • c <> d のとき,仮定が false 26 Inversion タクティックの例 Theorem eq_add_S : ∀(n m : nat), S n = S m → n = m. Proof. intros n m eq. inversion eq. reflexivity. Qed. ∀(n → Theorem silly4 : m : nat), [n] = [m] n = m. Proof. intros n o eq. inversion eq. reflexivity. Qed. 27 練習:Inversion Example sillyex1 : ∀(X : Type) (x y z : X) (l j : list X), x :: y :: l = z :: j → y :: l = x :: j → x = y. Proof. intros X x y z l j ex1 ex2. inversion ex1. inversion ex2. rewrite H0. reflexivity. Qed. 28 IHの工夫 Theorem beq_nat_eq_FAILED : ∀n m, true = beq_nat n m → n = m. Proof. intros n m H. induction n as [| n']. Case "n = 0". destruct m as [| m']. SCase "m = 0". reflexivity. SCase "m = S m'". simpl in H. inversion H. Case "n = S n'". destruct m as [| m']. SCase "m = 0". simpl in H. inversion H. SCase "m = S m'". apply eq_remove_S. (* 手詰まり...IHが特殊な m について言及 *) Admitted. 29 IHの工夫 true = beq_nat n' m → n' = m . ある m について ∀ m : nat, true = beq_nat n' m → n' = m 任意の m について 30 IHの工夫 Theorem beq_nat_eq : ∀n → m, true = beq_nat n m n = m. m は文脈に移動しない Proof. intros n. induction n as [| n']. Case "n = 0". intros m. destruct m as [| m']. SCase "m = 0". reflexivity. SCase "m = S m'". simpl. intros contra. inversion contra. Case "n = S n'". intros m. destruct m as [| m']. SCase "m = 0". simpl. intros contra. inversion contra. SCase "m = S m'". simpl. intros H. apply eq_remove_S. apply IHn'. apply H. Qed. 31 仮定にタクティックを使う simpl in H : 仮定 H を単純化 apply L in H : 仮定 H に条件文 L を適用 L1 → L2 : L1 を L2 に書換え 32 その他のタクティック • 複合式の上に destruct を用いる • remember • apply ... with ... 33 復習 34 • これまで見たタクティック – intros, reflexivity, apply, apply... in H, apply... with..., simpl, simpl in H, rewrite, rewrite ... in H, symmetry, symmetry in H, unfold, unfold... in H, destruct... as..., induction... as..., inversion, remember (e) as x, assert (e) as H – 大体のことが可能 • 今後,導入するタクティック – それほど多くない量 – automationタクティック 35 Gen 〜IHの一般化〜 36 IHの選定 Theorem double_injective_FAILED : ∀n m, double n = double m → n = m. うまくいかない Proof. intros n m. induction n as [| n']. Case "n = O"... P n = "if double n = double m, then n = m" •P O (i.e., "if double O = double m then O = m") •P n → P (S n) (i.e., "if double n = double m then n = m" implies "if double (S n) = double m then S n = m"). 37 IHの選定 Theorem double_injective_FAILED : ∀n m, double n = double m → n = m. うまくいく Proof. intros n. induction n as [| n']. Case "n = O"... P n = "for any m, if double n = double m, then n = m" •P O (i.e., "if double O = double m then O = m") •P n → P (S n) (i.e., "for any m, if double n = double m then n = m" implies "for any m, if double (S n) = double m then S n = m"). 38 IHの選定(今度はmで) Theorem double_injective_take2_FAILED : m, double n = double m → n = m. Proof. intros n m. induction m as [| m']. Case "m = O"... うまくいかない ∀n P n = "if double n = double m, then n = m" •P O (i.e., "if double O = double m then O = m") •P m → P (S n) (i.e., "if double n = double m then n = m" implies "if double (S n) = double m then S n = m"). 39 IHの一般化 Theorem double_injective_take2 : ∀n m, double n = double m Proof. intros n m. generalize dependent n. induction m as [| m']. Case "m = O"... → n = m. うまくいく 40
© Copyright 2024 ExpyDoc