Successfully reported this slideshow.                                                                                              Upcoming SlideShare
×

（Lambdaだけで） 純LISPのような ナニかを作る

1,872 views

Published on

ラムダ式で純LISPに近いものを組み上げます

Published in: Engineering
• Full Name
Comment goes here.

Are you sure you want to Yes No • Be the first to comment

• Be the first to like this

（Lambdaだけで） 純LISPのような ナニかを作る

1. 1. （Lambdaだけで） 純LISPのような ナニかを作る @maruuusa83 Daichi Teruya Okinawa National Collage of Technology
2. 2. λ 2 自己紹介 • まるさ(@maruuusa83) • 沖縄高専メディア科5年生
3. 3. λ 3 自己紹介
4. 4. λ 4 自己紹介
5. 5. λ 5 自己紹介
6. 6. アジェンダ • 自己紹介 • 今回やることとか色々 • 特殊形式の定義 • CONS, CAR, CDR • COND • データ構造の定義 • CONDの定義 • EQ • 値の定義 • EQの定義 λ 6
7. 7. • かなりいい加減な独自研究に満ちています！ • 初心者の嘘だと思って聞いてください・・・ λ 7
8. 8. λ λ 8
9. 9. 휷 λ 9 今回やること
10. 10. （Lambdaだけで） 純LISPのような ナニかを作る λ 10
11. 11. λ 11
12. 12. 予約語4つの言語 でLISPを作る lambda, ., quote, ::= λ 12
13. 13. どんな言語？？ λ 13
14. 14. どんな言語？？ • 今回は、Lambda項を用いたLambda計算を指す λ 14
15. 15. どんな言語？？ • 今回は、Lambda項を用いたLambda計算を指す • こういうやつ： λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 훽 λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 훽 λ푧. 푧푎푏 λ푥푦. 푥 훽 λ푥푦. 푥 푎 푏 훽 푎 λ 15
16. 16. どんな言語？？ • 今回は、Lambda項を用いたLambda計算を指す • こういうやつ： λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 훽 λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 훽 (λ푧. 푧푎푏) λ푥푦. 푥 훽 (λ푥푦. 푥) 푎 푏 훽 푎 λ 16
17. 17. どんな言語？？ • 今回は、Lambda項を用いたLambda計算を指す • こういうやつ： λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 훽 λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 훽 (λ푧. 푧푎푏) λ푥푦. 푥 훽 (λ푥푦. 푥) 푎 푏 훽 푎 ( ﾟДﾟ)ﾊｧ? λ 17
18. 18. どんな言語？？ • Lambda項を言語らしく起こした（！） λ 18
19. 19. どんな言語？？ • Lambda項を言語らしく起こした（！） ( ＾ω＾) <ここに項があるじゃろ？ ⊃ λ푥푦. 푥 푎 푏 ⊂ λ 19
20. 20. どんな言語？？ • Lambda項を言語らしく起こした（！） ( ＾ω＾) <ここに項があるじゃろ？ ⊃ λ푥푦. 푥 푎 푏 ⊂ ( ՞ਊ ՞) <こうじゃ！ ⊃ ((lambda x.(lambda y.x)) a) b) ⊂ λ 20
21. 21. どんな言語？？ • Lambda項を言語らしく起こした（！） ( ＾ω＾) <ここに項があるじゃろ？ ⊃ λ푥푦. 푥 푎 푏 ⊂ ＿人人人人＿ ＞ 腕が＜ ￣Y^Y^Y￣ ( ՞ਊ ՞) <こうじゃ！ ⊃ ((lambda x.(lambda y.x)) a) b) ⊂ λ 21
22. 22. 処理系書きました！！１ • 対話型の処理系 • ラムダ項を与えるとラムダ計算します λ 22 URL : http://lmd.maruuusa.tk/ Github : maruuusa83/lambda_evaluator
23. 23. 予約語の数 "lambda" { return (LAMBDA); } "quote " { return (QUOTE); } "::=" { return (DEFUN); } "." { return (PERIOD); } "(" { return (LP); } ")" { return (RP); } "n" { return (CR); } [a-z][0-9]? { lambda.l yylval.identifier = lambda_create_identifier(yytext); return (IDENTIFIER); } [_A-Z][_A-Za-z0-9]* { yylval.name = lambda_create_identifier(yytext); return (NAME); } λ 23
24. 24. 予約語の数 "lambda" { return (LAMBDA); } "quote " { return (QUOTE); } "::=" { return (DEFUN); } "." { return (PERIOD); } "(" { return (LP); } ")" { return (RP); } "n" { return (CR); } [a-z][0-9]? { lambda.l yylval.identifier = lambda_create_identifier(yytext); return (IDENTIFIER); } [_A-Z][_A-Za-z0-9]* { yylval.name = lambda_create_identifier(yytext); return (NAME); } λ 24
25. 25. 純LISPってなんぞ λ 25
26. 26. 純LISPってなんぞ • 最小限の関数とプリミティブのみのLISP • これは自身の処理系を記述できる最低限の構 成 λ 26
27. 27. 純LISPってなんぞ • 最小限の関数とプリミティブのみのLISP • これは自身の処理系を記述できる最低限の構 成 λ 27 5つの基本関数 cons, car, cdr eq, atom 4つの特殊形式 lambda, cond, define, quote
28. 28. Lambda計算について 휷
29. 29. Lambda項について • Lambda計算の対象となるのはLambda項のみ λ 29
30. 30. Lambda項について • Lambda計算の対象となるのはLambda項のみ • 変数푥0,푥1,푥2,…は、lambda項 • 푥が変数、푀がlambda項のとき、(λ푥. 푀)はlambda項 • 푀と푁がともにlambda項のとき、(푀 푁)はlambda項 λ 30
31. 31. Lambda項について • Lambda計算の対象となるのはLambda項のみ • 変数푥0,푥1,푥2,…は、lambda項 • 푥が変数、푀がlambda項のとき、(λ푥. 푀)はlambda項 • 푀と푁がともにlambda項のとき、(푀 푁)はlambda項 （項を定義するだけではよくわからない・・・） λ 31
32. 32. Lambda計算規則 λ 32
33. 33. Lambda計算規則 • β-簡約 項がλ푥. 푀 푁のような形をとるとき、 項푀の内部にある変数푥を푁で置き換える • 代入は次のように定義する • 푥 푥 ≔ 푁 ≡ 푁 • 푦 푥 ≔ 푁 ≡ 푦 • 퐿 푀 푥 ≔ 푁 ≡ 퐿 푥 ≔ 푁 푀 푥 ≔ 푁 • λ푦. 푀 푥 ≔ 푁 ≡ λ푧. ( 푀 푦 ≔ 푧 푥 ≔ 푁 ) λ 33
34. 34. 計算例 ((lambda x.x) a) -> (a) 単純に代入 λ 34
35. 35. 計算例 ((lambda x.x) a) -> (a) 単純に代入 何でも代入できる ((lambda x.x) (lambda y.y)) -> (lambda y.(y)) λ 35
36. 36. 計算例 ((lambda x.x) a) -> (a) 単純に代入 何でも代入できる ((lambda x.x) (lambda y.y)) -> (lambda y.(y)) 変数名が衝突すると その先置換しない ((lambda x.(lambda x.x)) a) -> (lambda x.(x)) λ 36
37. 37. 間違えやすい例 Ｘ(x y z) ○((x y) z) 含めるのは2項のみ。 基本は左側結合 λ 37
38. 38. 間違えやすい例 Ｘ(x y z) ○((x y) z) 含めるのは2項のみ。 基本は左側結合 Ｘ(lambda xy.yx) ○(lambda x.(lambda y.(y x))) 省略は認めていない λ 38
39. 39. 間違えやすい例 Ｘ(x y z) ○((x y) z) 含めるのは2項のみ。 基本は左側結合 Ｘ(lambda xy.yx) ○(lambda x.(lambda y.(y x))) Ｘ(lambda x.(x)) ○(lambda x.x) 省略は認めていない ごめんなさい、 処理系の仕様です； λ 39
40. 40. LISPの定義:特殊形式 휷 λ 40
41. 41. 必要な特殊形式 • lambda, quote, define, condが必要
42. 42. 必要な特殊形式 • lambda, quote, define, condが必要 • quoteは「評価しない」を指示 • (quote ((lambda x.x) a)) -> ((lambda x.(x)) (a))
43. 43. 必要な特殊形式 • lambda, quote, define, condが必要 • quoteは「評価しない」を指示 • (quote ((lambda x.x) a)) -> ((lambda x.(x)) (a)) • defineは無名関数に名前を与える • FUNC ::= (lambda x.x) • (FUNC a) -> (a)
44. 44. 必要な特殊形式 • lambda, quote, define, condが必要 • quoteは「評価しない」を指示 • (quote ((lambda x.x) a)) -> ((lambda x.(x)) (a)) • defineは無名関数に名前を与える • FUNC ::= (lambda x.x) • (FUNC a) -> (a) あとはcondだけ！（笑）
45. 45. condとな • cond：C言語でいうswitch-case文 • かなり複雑になりそうなのでIF文に・・・ λ 45
46. 46. condとな • cond：C言語でいうswitch-case文 • かなり複雑になりそうなのでIF文に・・・ • λ푥푦푞. 푞푥푦って感じ？ q:選択子x:THEN y:ELSE • IF ::= (lambda x.(lambda y.(lambda q.((q x) y)))) λ 46
47. 47. condとな • cond：C言語でいうswitch-case文 • かなり複雑になりそうなのでIF文に・・・ • λ푥푦푞. 푞푥푦って感じ？ q:選択子x:THEN y:ELSE • IF ::= (lambda x.(lambda y.(lambda q.((q x) λ 47 y)))) • TRUE ::= (lambda x.(lambda y.x)) • FALSE ::= (lambda x.(lambda y.y))
48. 48. condとな • cond：C言語でいうswitch-case文 • かなり複雑になりそうなのでIF文に・・・ TRUEは一つ目の引数、 FALSEは二つ目の引数を返す • λ푥푦푞. 푞푥푦って感じ？ q:選択子x:THEN y:ELSE • IF ::= ということに注目！！！ (lambda x.(lambda y.(lambda q.((q x) y)))) • TRUE ::= (lambda x.(lambda y.x)) • FALSE ::= (lambda x.(lambda y.y)) λ 48
49. 49. condとな • ついでに論理演算子も定義する λ 49
50. 50. condとな • ついでに論理演算子も定義する • NOT ::= (lambda q.((q FALSE) TRUE)) λ 50
51. 51. condとな • ついでに論理演算子も定義する • NOT ::= (lambda q.((q FALSE) TRUE)) • AND ::= (lambda p.(lambda q.((p q) FALSE))) • OR ::= (lambda p.(lambda q.((p TRUE) q))) λ 51
52. 52. LISPの定義:標準関数 휷 λ 52
53. 53. cons, car, cdr • car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ？
54. 54. cons, car, cdr • car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ？ • (CAR ((CONS a) b))という感じにしたい • が、最左（名前呼び）戦略なので CARの評価時点でCONSが未評価になってしまう
55. 55. cons, car, cdr • car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ？ • (CAR ((CONS a) b))という感じにしたい • が、最左（名前呼び）戦略なので CARの評価時点でCONSが未評価になってしまう • λ푧. (푧 λ푥푦. 푥) としてCONSを左へ！ • CAR ::= (lambda z.(z (lambda x.(lambda y.x))))
56. 56. cons, car, cdr • consに値呼びを名前呼びに戻す力を持たせる • λ푥푦푧. 푧푥푦 として最後に評価項をとる CONS ::= (lambda x.(lambda y.(lambda z.((z x) y)))) λ 56
57. 57. eqとequalの定義・・・ λ 57
58. 58. eqとequalの定義・・・ かなりややこしい！ （時間がない！！！！） λ 58
59. 59. データ構造の定義：LIST • eq, atomを定義したい • が、(M N)がデータ構造だとかなり扱いにくい • CONSの定義を右側結合でそのまま使う！ • ただし、必ず末尾にNIL::=FALSEを含む λ 59
60. 60. データ構造の定義：LIST • eq, atomを定義したい • が、(M N)がデータ構造だとかなり扱いにくい • CONSの定義を右側結合でそのまま使う！ • ただし、必ず末尾にNIL::=FALSEを含む • < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) • < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) 훽 퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 훽 λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) λ 60
61. 61. データ構造の定義：LIST • eq, atomを定義したい • が、(M N)が定デ義ータす構る造LISPだとかでなは り扱いにくい • CONSの定義を右側結合でそのまま使う！ 全てのデータはLISTで表現！ • ただし、必ず末尾にNIL::=FALSEを含む GEN_ATOM ::= (lambda x.((CONS x) NIL)) ADD_LIST ::= • < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) • < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) (lambda l1.(lambda l2.((CONS l2) 훽 퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 훽 λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) λ 61 l1)))
62. 62. データ構造の定義：LIST • eq, atomを定義したい • が、(M N)が定デ義ータす構る造LISPだとかでなは り扱いにくい • CONSの定義を右側結合でそのまま使う！ 全てのデータはLISTで表現！ • ただし、必ず末尾にNIL::=FALSEを含む GEN_ATOM ::= (lambda x.((CONS x) NIL)) ADD_ATOM ::= • < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) • < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) (lambda l1.(lambda l2.((CONS l2) 훽 퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 훽 λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) λ 62 l1)))
63. 63. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 λ 63
64. 64. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) λ 64
65. 65. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) λ 65
66. 66. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) λ 66
67. 67. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) < M, N > ::= (lambda z.((z M) (lambda z.((z n) NIL))) λ 67
68. 68. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) < M, N > ::= (lambda z.((z M) (lambda z.((z n) NIL))) λ 68
69. 69. • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) atomの定義 λ 69
70. 70. atomの定義 • アトムは、lambdaを一枚はがすとNIL • リストは、lambdaを1枚はがしてもリスト • リストならFALSEを返す感じの方針 • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) • ATOM ::= (lambda x. (NOT (IS_LIST x)) ) λ 70
71. 71. データの定義 • eqを定義したい・・・ • 二つの引数が等しいか調べる • 識別子が同じか調べるのは言語仕様レベルの話？ λ 71
72. 72. データの定義 • eqを定義したい・・・ • 二つの引数が等しいか調べる • 識別子が同じか調べるのは言語仕様レベルの話？ • 値を定義して、同じか調べられるようにする ⇒チャーチ数 λ 72
73. 73. チャーチ数とな • 関数適用の回数で数値を表現する • 0 ≔ λ푠푧. 푧, 1 ≔ λ푠푧. 푠푧, 2 ≔ λ푠푧. 푠 푠 푧 , … λ 73
74. 74. チャーチ数とな • 関数適用の回数で数値を表現する • 0 ≔ λ푠푧. 푧, 1 ≔ λ푠푧. 푠푧, 2 ≔ λ푠푧. 푠 푠 푧 , … • 2つ目の引数zに1つ目の引数sをN回適用する • FALSEと0の表現が同じであることに注目 λ 74
75. 75. チャーチ数の比較 • IS_ZERO ::= ((IF (lambda x.FALSE) TRUE)) • atomとほぼ同じ形(読み捨てが3個→1個に) λ 75
76. 76. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ λ 76
77. 77. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) λ 77
78. 78. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) (lambda f.(lambda x.(f (f…(f a)))…) λ 78
79. 79. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) • GREATER ::= (lambda m.(lambda n. ((n (lambda z.(((IF (CDR z)) z) (CAR z))) (N_TRUE_APP m) ((CONS FALSE) FALSE) )) λ 79
80. 80. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) • GREATER ::= (lambda m.(lambda n. ((n (lambda z.(((IF (CDR z)) z) (CAR z))) (N_TRUE_APP m) ((CONS FALSE) FALSE) )) λ 80
81. 81. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) • GREATER ::= (lambda m.(lambda n. ((n (lambda z.(((IF (CDR z)) z) (CAR z))) (N_TRUE_APP m) ((CONS FALSE) FALSE) )) λ 81
82. 82. チャーチ数の比較 • MとNの大小比較！ • trueをN個生成して、M回IFに食わせる ⇒大きさの比較ができる！ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) • GREATER ::= (lambda m.(lambda n. ((n (lambda z.(((IF (CDR z)) z) (CAR z))) (N_TRUE_APP m) ((CONS FALSE) FALSE) )) λ 82
83. 83. 比較ができるからeqができる • 等しければTRUEが返る ⇒どちらで比較してもTRUEならば等しい！ λ 83
84. 84. 比較ができるからeqができる • 等しければTRUEが返る ⇒どちらで比較してもTRUEならば等しい！ • EQ ::= (lambda n.(lambda m. ((AND (NOT ((GREATER n) m))) (NOT ((GREATER m) n))) ) λ 84
85. 85. 比較ができるからeqができる • 等しければTRUEが返る ⇒どちらで比較してもTRUEならば等しい！ • EQ ::= (lambda n.(lambda m. ((AND (NOT ((GREATER n) m))) (NOT ((GREATER m) n))) ) SIMPLE!! λ 85
86. 86. 휷 まとめ λ 86
87. 87. IFとそれに伴う諸々(COND) • IF ::= (lambda x.(lambda y.(lambda q.((q x) y)))) • TRUE ::= (lambda x.(lambda y.x)) • FALSE ::= (lambda x.(lambda y.y)) • NOT ::= (lambda q.((q FALSE) TRUE)) • AND ::= (lambda p.(lambda q.((p q) FALSE))) • OR ::= (lambda p.(lambda q.((p TRUE) q)))
88. 88. CONS, CAR, CDR • CONS ::= (lambda x.(lambda y.(lambda z.((z x) y)))) • CAR ::= (lambda z.(z TRUE)) • CDR ::= (lambda z.(z FALSE)) λ 88
89. 89. LISTとATOM • GEN_ATOM ::= (lambda x.((CONS x) NIL)) • ADD_ATOM ::= (lambda l1.(lambda l2.((CONS l2) l1))) • IS_LIST ::= (lambda x. ((IF (lambda xyz.TRUE) FALSE) (CDR x) )) • ATOM ::= (lambda x.(NOT (IS_LIST x)) ) λ 89
90. 90. チャーチ数とEQ • N_TRUE_APP ::= (lambda n.(lambda z. (n (lambda z.((CONS TRUE) z))) ) • GREATER ::= (lambda m.(lambda n. ((n (lambda z.(((IF (CDR z)) z) (CAR z))) (N_TRUE_APP m) ((CONS FALSE) FALSE) )) • EQ ::= (lambda n.(lambda m. ((AND (NOT ((GREATER n) m))) (NOT ((GλREATER m) n))) ) 90
91. 91. 予約語4つの言語 でLISPを作る lambda, ., quote, ::= （16行くらい？） λ 91
92. 92. λ 92
93. 93. λ 93
94. 94. Thank you for listening marusa (@maruuusa83) λ 94