私を SKI に連れてって

66
私を SKI に連れてって 201x年m月d日 3OUCC LTのつもりだったけど長すぎてボツ

Transcript of 私を SKI に連れてって

Page 1: 私を SKI に連れてって

私を SKI に連れてって201x年m月d日 第3回 OUCC LT会 のつもりだったけど長すぎてボツ

Page 2: 私を SKI に連れてって

お前誰って人のための

すしす

Twitter: @susisu2413

GitHub: susisu

Page 3: 私を SKI に連れてって

本日の予定

λ計算入門

SKIコンビネータ入門

Lazy K の紹介

Page 4: 私を SKI に連れてって

λ計算入門

Page 5: 私を SKI に連れてって

λ計算とは

"計算"を関数とその適用でモデル化したもの

関数型言語の理論的基盤

ここでは型無しλ計算を紹介します

型付きもあるんだよ

Page 6: 私を SKI に連れてって

λ式

変数 a, b, c, ..., x, y, z, ...

λ抽象 λx.x, λx.λy.(x y), ...

関数適用 (f x)

Page 7: 私を SKI に連れてって

λ式λx.λy.* は λx y.* と略記する

関数適用の括弧は曖昧でない場合は省略する

x y = (x y)

関数適用は左結合

f x y = ((f x) y)

Page 8: 私を SKI に連れてって

α-変換

λ抽象の束縛変数名は重要ではない

例えば λx.x = λy.y

束縛変数名を別の名前に置き換える操作をα-変換と呼ぶ

α-変換で同じλ式にできるなら等価

Page 9: 私を SKI に連れてって

β-簡約

要はただの関数適用の評価

λ抽象内部の束縛変数を全て引数で置き換える

例えば (λx.f x) y = f y

β-簡約で同じλ式にできるなら等価

Page 10: 私を SKI に連れてって

η-変換どんな引数に対しても同じ結果になるならば、それらは同じといってもいいよね (外延的等価性)

例えば f = λx.f x

これらの間の変換をη-変換と呼ぶ

η-変換で同じλ式にできるなら等価

Page 11: 私を SKI に連れてって

Quiz

1. λx.x y = λy.y y ?

2. (λx.λx.x y) y = λy.y y ?

3. λx.x = (λx y z.x z (y z)) (λx y.x) (λx y.x) ?

Page 12: 私を SKI に連れてって

Answer

1. No

2. No

3. Yes

Page 13: 私を SKI に連れてって

λ計算

λ式と変換・簡約の規則をまとめてλ計算と呼ぶ

λ計算はチューリング完全

どんな手続き (プログラム) もλ式で表現できる

Page 14: 私を SKI に連れてって

Q. どう計算するの

入力 x が与えられるとする

手続きを表すλ式 p をうまく選べば、例えば y = p x で出力が得られる

y を変換・簡約すれば解読できそう

Page 15: 私を SKI に連れてって

Q. 数値とかどうするの

数値がなければ、λ式を使えばいいじゃない

真理値がなければ、λ式を使えば

リストがなければ、λ式を

Page 16: 私を SKI に連れてって

Church数

λ式で自然数を表わすひとつの方法

Page 17: 私を SKI に連れてって

Church数

0 := λf x.x

1 := λf x.f x

2 := λf x.f (f x)

...

Page 18: 私を SKI に連れてって

Church数次の自然数を求める関数 Succ

Succ := λn f x.f (n f x)

足し算 Add

Add := λa b f x.a f (b f x)

掛け算はどうなるか考えてみよう

Page 19: 私を SKI に連れてって

Church数

掛け算 Mul

Mul := λa b f x.a (b f) x

Page 20: 私を SKI に連れてって

Church数前の自然数を求める関数 Pred

Pred := λn f x. n (λg h.h (g f)) (λy.x) (λy.y)

ただし Pred 0 = 0

キリがないのでこれ以上はやめる

Page 21: 私を SKI に連れてって

Church真理値

True := λx y.x

False := λx y.y

If := λp x y.p x y = λp.p

Page 22: 私を SKI に連れてって

Church真理値

AND, OR, NOT

And := λp q.p q False

Or := λp q.p True q

Not := λp.p False True

Page 23: 私を SKI に連れてって

述語の例

Church数 n が 0 かどうか調べる

0 = λf x.x だった

IsZero := λn. n (λx.False) True

だんだんとプログラムが書ける気がしてきませんか?

Page 24: 私を SKI に連れてって

Church対

リストや木構造は対 (pair) の連鎖で表現できる

[1, 2, 3] = (1, (2, (3, 空)))

対をλ式で表現できればいいよね

Page 25: 私を SKI に連れてって

Church対

対をつくる関数 Cons

Cons := λx y c.c x y

かんたん!べんり!

Page 26: 私を SKI に連れてって

Church対

対の前後を取り出す関数 Car, Cdr

Car := λp.p (λx y.x)

Cdr := λp.p (λx y.y)

Page 27: 私を SKI に連れてって

Church対

空 (リストの終端) は?

好きなものを使えば良い

False が一般的っぽい?

Page 28: 私を SKI に連れてって

Quiz入力 x が 2 つのChurch数 a, b のChurch対で与えられる

出力 y = p x が、a = 0 なら y = b、それ以外なら y = a * b となる p を書いてみよう

Succ などこれまでに定義したものは使ってもよい

Page 29: 私を SKI に連れてって

Answer

例: λx.IsZero (Car x) (Cdr x) (Mul (Car x) (Cdr x))

Page 30: 私を SKI に連れてって

繰り返し処理

繰り返し処理を関数で表現したい時は、再帰的な関数を書けばいい

f(0) = 1, f(n) = n * f(n - 1)

けれどλ計算では"再帰的な定義"ができないので、単純には書けない

Page 31: 私を SKI に連れてって

関数の不動点

関数 f に対して、f x = x となる ような x を f の不動点と呼ぶ

Page 32: 私を SKI に連れてって

Fix関数 f を引数にとり、その不動点を返す関数 Fix が存在したとする

Fix f = f (Fix f)

f = λx n. IsZero n True (x (Pred n))

Fix f n は n 回の空ループになる

Page 33: 私を SKI に連れてって

Fix

Fix があれば、繰り返し処理を表現することが出来る

このような関数 Fix をなんとかλ式だけで表現できないか?

Page 34: 私を SKI に連れてって

Fix

できる!

Fix := λf.(λx.f (x x)) (λx.f (x x))

実際に Fix f = f (Fix f) となるか確かめてみるとよいです

Page 35: 私を SKI に連れてって

λ計算のまとめλ計算は、計算を関数とその適用でモデル化したもの

チューリング完全

数値も真理値もリストもλ式で表現できる

繰り返し処理だってできちゃう

Page 36: 私を SKI に連れてって

SKIコンビネータ入門

Page 37: 私を SKI に連れてって

コンビネータ計算とは

!

高階関数 (コンビネータ) を用いて計算を行う

λ計算と同じく、簡約が存在

(P x y z ...) = E

簡約の結果 E は、コンビネータ P の定義による

Page 38: 私を SKI に連れてって

コンビネータの例

B x y z = x (y z)

C x y z = x z y

W x y = x y y

Page 39: 私を SKI に連れてって

コンビネータの例

S x y z = x z (y z)

K x y = x

I x = x

実は I = S K K とも書ける

Page 40: 私を SKI に連れてって

SKIコンビネータ計算

S、K、I の 3 つのコンビネータを、"基底"として用いる

他のコンビネータは S、K、I の組み合わせで表現する

スキーとは関係がない

Page 41: 私を SKI に連れてって

SKI で何ができるかSKIコンビネータ計算はチューリング完全

λ抽象と相互に変換することができる

SKI→λ は自明

λ→SKI については Wikipedia の「コンビネータ論理」のページを見るとよいかも

Page 42: 私を SKI に連れてって

SKI でChurch数0 := KI

1 := I

2 := S(S(KS)K)I

...

Succ := S(S(KS)K)

Page 43: 私を SKI に連れてって

SKI でChurch真理値

True := K

False := KI

If := I

Page 44: 私を SKI に連れてって

SKI でChurch対

Cons := S(S(KS)(S(KK)(S(KS) (S(K(SI))K))))(KK)

笑っちゃうよね

Page 45: 私を SKI に連れてって

SKI で Fix (Y)

Fix よりも、不動点コンビネータ Y と呼ぶことが多い (きがする)

Y := SSK(S(K(SS(S(SSK))))K)

Page 46: 私を SKI に連れてって

Quiz

Church数の掛け算、足し算を SKI で書いてみよう

足し算の方が難しくなるはず

Page 47: 私を SKI に連れてって

Answer

Mul = S(KS)K

Add = S(KS)(S(K(S(KS))) (S(KK)))

Page 48: 私を SKI に連れてって

SKI のまとめS, K, I という 3 つのコンビネータと適用だけで計算をする

チューリング完全

λ抽象と相互に変換できる

データも表せるし、繰り返し処理もできる

Page 49: 私を SKI に連れてって

だんだん自分の SKI 力がどれほどのものか 確かめたくなってきましたよね?

Page 50: 私を SKI に連れてって

Lazy K

Page 51: 私を SKI に連れてって

こころ夏目漱石

Page 52: 私を SKI に連れてって

“精神的に向上心のないものは馬鹿だ”

Page 53: 私を SKI に連れてって

“精神的に向上心のないものは馬鹿だ”Eager K

Page 54: 私を SKI に連れてって

Lazy K とは

SKIコンビネータ計算をベースにした言語

遅延評価、故に Lazy

対義語: Eager, Strict

こころの K とは関係がない

Page 55: 私を SKI に連れてって

遅延評価

結果に必要のない部分を評価 (計算) しないための仕組み

例えば K x y = x の y は必要ないので、評価を省略したい

Page 56: 私を SKI に連れてって

遅延評価

ほとんどのプログラミング言語では、引数は適用の前に評価される

Lazy K では、引数はそれ自身が関数として適用に使われるまで評価が遅延される (使わなければ評価されない)

これによって、Yコンビネータによる 停止するループや、無限の長さをもつリストが実現できる

Page 57: 私を SKI に連れてって

入力

入力は文字コードをChurch数で表現したものの、Church対によるリストで与えられる

入力の終端はChurch数 256

256 = SII(SII(S(S(KS)K)I))

ただし"リストの終端"ではない

Page 58: 私を SKI に連れてって

出力

入力 X とプログラム P に対して、出力は Y = P X

出力も文字コードをChurch数で表現したものの、Church対によるリスト

出力の終端も 256 以上のChurch数

Page 59: 私を SKI に連れてって

記法

Lazy K には 4 つの記法がある

コンビネータ計算 …… S(KI)I

unlambda …… ``s`kii

Iota …… * と i だけ

Jot …… 0 と 1 だけ

Page 60: 私を SKI に連れてって

記法 (その他)

空白、改行は無視される

# の後は改行までコメント

空ファイルは I

Page 61: 私を SKI に連れてって

Lazy K 処理系http://esoteric.sange.fi/essie2/download/lazy-k.zip

Windows 用のバイナリ同梱

GCC でコンパイルするときは lazy.cpp にパッチを当てる

https://gist.github.com/susisu/831e06af2ddee14938c8

Page 62: 私を SKI に連れてって

Lazy K 処理系

実行はファイルから、または -e で直接プログラムを指定

$ lazy <file>

$ lazy -e <program>

Page 63: 私を SKI に連れてって

Lazy K 処理系ためしになにか動かしてみる

$ lazy eg/calc.lazy

$ lazy -e SKK

中身を見るともっとたのしい

SKI を組み合わせて、君だけの最強プログラムを作ろう!

Page 64: 私を SKI に連れてって

Lazy K の闇は深い

Page 65: 私を SKI に連れてって

参考文献

大体 Wikipedia を読めばいいと思う

ラムダ計算

コンビネータ論理

SKIコンビネータ計算

不動点コンビネータ

Page 66: 私を SKI に連れてって

参考文献

The Lazy K Programming Language

https://tromp.github.io/cl/lazy-k.html

↑の日本語訳

http://legacy.e.tir.jp/wiliki?%CB%DD%CC%F5%3A%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%ECLazy_K