万物は関数である
$ \lambda x.x(サムネ用)
前提
コンピュータの世界では単純な0と1の羅列によって全てのデータや計算式を表現することができる
同様にして、計算機理論の上では単純なラムダ式(無名関数)の構造によって全てのデータや計算式を表現することができる
ラムダ式(無名関数)
ラムダ式という名前は無名関数を表す記号として習慣的にλ(ラムダ)が使われることからそう呼ばれている
別に無名である必要は無いのだが、ラムダ式では関数が何重にも入れ子になり重なり合うため、一つ一つ名前をつけていたら追いつかないため、無名関数を用いる
実際の書き方
普通の関数:$ f(x) = x+1
ラムダ式:$ \lambda x.x+1
また代入する時は関数を括弧で括り、その後ろに代入するものを書く
$ (\lambda x.x+1)2=2+1=3
カリー化
ラムダ式で表される関数は引数を1つしか持てない
ラムダ式とは構成要素を極めて単純にした世界なのだ
複数の引数を取らなければならない関数をラムダ式にする場合を以下に示す
例:2+3
加算という関数は2,3の2つの引数を取り、2+3を計算して5を返す
これを引数を1つしか持てないラムダ式に落とし込むとこうなる
$ \lambda x.(\lambda y.x+y)
この式はこんな感じに処理される
2を受け取って「2に足す」という関数を返す
$ (\lambda x.(\lambda y.x+y))2 = \lambda y.2+y
↑の関数が3を受け取って5を返す
$ (\lambda y.2+y)3=2+3=5
引数を1つしか持てないラムダ式であっても、このように関数を入れ子構造にすることで複数の引数を扱える
実際には省略のため引数を複数取るかのような以下の表記をする
$ \lambda xy.x+y
ラムダ式の機能
定義
ここまで例にしてきたような引数と返り値のペア
適用
数学で言うところの代入のようなもの
よく使うので数学では$ f(x)と書くところをラムダ式では省略して$ fxと書く
ラムダ式はこの2つだけで全ての計算を行う
数字も関数である?
ここまで、整数や加算などラムダ式でない物を含んだラムダ式を分かりやすい例として挙げてきた
実際にはラムダ計算の世界に存在するものはラムダ式のみであり整数や加算もラムダ式の構造によって表現される
ここではチャーチ数を例として整数と加算の定義を示す
0: $ \lambda f x.x
1: $ \lambda f x.fx
2: $ \lambda f x.f(fx)
3: $ \lambda f x.f(f(fx))
イメージ:fを入れ子にする回数を数として定義した
加算(m+n): $ \lambda mnfx.mf(nfx)
イメージ:mの入れ子の最深部にnを埋め込む
2+3を実際に計算してみる
$ (\lambda mnfx.mf(nfx))$ 2$ 3
$ (\lambda mnfx.mf(nfx))$ (\lambda f x.f(fx))$ (\lambda f x.f(f(fx)))
$ (\lambda mnfx.mf(nfx))$ (\lambda g y.g(gy))$ (\lambda f x.f(f(fx)))
※適用のために変数名を書き換えたけど構造は同じ
$ (\lambda nfx.(\lambda g y.g(gy))f(nfx))$ (\lambda f x.f(f(fx)))
$ (\lambda nfx.(\lambda y.f(fy))(nfx))$ (\lambda f x.f(f(fx)))
$ (\lambda nfx.f(f(nfx))$ (\lambda f x.f(f(fx)))
$ (\lambda nfx.f(f(nfx))$ (\lambda gy.g(g(gy)))
$ \lambda fx.f(f((\lambda gy.g(g(gy)))fx)
$ \lambda fx.f(f((\lambda y.f(f(fy)))x)
$ \lambda fx.f(f(f(f(fx)))$ =5
具体的なやり方は重要ではなく関数の構造のみでデータや計算を表現できるという事実が大事
0と1の羅列によって全てのデータや計算式を表現するのと同じ様に、関数の構造によっても全てのデータや計算式を表現できる
大事なことなので2回書きました