Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)

6,579 views

Published on

.NET基礎勉強会での発表資料です。

  • Be the first to comment

ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)

  1. 1. ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません) bleis-tift July 20, 2013
  2. 2. 自己紹介 id:bleis-tift / @bleis なごやではたらくゆるふわ.NETer 好きな関数型言語は F# Microsoft MVP for Visual F#
  3. 3. .NETの基礎ということで・・・ IL・・・?そんなこわいことこわい人がいっぱい 来ること確定な場所で話せません><。 .NET と言えば F#ですよねー (異論は認める F#の基礎と言えばラムダ計算ですよねー (.NET 基礎ならなごやこわいは参加しないだ ろうし、これにしよう!) どうしてこうなった・・・
  4. 4. 今日やること ラムダ計算って何? ラムダ計算で計算してみる ラムダ計算を拡張してみる ラムダ計算を知らない人を対象に、ラムダ計算が ナニモノなのかの感覚を掴んでもらうのが目的! こわい人がそこらじゅうにいるからgkbr
  5. 5. ラムダ計算って何?
  6. 6. その前に 関数型言語って何?
  7. 7. 関数型言語とは ある人曰く、「それぞれの人が色々な特徴か ら適当なサブセットを選んで関数型と呼ぶ」 ある人曰く、「永続的データ構造を扱う言 語だ」 ある人曰く、「そんなものはない。あるのは 関数プログラミングというスタイルだけだ」 「この言語は関数型言語だ!」という判断は各人に 任せるとして、個人的には「ラムダ計算に基づく 言語」は関数型言語でいいのでは?と思ってます。
  8. 8. よくある(かもしれない)誤解 「ラムダ計算に基づく言語」は関数型言語 → ラムダ式を持っていれば関数型言語だ? 今日はこの(ないかもしれない)誤 解を解きに来ました!
  9. 9. ラムダ計算とは すごくシンプルなプログラミング言語 文法がシンプル 予約語は λ だけ 関数しかない 真偽値も、数も、条件分岐も、ループも、全部関 数で表す 色々な関数型言語の基礎になっている
  10. 10. ラムダ計算の文法 ラムダ計算のプログラムは一つの項 (式と思って もらえれば) として表されます 項の要素になれるのは、以下の 3 つだけです 名前 ・・・・・・・・・・・変数 (項 項)・・・関数適用 (λ名前. 項)・・・ラムダ抽象 名前には、英字一文字を使うことが多いです。
  11. 11. ラムダ計算の項として有効なもの 以下の文字列の並びは、ラムダ計算の項として有 効です x (f x) (λx.x) (λf.(λx.(f x)))
  12. 12. カッコの省略 . .(λf.(λx.(f x))) の一番外側のカッコと一番内側のカッコは取り除 いても曖昧になりません。 . .λf.(λx.f x) 以降では、曖昧性のないカッコは省略します。
  13. 13. 文法のおさらい . ラムダ計算の文法 .. . t ::= < name > | (< t > < t >) | (λ < name > . < t >) 数値はおろか、真偽値などもない 変数が導入されるのはラムダ式の引数のみ 値はラムダ抽象 (つまり関数) のみ!
  14. 14. ラムダ計算の意味 文法を定義しただけでは何の役にも立たない ので、意味を与えてあげましょう!
  15. 15. ラムダ計算における計算 ラムダ計算における計算とは、引数に関数を適用 することです。 t1 t2 という項があった時に、t1 がラムダ抽象だっ た場合に、ラムダ抽象の中の項に現れる引数を t2 で置き換えます。 . 例えばこんな .. . (λx.x) (λy.λz.(y z)) ↓下線を引いた項に引数を与えて簡約 λy.λz.(y z)
  16. 16. 簡約の方法 簡約の方法にはいろいろありますが、ここでは皆 さんになじみの深い方法を採用します。 t1 t2 という項があった時、 t1 から先に簡約する t2 の簡約を終えてから、全体を簡約する という方法で、「値呼び戦略」と呼ばれます。
  17. 17. では・・・ 文法が分かり、意味も与えたところで、実際にこ れを使って計算してみましょう!
  18. 18. ラムダ計算で計算してみる
  19. 19. 無理・・・ 数も扱えないのにどうやって計算するんですか・・・ ということで、まずは道具を揃えましょう!
  20. 20. カリー化関数 ラムダ計算では複数引数を受け取る関数はないの で、関数を返す関数をよく使います。 . カリー化関数 λx.λy.x に λa.a と λb.b を渡す .. . (λx.λy.x) (λa.a) (λb.b) −→ (λy.(λa.a)) (λb.b) −→ λa.a λx.(λy.x) 自体は関数を返す関数だけど、2 つの引 数をとる関数と同じような働きをする!
  21. 21. カリー化関数の略記法 いちいちカリー化関数書くの面倒なので、略記法 を導入します。 . 上と下の記述は交換可能 .. . λx.λy.t λxy.t
  22. 22. 真偽値 関数で表しましょう。 . 真偽値を表す関数 .. . 真:λtf.t 偽:λtf.f なんでこれが真偽値?
  23. 23. 真偽値(2) 真が λtf.t、偽が λtf.f だったとして、 if cond then x else y を、cond x y とする cond に真を入れてみる ((λtf.t) x) y (λf.x) y x cond に偽を入れてみる ((λtf.f) x) y (λf.f) y y 真偽値として働いている!
  24. 24. 自然数 真偽値同様、関数で表現します。 . 自然数を表す関数 .. . 0:λsz.z 1:λsz.s z 2:λsz.s (s z) 3:λsz.s (s (s z))) z に s を何回適用するかで自然数を表します。 指で数を数えるのに似てますね。
  25. 25. 次の数を求める関数 succ . succ 関数 .. .λn.λsz.s (n s z) 1. 自然数 n は λsz.t の形をしている 2. n に s と z を渡せば、t の部分が取り出せる 3. t にもう一回 s を適用すれば、次の数になる!
  26. 26. 足し算してみる . add 関数 .. .λmn.λsz.m s (n s z) 1. 自然数 m は λsz.s (s (. . . (s z) . . . )) の形を している (s は m 個) 2. 自然数 n は λsz.t の形をしている (t には n 個の s が含まれる) 3. 自然数 m の z 部分を n の t 部分に入れ替え れば、足し算ができる!
  27. 27. 2 + 3 1. (λmn.λsz.m s (n s z)) (λsz.s (s z)) (λsz.s (s (s z))) 2. (λn.λsz.(λsz.s (s z)) s (n s z)) (λsz.s (s (s z))) 3. λsz.(λsz.s (s z)) s ((λsz.s (s (s z))) s z) 4. λsz.(λz.s (s z)) ((λsz.s (s (s z))) s z) 5. λsz.(λz.s (s z)) ((λz.s (s (s z))) z) 6. λsz.(λz.s (s z)) ((s (s (s z)))) 7. λsz.(λz.s (s z)) (s (s (s z))) 8. λsz.(s (s (s (s (s z))))) s が 5 個あるので、2 + 3 できました!
  28. 28. 掛け算してみる . mul 関数 .. .λmn.λsz.m (n s) z 1. 自然数 n は λsz.s (s (. . . (s z) . . . )) の形をし ている (s は n 個) 2. 自然数 n に s だけ適用したものは、引数に s を n 回適用する関数になる 3. それを自然数 m の s として渡すので、s を n 回適用したものが m 個作られる 4. それに z を渡してあげれば、 m と n を掛け合わせた結果の自然数になる!
  29. 29. 2 × 3 1. (λmn.λsz.m (n s) z) (λsz.s (s z)) (λsz.s (s (s z))) 2. (λn.λsz.(λsz.s (s z)) (n s) z) (λsz.s (s (s z))) 3. λsz.(λsz.s (s z)) ((λsz.s (s (s z))) s) z 4. λsz.(λsz.s (s z)) (λz.s (s (s z))) z 5. λsz.(λz.(λz.s (s (s z))) ((λz.s (s (s z))) z)) z 6. λsz.(λz.(λz.s (s (s z))) (s (s (s z)))) z 7. λsz.(λz.(s (s (s (s (s (s z))))))) z 8. λsz.(s (s (s (s (s (s z)))))) s が 6 個あるので、2 × 3 できました!
  30. 30. そのほかの計算 以下の話題は時間の関係上、省略します。 自然数の引き算、割り算 再帰 Church-Rosser 性
  31. 31. ラムダ計算を拡張してみる
  32. 32. ラムダ計算の拡張 さすがに、生のラムダ計算を扱うのはつらい →拡張しましょう!
  33. 33. 記法の拡張 2 + 3 を計算するだけで、 . 2 + 3 .. .(λmn.λsz.m s (n s z)) (λsz. s (s z)) (λsz.s (s (s z)))) つらい・・・
  34. 34. 数値の導入 数詞 (0 とか 1 とかそういうやつ) と関数で作った 自然数を対応付けることができる。 2 に対して λsz.s (s z)) を対応付けるようにすれ ば、人間にとってよりわかりやすい! ついでに、+ も λmn.λsz.m s (n s z) に対応付け てしまえば、2 + 3 はそのまま、 . .2 + 3 と記述できる! n に 2 を足す関数なら、 . .λn.n + 2 分かりやすい!
  35. 35. 真偽値の導入 ついでに真偽値も導入しましょう。 true と λtf.t を、false と λtf.f を対応付けます。 if-then-else も導入しましょう。 とりあえず、if cond then x else y を、cond x y に対応付けましょう。 . if-then-else を使った例 .. .λbmn.if b then m + n else m ∗ n b が真なら m + n を、偽なら m ∗ n を計算する 関数
  36. 36. 計算体系の拡張 記法だけじゃなくて、計算体系も拡張しましょう!
  37. 37. 型の導入 本当はここからの話をしようかな、と思ってたん ですが・・・ 色んな意味で時間がなかったので、ここからの拡 張は各自の課題ということで。 詳しくは、 をどうぞ!
  38. 38. 宣伝! この後の懇親会で、ちょうどその本の読書会があ るそうですよ! 興味のある人はオーム社のサイトから PDF 版を購 入して参加しましょう!

×