Slide 1

Slide 1 text

証明しながらプログラミング! タクティックによるCoqプログラミング Zli 2023大LT 春 2023-05-14

Slide 2

Slide 2 text

自己紹介 学部3年 昨日までpixivの人と一緒に RubyKaigi(松本)に行ってました 趣味 ゲーム : Factorio, Simutrans なろう : たくさん 鉄道 : 乗り鉄(ライト層) Twitter: @sou7_ _ _ 好きな言語: Coq Ruby 2

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

今日話すこと プログラミングと数学の証明の話 証明しながらプログラミングする話 昨日まで動的型付け言語のカンファレンスに居たんですが、今日は型の話ばっかしま す(小声) 4

Slide 5

Slide 5 text

プログラミング(Elm) round : Float -> Int toString : Int -> String これらの関数を使って、 Float -> String の関数を作るにはどうするか froatToString : Float -> String froatToString x = toString (round x) 5

Slide 6

Slide 6 text

証明 仮定 仮定 を求める 定理 定理 6

Slide 7

Slide 7 text

プログラミングも、数学の証明も、大体一緒!? 1つ目: A -> B 2つ目: B -> C 求めたいものはA -> C AをA -> Bを使ってBに変換する BをB -> Cを使ってCに変換する 7

Slide 8

Slide 8 text

証明しながらプログラミングしてみよう From mathcomp Require Import ssreflect. Variables A B C : Type. Hypothesis HA_to_B : A -> B. (* 仮定A -> B *) Hypothesis HB_to_C : B -> C. (* 仮定B -> C *) HA_to_Bは A型を受け取ってB型を返す関数 であり AならばBという仮定 HB_to_Cも B型を受け取ってC型を返す関数 であり BならばCという仮定 8

Slide 9

Slide 9 text

証明っぽく書くとこう Theorem A_to_C : A -> C. move=> HA. (* 仮定Aを一旦どける *) apply HB_to_C. (* 仮定B -> Cを使う *) apply HA_to_B. (* 仮定A -> Bを使う *) exact HA. (* 仮定Aを使う *) Qed. 余談 : 高校などで習う証明は仮定から積み上げていく前向き推論が多いのですが、Coq では結論を崩して仮定に落としていく後ろ向き推論を使います。 9

Slide 10

Slide 10 text

生成されるプログラムはこう A_to_C = fun HA : A => HB_to_C (HA_to_B HA) : A -> C 証明していたら、いつの間にかプログラミングできちゃった!?!? 10

Slide 11

Slide 11 text

条件分岐 <-> 場合分け 関数呼び出しが出来たら、次は条件分岐もやりたい! 11

Slide 12

Slide 12 text

プログラミングの条件分岐 max : Int -> Int -> Int max a b = if a > b then a else b よく見る感じ! 12

Slide 13

Slide 13 text

数学の場合分け 仮定1: ほしいもの: かつ、 のとき、x=0なことを示す 仮定 の場合 の場合 仮定より なので、矛盾 13

Slide 14

Slide 14 text

条件分岐と場合分けって似てると思いません? 14

Slide 15

Slide 15 text

max関数をCoqで証明っぽく書いてみよう Require Import Arith Classical. Definition max (x y : nat): nat. Proof. case_eq (y <=? x) => H. (* y <=? x の結果はtrueまたはfalseになるので、それで場合分け *) - apply x. (* trueの場合、xを適用 *) - apply y. (* falseの場合、yを適用 *) Qed. 15

Slide 16

Slide 16 text

生成されたプログラム max = fun x y : nat => ((if y <=? x as b return ((y <=? x) = b -> nat) then fun _ : (y <=? x) = true => x else fun _ : (y <=? x) = false => y) : (y <=? x) = (y <=? x) -> nat) eq_refl : nat -> nat -> nat 16

Slide 17

Slide 17 text

ちょっと型エラーが出るので余計なやつを削り・・・ Definition max' := fun x y : nat => if y <=? x as b return ((y <=? x) = b -> nat) (* returnの後のは型が書いてあります *) then fun _ : (y <=? x) = true => x (* trueの場合、xを返す *) else fun _ : (y <=? x) = false => y. (* falseの場合、yを返す *) 実行! Eval compute in max' 3 2 _. (* = 3 : nat *) 17

Slide 18

Slide 18 text

発展 これまで、プログラムと証明が対応しているという話をしてきました => なら、どういうふうに対応しているのか 18

Slide 19

Slide 19 text

カリー・ハワード同形対応 プログラミングの世界 数学の世界 型 命題 プログラム 証明 条件分岐 場合分け 関数 AならばB それぞれ相互に変換できる! 関数プログラミング言語で関数の型を と書くのは、数学の記法と合わせるため 19

Slide 20

Slide 20 text

まとめ 証明とプログラミングは似ている Coqを使うと、証明をプログラムとして書ける Coqを使うと、プログラムを証明として書ける Coqは強力! Coqはなんでもできる! Coq勉強してみよう! 20

Slide 21

Slide 21 text

嘘。CoqはIOできないのでHello worldできない。 21