Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ken-okabe/82e2503006fc35627b8e to your computer and use it in GitHub Desktop.
Save ken-okabe/82e2503006fc35627b8e to your computer and use it in GitHub Desktop.
#関数、値、圏論、モナド、評価戦略、純粋関数型、その辺りの「数学的基礎」を教える
純粋関数型言語の定義は論争があるらしいです。
多くの人が純粋関数型言語は副作用がない、という文脈で語っています。
ところが、よくよく調べてみると、その「副作用」というのがかなりトリッキーなワードで、彼ら自身がIO(入出力)と副作用の関係、さらに参照透過との関係があまりよくわかっていない感じで、原因と結果がはちゃめちゃな言葉遣いをしているのをみます。
私が純粋関数型っていうのは遅延評価戦略が不可分だ、って書いていたら、
副作用の排除(この言葉がどういう感じで彼らに使われているのかが未だよくわからない)が重要だ、いう文脈でJavaScriptを純粋関数化する!という優秀な人が現れ、JavaScriptにHaskellのIOモナドを実装してしまいました。
そのコードを見ると、それはJavaScriptに遅延評価を実装する典型的なコードであり、挙動の説明も完全に遅延評価でFRPの話でした。
そういう感想というか論評を私が書いていると、
またもやその私の見解に猛烈に反発する方々が登場し、
ちょっとした議論になりました。
よくよく話を聞いてみると、
私が使う「評価」つまり「計算」っていう言葉遣いが、
世間一般とはずれまくっていて、
値の評価(Eval)、つまり値を計算する、ってことと
関数の評価(Apply)、つまり関数を計算する、ってことが、
ほんとうは別物なのに、その区別がついていない、という意見表明をされました。
そしてその彼らの理論的背景は数学だそうです。
圏論とか。
そして私がなんとなーく感じる雰囲気っていうのは、
おそらく私が世間とズレていて、
こういう彼らの意見のほうが正しい、って本気で信じている人が
それなりの数存在している、ってことなんですね。
まあ、私なんかにしてみると、おいおいマジかよ?
って思うわけですが、
中には100人中100人がそう思っていて、
私は101人目の「異端者」であるらしいです(笑)
まあ、101人目でもなんでも、間違っているのはその100人のほうなので、
どういうトンデモ理論を強弁されようとも、こちらの見解が揺るぐことなど微塵もないわけなのですが、まあ要するにそういう感じで思っている人らがいる、っていうのは大変興味深い事柄でした。
値の評価(Eval)、つまり値を計算する、ってことと
関数の評価(Apply)、つまり関数を計算する、ってことが、
あくまで違う階層でプログラミングでは区別されるべき事柄である、
っていう彼らの決意表明は、
彼らがそう思っている数学的理論背景である「圏論」には、
もちろんそんな決意表明を後押しするような
理論、考え方なんてあるわけもなく、むしろ全否定されている、
っていうのは、ちょっと気の利いた人、
あるいは圏論を理解している人ならば、誰でもわかることでしょう。
ぶっちゃけ私はそんなに圏論を精査したわけでもなんでもないのですが、
その程度のことはざっと表面をなぞっただけでも普通にわかりました。
私が圏論の表面をざっとなぞっただけで判った明白なことを、
彼らがわかっていない、ってことは、
彼らは圏論のことなんて、何も知らないのに偉そうに言ってる、ってことですね。
圏論では「値」とか「関数」みたいな絶対的存在はありません。
それらは相対的なものであり、
値は関数となり、
関数は値となり、
相互にコロコロと立場が入れ替わります。
値とは関数であり、
関数とは値なのです。
だから、プログラミングの「数学的基礎」としては、
値の評価(Eval)、つまり値を計算する、ってことと
関数の評価(Apply)、つまり関数を計算する、ってことが、
あくまで違う階層でプログラミングでは区別されるべき事柄である、
なーんていうのは、戯言以外のなにものでもない、ってことです。
こんなもんは、圏論の表面をざっとなぞるだけで、誰でもすぐわかるはずです。
わかる「はず」ですが、こういう戯言を、
100人中100人が正しいとおもっていて、オマエの考えが異端だ、
私は「評価」っていうのが何か理解していない、
その辺りよく区別ついていないからだ、数学勉強しろ、
みたいに豪語しちゃうっていうのは笑止千万。
というわけで今回、
訳知り顔のなーんもわかっていない連中に向けて、 
「数学的基礎」の講義を私の方からします。
「数学的基礎」の講義っていってもまったくたいしたことではないです。
多分中学生にもわかるレベルのおはなしです。
時間もないので、適当にブレインストーミングみたいになりますが、
その辺りは大目にみてください。
スターバックスでこいつが自分に向けてしゃべっているみたいに思ってくれればいいです。
大丈夫、中学生でもわかる話しかしませんし、数式なんてでてきません。
そんなもん必要ないから。
まず件の「圏論」がプログラミングで重要である理由っていうのは、
「圏論」が数学の根源にある性質を密接に表現する理論体系だからです。
数学の根源、というより「数」の根源としてある性質を表現する理論体系。
だから今から話すことを聞き終わったら、
だいたい「圏論」ってどういうもんなのか?あなたは理解できる、
ってことになります。
つまり「おいおい、つーか圏論が何か?ってことをまず説明してくれや」
みたいな心配は無用です。
「数」って知ってますよね?
あるいは、知っている「つもり」ですよね?
1,2,3,4,5,6・・・・・・・
みたいなやつです。
「1」に「1を足す」っていう論理操作を知っていますよね?
「数」っていうのは「論理操作」の対象であって、
「論理操作」は「数」ではない、って普通思われています。
つまり、この
「1」
「1を足す」
っていうのは、まったく違う事柄である、と大方の人は思っている。
実は違います。
「数」と「論理操作」は同じものなんです。
比喩でもなんでもない、数学で比喩なんてものはない、
100%厳密に、数学的に、
「数」と「論理操作」は同じもの。
これが今回お話する結論であり、話の内容のすべてです。
だから、これがわかったら、後は読む必要もないし、
圏論もわかっているってことだし、
私の主張のほうが正しい、ってこともわかるはずなので、
お疲れ様でした、ってことになります。
そうなりますが、大方の人、
特に訳知り顔で私の見解が間違いだ、数学勉強しろって
戯言を言っている人はわからないでしょうから、説明します。
「1」っていうのは数ですが、同時に、
「1を足す」っていう論理操作でもあります。
数直線を考えてみます。
![enter image description here](https://lh6.googleusercontent.com/-7lCHNxDDylE/VLpyn_RPlQI/AAAAAAAAFUc/GTBX8CdnS8I/w923-h185-no/BFF4C4BEC0FE%28-5A1C12B5_1B9EFA4DF%29.jpg)
原点0がありますよね?
そこに「1を足す」と
原点0から正の方向にその「数」がぐいっと
「1」の場所に「移動」します。
すべての数は、この「移動」つまり「論理操作」をもって表現できます。
「表現できる」っつーか、それが正真正銘の「数」のことです。
「論理操作」をもって移動した結果としての「数」なのか、
最初からぽつんと存在している「数」なのか、
そんなもんは数学的にはまったく区別などありません。
つまり「論理操作」=「数」なんです。
「論理操作」、「移動」を「矢印」として捉えても構いません。
なんでも好きなように想像すればいいし、
別に「矢印」である必要もないが、
多くの人はそれを「矢印」というイメージで脳内で想像しています。
数学ではこの「矢印」のことを「ベクトル」という名前で呼びます。
ベクトルは数です。
ベクトルは論理操作、あるいは移動をイメージしたものですが、
さっき説明したとおり、それは数と一切の区別はありません。
ベクトルという論理操作は数です。
虚数っていうのを中学か高校で習います。
二乗したら−1になる数です。
さっき出した数直線は、
![enter image description here](https://lh6.googleusercontent.com/-7lCHNxDDylE/VLpyn_RPlQI/AAAAAAAAFUc/GTBX8CdnS8I/w923-h185-no/BFF4C4BEC0FE%28-5A1C12B5_1B9EFA4DF%29.jpg)
実数の数直線ですが、
虚数はこの数直線上のどこにも存在しません。
混乱したデカルトが、数学者のくせに早まって
「想像上の数」ImaginaryNumberとか名前をつけてしまったので、
虚数と呼ばれています。
ぶっちゃけ、数なんて全部想像上の存在なんで、
こいつだけ「想像上の数」で虚数、とかまったく筋の通らない話ですが、
まあとりあえず虚数って呼ばれています。
ちなみにこれが虚数って名前をつけられたせいで、
理系の学生やあるいはプロの研究者でも、
虚数は実際には存在しないけど、理論では役立つ方便として処理しておけばいい、みたいにトンチンカンなことを言うひとらは結構います。
方便どころか、虚数は量子力学の根幹としてあり、
この世の中は実数と虚数が入り乱れたもので成立しています。正味そうです。
実数と虚数なんて数学的には双子みたいなもんです。
表裏一体。
-1 の平方根は i という虚数単位で現すことにします。
でも4の平方根が プラス2 とマイナス2とふたつ数が存在するように、
-1 の平方根も プラスのi と マイナスのi の2つ存在しないと筋が通りません。
どっちがどっちなんだ?
プラスのiってなんだ?
マイナスのiってなんだ?
区別なんてありません。
i 虚数単位、っていうのは純粋にプラスとマイナスで区別がない数なんです。こういうのを「対称性」って言いますが、
この我々の世界の物理法則がなんか左右対称だったり、
左右対称が崩れても、反物質の世界ではまたつじつまが合ったり、
とやたら対称性の法則になっていうのは、こういう数学の対称性が根本原因としてあります。
i 虚数単位がプラスマイナスで完全に対象で、
プラスマイナスを交換しても、まったく同じものになる、
区別がつかない、っていう対称性があらゆるところに影響を及ぼしています。
こういう虚数が100%「対称性」があるって事柄を
[複素共役](http://ja.wikipedia.org/wiki/%E8%A4%87%E7%B4%A0%E5%85%B1%E5%BD%B9)と日本語では呼称しますが、名前なんてどうでもいいです。
どーせこんなもんは日本国内でしか通用せず、英語では、
complex conjugationっていうのだから。
「複素共益」って名前だけを知っていて、
それが実際なんのことか?今説明したような意味であることを知らない人のほうが多分多いでしょう。
「圏論」にしても一緒。
 
じゃあさ、iのプラスとかマイナスとか、
それはいったいどういう意味なんだ?
実数のプラスマイナスは数直線の方向でわかるけど、
虚数のプラスマイナスはどうするんだ?
数直線に乗らないんだろう?ってなります。
これをとんでもない方法で解決したのが、
天才数学者ガウスです。
ガウスは、虚数にもプラスマイナスの数直線を与え、
なんと、実数の数直線と直交する方向にボンと置いてしまいました。
![enter image description here](https://lh4.googleusercontent.com/-0o6B0qwVdw8/VLpyTXUAK0I/AAAAAAAAFUU/fDp9xQeHZek/w500-h413-no/dc_fig02.gif)
これはガウス平面と呼ばれています。
数学史でとんでもないブレイクスルーです。
さっき説明したように、
プラスとかマイナスというのは、
単にベクトルの移動として捉えられるので、
実数軸であろうと、虚数軸方向であろうと、
こういう二次元平面として捉えたら、
虚数はその虚数軸で
プラス方向に移動したらプラスのi
マイナス方向に移動したらマイナスのi
という「数」になるわけです。
そして念の為ですが、
この虚数のプラスマイナスの区別なんてありません。
どっちかを適当に決めれば、反対方向が決まる。
気に入らなければ入れ替えればいいけども、
そもそも区別なんてないものを気に入るとか気に入らないとかないでしょ?
っていう対称性をもつプラスマイナスの方向です。
ベクトルというのは移動なんで、
この平面上を実数軸方向、虚数軸方向に
縦横無尽に移動できてしまいます。
実数軸方向に3移動 +3という数
虚数軸方向に2移動 +2iという数
あわせたら3+2iという数
おいおい、ベクトルって
(3,2)
あるいは
(3,2i)
っていう「座標」あるいは、「移動量」でしかないはずなのに、
なんで
3+2i
とかいきなりちがうX軸Y軸成分が加えられてごっちゃになってるんだ?
って混乱する生徒が多いんですが、
最初に説明したように、
移動することを現す矢印、ベクトルというのは数であり、
3移動するという論理操作も数であり
2移動するという論理操作も数なので、
こういう
3+2i
になるのは道理です。
ガウス平面上のベクトルはそのまま数になります。
2つ要素があるベクトルなので、複素ベクトル、
あるいは複素数といわれたりします。
というように、
数学では、ゴリゴリに
ベクトル=数
移動量=数
論理操作=数
っていう構図になっています。
この辺は実は基本中の基本です。
数の基本。
操作と数、
数と操作の区別なんて一切存在しない。
複素ベクトルがそのまま要素同士あわされて複素数になって、
そのまま加減乗除、微分積分しても、一切の論理破綻が起らないのは、
操作と数、数と操作の区別が一切ないからです。
ベクトルが為す体系は矢印の幾何学的なやつもざっくりと含めて、
[ベクトル空間](http://ja.wikipedia.org/wiki/%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93)と呼ばれていますが、
特にこのように
ベクトルはすなわち数であり、
数はすなわちベクトルであり、
両者はまったく区別がつかない
というような視点で数体系をみたとき、それを特別に
[数ベクトル空間](http://ja.wikipedia.org/wiki/%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93#.E6.95.B0.E3.83.99.E3.82.AF.E3.83.88.E3.83.AB.E7.A9.BA.E9.96.93)と呼びます。
ベクトルと数ベクトルの何が違うのか?
っていうと、ここでもう一度考えを整理しなおしてみると、
すべてのベクトルに「基底」「基準値」を設定するかしないかの違いです。
すべてのベクトルに「基底」を設定してやれば、それは数と見分けがつかなくなる、数ベクトルの体系、空間をなすという最初から書いていることになる、ってことです。
数直線では当然、原点0が基底で、
任意のベクトルは原点0から出発することで、
そのベクトル=数、てなるのは説明したとおりですが、
これは実は足し算引き算=加法の限定です。
0 + 1 = 1
0 + 2 = 2
0 + 3 = 3
掛け算割り算の場合、原点0を基準に、
0 × 1 = 0
0 × 2 = 0
0 × 3 = 0
とやっても数ベクトルの体をなしません。
当然、掛け算割り算=乗法の場合は、
原点0ではなく1を基底としてやり
1 × 1 = 1
1 × 2 = 2
1 × 3 = 3
とやればちゃんと数ベクトルの体をなします。
こういう加法の基底である0
乗法の基底である1
っていうのを
加法に関する単位元 0
乗法に関する単位元 1
と整理分類して単位元と名前をつけることもできます。
加法に関する単位元 0
乗法に関する単位元 1
それから
虚数単位 i
は、代数体系の根源となるもので、
これらがなす数ベクトル空間が、数の全部です。
複素数の範囲まで考えないと、すべての代数方程式は解けません。
こういう複素数のベクトルが体をなす複素ベクトル空間である、
ガウス平面で、
![enter image description here](https://lh4.googleusercontent.com/-0o6B0qwVdw8/VLpyTXUAK0I/AAAAAAAAFUU/fDp9xQeHZek/w500-h413-no/dc_fig02.gif)
乗法に関する単位元 1
を基底として、
虚数単位 i
がどういう挙動を示すのか?
ちょっと考えてみます。
1 × i = i
1 × i × i = -1
1 × i × i × i = -i
1 × i × i × i × i = 1
![enter image description here](https://lh4.googleusercontent.com/-aUQRWkQ-gyI/VLwOvsjlKqI/AAAAAAAAFU0/ZnymquUE11c/w443-h378-no/image051.gif)
となんと、
乗法に関する単位元 1
に一周して戻ってしまいました。
ガウス平面上で回転した、ということです。
ガウス平面上で
半径が
乗法に関する単位元 1
である円を考えることができます。
[ガウス平面上の単位円](http://ja.wikipedia.org/wiki/%E5%8D%98%E4%BD%8D%E5%86%86#.E3.82.AC.E3.82.A6.E3.82.B9.E5.B9.B3.E9.9D.A2.E4.B8.8A.E3.81.AE.E5.8D.98.E4.BD.8D.E5.86.86)
です。
ここで、微分っていうのを考えてみます。
微分っていうのは、数の変化の極小です。
数っていうのはベクトルと同じもんなんで、
ベクトルの変化率、
つまり、
変化後のベクトル
から
変化前のベクトル
を引き算したもので、
幾何学的なイメージでは、こういう図式になります。
![enter image description here](https://lh6.googleusercontent.com/-c5oK0xZs-q4/VLwQNyZjc5I/AAAAAAAAFVc/Vz7RhOumIC0/w538-h192-no/config_3_1_3_2_2.jpg)
任意の変化において、その局所局所ではこの図のような
近似円が考えられます。
![enter image description here](https://lh6.googleusercontent.com/-7f_m1CRuLK4/VLwP-BDUmTI/AAAAAAAAFVI/PsGQ0NOXE-o/w298-h319-no/curvature2.png)
この図から明らかですが、
その変化する瞬間のベクトル自身の矢印の向きと、
その変化する瞬間のベクトルの変化の矢印の向きは
常に直角=90度になっています。
ガウス平面上の単位円で90度回転っていうのは、
虚数単位であるiを掛けることと同じ論理操作です。
![enter image description here](https://lh4.googleusercontent.com/-aUQRWkQ-gyI/VLwOvsjlKqI/AAAAAAAAFU0/ZnymquUE11c/w443-h378-no/image051.gif)
つまり、
数というベクトルの変化率を求めてやりたい、
数を微分したければ、
虚数単位であるiを掛けてやれば良い。
複素数では、微分積分ってのは、
虚数単位での掛け算割り算になってしまいます。
虚数単位であるiは微分の単位元です。
加法に関する単位元 0
乗法に関する単位元 1
微分積分法に関する単位元 i
ってことになります。
まあこの辺からかなり素直に、
回転を司る関数、サインコサインの三角関数と、
虚数と指数関数と微分の関係から、
オイラーの公式が出てくるわけで、
おもしろいトピックだけどキリがないので省略。
i^0=1
i^1=i
i^2=-1
i^3=-i
i^4=1
という風に、iを4回かけると元に戻る、
f(x)=sin(x)のとき、
f'(x)=cos(x)
f''(x)=-sin(x)
f'''(x)=-cos(x)
f''''(x)=sin(x)
という風に、4回微分すると元に戻る、
っていうのも、
複素数では、微分積分ってのは、
虚数単位での掛け算割り算になってしまう、
という数学的に等価な性質によるもの。
微分積分が
掛け算割り算になっている。
そして
掛け算割り算っていうのは、
足し算引き算の繰り返しである、
それぞれの論理操作における単位元を基底とした
論理操作はそのまま数になっている、
単位元自体がひとつの数であり、
乗法の単位元 1 は
加法の単位元 0 を基底としたベクトルという論理操作だ、
 
とありとあらゆる階層で、
と延々と入れ子構造になっており、
ありとあらゆる関係性がある、
という構造になっているわけです。
「数」というものは、
数と論理操作が、まったく同一である、ということ、
「数」そのものが無限に自分を参照して自分自身となっている構造、
無限自己参照構造体とも表現できる「何か」です。
こういう、数が根源的なところで、
回転するという性質をもっている、
単位円での回転、
三角関数でも表現できる波動の性質を見せる、
というのは、この世界の根源となる仕組みに直結していて、
複素数による関数、波動関数はそのまま物理法則になります。
実数だけの範囲では、アインシュタインの相対性理論までの範囲が書けます。
しかし、量子力学以降になってくると、この数の全部の範囲、
複素数でないと物理法則が記述できなくなってきます。
シュレディンガー方程式という量子力学の根幹をなす、
波動関数についての方程式には、
もろに虚数単位が登場してきて、もうこの辺は完全に複素数の世界です。
そして、この量子力学の範囲では、
もう数そのものよりも、操作のほうが基準になってきて、
波動関数 -> 状態ベクトルとか、
操作そのものが物理量として扱われる世界です。
「量子」っていうのは「論理操作」のことです。
つまり、我々が目にする物質の根源は、
「論理操作」なんですよ、知ってました?
数が、ありとあらゆる階層で、
と延々と入れ子構造になっており、
ありとあらゆる関係性がある、
という構造になっている、
数と論理操作が、まったく同一である、ということ、
「数」そのものが無限に自分を参照して自分自身となっている構造、
無限自己参照構造体とも表現できる「何か」である。
ここまでよろしいですね?
関数型プログラミングの理論的背景としても、
集合とか写像っていう話がありますが、
数のあつまりである、[集合](http://ja.wikipedia.org/wiki/%E9%9B%86%E5%90%88)という操作対象
を論理操作する[写像](http://ja.wikipedia.org/wiki/%E5%86%99%E5%83%8F)つまりこれはベクトルですが、
こういう考えでやっていくと、
そもそもの、数ってのとベクトルってのが区別がないわけです。
じゃあそもそも、
操作対象である集合、
論理操作する写像、
って分けて考えている根本の土台が崩れている、
これでは考えを推し進めていく上でかなり都合が悪い、
両者を渾然一体として扱えるような理論体系がどうしても必要だ、
そこで颯爽と登場するのが「圏論」である、というわけです。
数の根源的な性質、
操作と数、数と操作の区別が一切ないっていう構造について
明示的に論じたのが「圏論」です。
圏論では単に「関係性」を論じます。
操作は、数になり
数は、操作となり、入り乱れる、
そういう関係性を数学的に論証したのが圏論です。
圏論では、
数、あるいは数のまとまり集合のことをもうちょっと抽象化して、
対象(objects)
として捉えることにします。
論理操作、写像のことをもうちょっと抽象化して、
射(morphisms)
として捉えることにします。
ところが、
この数と論理操作が、相互にコロコロと入れ替わるんですね。
だって同じものだから。
数、集合が 操作対象であり、
論理操作、写像が あくまで操作する行為であり、
両者が別々に絶対的に区別されている世界観ではなく、
対象(objects)
射(morphisms)
というのは絶対的な区別もありません。
対象(objects)
[射(morphisms)](http://ja.wikipedia.org/wiki/%E5%B0%84_%28%E5%9C%8F%E8%AB%96%29)
という「何か」はお互いにころころと入れ交わる「何か」なんです。
だって、「もともと同じもの」を別々に語ろうとした「何か」なんだから。
**対象(objects) = 射(morphisms)**
こういう「もともと同じもの」でも
お互いにころころと入れ替わる関係性を構成している「何か」であるのを
語るのが圏論です。
だから当然「圏」ってなに?っていうのを語るのは非常に難しいわけです。
そんなもんを明確に定義するのは土台無理な試みでしょう。
[圏 (数学)#定義](http://ja.wikipedia.org/wiki/%E5%9C%8F_%28%E6%95%B0%E5%AD%A6%29#.E5.AE.9A.E7.BE.A9)
>圏論においては自然変換と関手が重要であり、**圏はあくまで補足的なもの[3]という位置づけからか、圏の定義は大きく変遷している。**よく知られているのは次の3つの定義である。ただし、Buchsbaum及びグロタンディークの定義はホモロジー代数以外で用いるべきではない。
>**もっとも無難な定義**
この定義はほか二つの定義にくらべて直感的ではなく非常にわかりにくい。しかしながら、技術的にはこの定義をとればちょうどアレクサンドル・グロタンディークの図式スキームの理論を圏論の一部として扱うことができるようになる[10][11]。そのため、圏の図式に関する定理やそれらを土台とする諸定理を圏論の定理として紹介する場合は**この定義を採用するよりほかない**[12]。
なんと、数学という厳密な理論体系において、
圏論においては、
**圏はあくまで補足的なものという位置づけ**
だの
**定義は大きく変換している**
だの
**もっとも無難な定義**
だの
**この定義を採用するほかない**
などと大変混乱しているのは、それが根本的な理由です。
圏論とは、「数」というもの自体の根源を語ること、
自分自身の足元をみつめるような理論なんで、
外形的な世界観の定義が非常に困難なのです。
「数」というものは、
数と論理操作が、まったく同一である、ということ、
「数」そのものが無限に自分を参照して自分自身となっている構造、
無限自己参照構造体とも表現できる「何か」です。
この非常に精緻な構造をガチで語ろうとするのが圏論なんですね。
まあだから、圏論の圏の定義とかどうでも良いです。
今わたしがこうやって話したことを
難しい言葉で表現すると、
>[圏論(けんろん、英: category theory)](http://ja.wikipedia.org/wiki/%E5%9C%8F%E8%AB%96)とは、代数的な構成の変換の自然さを形式化するために導入された理論である。射のクラスである圏とその間の対応である関手、構成の置き換えの自然さを表す自然変換が主な道具立てである。
>概要
有限次元線型空間Vとその二重双対空間V**は同型であるが、その同型は自然(natural)であると呼ばれる。現代数学においてはこのような"自然さ(naturality)"と呼ばれる現象が頻繁に現れる。圏論の作られた目的の一つは、自然変換(natural transformation)と呼ばれる射の族を定義することでこの自然さの概念を形式化することであった。なお、自然変換を定義するにあたっては関手(functor)が、関手を定義するにあたっては圏(category)をそれぞれ射の(余)ドメインにあたるものとして定義する必要があった。
ってことになります。
 
「数」というものは、
数と論理操作が、まったく同一である、
操作と数、数と操作の区別が一切ないっていう構造、
「数」そのものが無限に自分を参照して自分自身となっている構造、
無限自己参照構造体とも表現できる「何か」です。
数っていうのが何か?っていう本質的議論こそが「圏論」です。
本質を語ろうとする理論では、本質のほうが重要なのであって、
本質を語ろうとする理論ででてくる、名前のことを語るのは本質ではありません。
大方の「訳知り顔」の連中は、
こういう数の本質をすっかりぶっとばしてしまって、
本質を語ろうとする理論ででてくる、
名前のことを一生懸命に語ろうとします。
なんもしらないからです。
こういう「訳知り顔」の連中が一生懸命に
**「圏論」を「わかったような気になって」**
「わかりやすく」他の人に説明しようとしても、
そんなもん**わかるわけがありません**。
なぜなら**本人自身がなんもわかっていないから**ですね。
たとえば、この記事に、
さっそく、こういう「訳知り顔」の連中のひとりからコメントがつきました。
>括弧を数えるな、感じろ! ‏@athos0220
この間話題になった妖怪ウォッチを勘で説明するっていうのとほとんど同じノリだ。**圏論1ミリもかすってない。**
/関数型言語 - 関数、値、圏論、モナド、評価戦略、純粋関数型、その辺りの「数学的基礎」を教える on @Qiita
>utilitas
**基礎論を1㍉も知らないひとに教わる「数学的基礎」と「論理」ってやつか。**しかも本文と表題になんの関係もないよ**(圏論ドコー**
「論理を人間が勝手に物質化する行為である『計算』」って証明論とかどうすんのっと。
はいアホですね。
圏論ドコー
って、数の本質を語ること=圏論を語ることと同値なんです。
数の本質をなーんも知らずに、
数の本質を語る「ことば」のほうだけを圏論、
だと思い込んでるから、こういうツッコミを入れる。
こういうのがウンザリするほど山ほど存在します。
プログラミングの世界で、
「圏論」っていうのを訳知り顔に語っている連中のほとんどは
この部類であると断言してよいでしょう。
**おまえらが数学勉強して出直してこいよ?な?**
っていうところです。
>「論理を人間が勝手に物質化する行為である『計算』」って証明論とかどうすんのっと。
さらにこの訳知り顔は
「証明」っていうのが人間様の物質世界における
人間的行為であることも知らないようです。
「論理」というのは、人間とはまったく関係のない世界にのみ存在します。
論理世界に「証明」なんてもんが存在する余地は1㍉も存在しません。
「証明」っていうのは「計算」です。
頭の中だけで「証明」しようとも、
それはあなたの脳という神経物質にマッピングされて、
その「証明」という「計算結果」が物質化されているんですよ。
「証明」ていうものは、人間様の勝手な都合による
「計算」という人間的行為であり、
「論理」の物質化です。
「論理」は「論理」。
それはただそこにある。
証明もなんもない。
最初から全部
「証明」し終わっているもんだし、
最初から全部
「計算」し終わっているもんだし、
「証明」=「計算」というものが付け入る余地なんてどこにもありません。
数学っていうのは、
人間と無関係に存在する「論理」
論理を人間が勝手に物質化する行為である「計算」
を合わせたものです。
「論理」は抽象的で目にも見えず、わけがわからない概念なので、
我々が小学校に入学したてのころは、
「算数」という授業で
「りんご」やら「みかん」というモノを題材とし、
現実的行為である「計算」の訓練だけを徹底的にさせられます。
計算ドリルとかやりましたよね?
しかし、「計算」に慣れさせれたところで、高学年になると、
式と計算
数量関係
比率
みたいなことを習わされ始めます。
これが「計算」の背後に存在する「論理」のことで、
「論理」や物質世界と基本無関係な事象です。
ここが重要なので繰り返すと、
「論理」は物質世界と無関係。
「計算」は物質世界に論理を展開する人間による行為。
「論理」と「計算」双方あわせたものを「数学」と呼びます。
中学に進学すると、
「算数」は「数学」に名前が変わります。
これは「計算」じゃなくて「論理」のほうに比重をシフトするぞ?
っていう教育機関による決意表明みたいなもんで、
この辺になると「関数」みたいなことも習い始めます。
「関数」っていうのは「論理」であり「計算」ではありません。
「関数」はあくまで論理操作です。
プログラミングっていうのは
コンピュータという「計算機」というマシンで
「論理」を物質化する「計算」をするための手法です。
数学=論理+計算
プログラミング=論理+計算
です。
プログラミングは数学である、
プログラミングは数学の一部である、ということです。
だから、数という根源的性質をあつかう圏論は、
そのままプログラミングに適用できます。
ただし、
論理っていうのは論理的存在なんでなんでも自由なんですが、
計算っていうのは物質化行為なんでいろんな制約があります。
たとえば無限っていう論理的存在は、
コンピュータの有限なリソースをもって物質世界に物質化できません。
無限は計算不可能な論理です。
そういうのに留意しながらやっていくのがプログラミングです。
何に留意するか?っていうともちろん
計算っていう制約のある物質化行為のほうです。
論理のほうは自由。
**数と操作の区別なんてない、同じものだ、**
それを論じるのが**圏論**で、
プログラミングの「ことば」、論理的にはまったく同じものを
勝手に違う言葉でいってるだけなんですが、言い換えると、
**値と関数の区別なんてない、同じものだ、**
ってことになります。
数学の「**計算**」も
プログラミングの「ことば」、論理的には全く同じものを
勝手に違う言葉で言い換えると、それは
**評価**
ってことになります。
いろいろ訳知り顔で
あれ読めこれ読めだの言ってくる面倒くさい連中が多い世の中なんですが、
ぶっちゃけただそれだけのことです。
極めてシンプルなことを別の言葉で言い換えているだけにすぎない。
なんも難しいことなんてありません。
-----------
関数型プログラミングの根本である「集合写像」の数学概念が、
そのままコンピュータによる計算という「物質化」にそのまま当てはめることが不可能であるから、
より「集合写像」をより抽象化した「圏論」をもってその
「計算」=「物質化」を扱う必要があるということですね。
["プログラム"の圏とクライスリ圏(categories of "programs" and Kleisli categories)](http://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%8A%E3%83%89_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)#.22.E3.83.97.E3.83.AD.E3.82.B0.E3.83.A9.E3.83.A0.22.E3.81.AE.E5.9C.8F.E3.81.A8.E3.82.AF.E3.83.A9.E3.82.A4.E3.82.B9.E3.83.AA.E5.9C.8F.EF.BC.88categories_of_.22programs.22_and_Kleisli_categories.EF.BC.89)
>プログラミングの教則として、引数と返り値をもつことからプログラム(program)とは数学の関数、すなわち集合写像(mapping)であると教えられることがある。
しかしながらこの喩えは
入出力等をもたらすプログラム
例外を返すプログラム
引数に対して値を返さない(停止しない)プログラム
同じ引数でも返り値が異なる可能性のあるプログラム
などを説明することができない。つまり、プログラムは集合写像ではない(a program is NOT a mapping)[4]。
プログラム(program)の数学的モデルを見つけ出す過程において、Moggi は圏論と表示的意味論の観点からプログラムは圏の射、型は圏の対象とみなすことができ[5]、さらに直感的解釈として、関数が値を取り値を返すものであるのに対しプログラムが値を取り計算した 値を返す[6]、すなわち引数の型と返り値の型の間にはなにか違いがあり単純な射の合成ができない、と考えた。
集合写像(関数):値 →       値
プログラム   :値 → "計算した" 値
Moggi はこのような射としてのプログラムの数学的モデルとしてクライスリ圏(Kleisli category)の射が妥当であると主張し[7]実際に副作用、例外処理、非決定計算などの効果[8]をうまくクライスリ圏の枠組みで統一的に定式化できることを示した。
そういった壮大な背景をもつ理論であるが、実用上重要であるのは『引数と返り値の型がデータとして同一であっても合成することができず、クライスリトリプルに由来した合成規則を用いなくてはならない』という点である。
ここで、
>引数に対して値を返さない(停止しない)プログラム
っていうのは、要するに
「無限」っていう「論理」は、
「計算」不能なので、「物質化」できないってことです。
「集合写像」の数学概念をそのまま
コンピュータという物質マシンに適用した時、問題となるのは、
この
「←操作」っていう部分で
「←操作」 = 「計算」 つまり「物質化」とすると、
「論理」たとえば「無限」みたいなもんは「物質世界」に収まりきるわけがない(計算不能、物質化不能)ので速攻で破綻します。
もう、この時点で
「←操作」 ≠ 「計算」
としなきゃいけないのは、明々白々です。
「←操作(関数)」 ≠ 「計算(評価)」 でないといけない。
 
関数は、宣言と同時に、即座に評価されてはいけない。
すなわち私が主張するところの、CallByNeed遅延評価でなければいけない。
関数評価も値の評価も圏論では同一のことであり、差なんてまったくないので、
値EVALと関数APPLYが違うだろうなんていう強弁は、
何の数学的裏付けもない単なる戯言であるというのは示したとおりです。
 
>つまり、プログラムは集合写像ではない(a program is NOT a mapping)
>引数に対して値を返さない(停止しない)プログラム
を完全に論理的対象として扱えるようにした解決策としての「圏論」の具現化するならば、
実装は遅延評価でなければいけないし、遅延評価と不可分です。
この圏論の導入は、
コンピュータのプログラミングが、
真に数学的と一致するような目的、
真に宣言的に記述できるようにするために導入されたのであり、
圏論を導入したコードというのであれば、宣言的にかけてアタリマエなんです。
先行評価なら無限なんて宣言的に書けないんだから、そんなもんは圏論の実装ではない、ってことだし、
副作用の排除っていうのは、単に宣言的に書けるようにするための「機構」であり、
それは手段であり、目的でもなんでもありませんね。
純粋関数型を圏論が数学的基礎にあると語りながら、
それはすなわち「副作用の排除である」と語るすべての論者、
そして、私が、
いやいやそれは「宣言型」に書くことで「遅延評価」が本質だよね?と言った時、
訳知り顔に批判するすべての連中には??と思うだけです。
なんで、こんな馬鹿げた状況になっているのか?正直わたしにはまったく理解不能なわけです。
IOモナドという、入出力の話に限って考察してみると、
IOモナドのJavaScriptの実装コードを観察しても、当然遅延評価となっていることは容易に追認できます。
「←操作」 ≠ 「計算」と遅延評価の実装にすることは、
「←操作」をとりあえずは「論理」のままに据え置くっていうことです。
つまり
「論理」=「←操作」なのです。
これは、まさに圏論のことに他なりませんから、
IOモナドの理論的背景は圏論だ、ってことになります。
------------
値のEVAL
関数のAPPLY
が違う?
まあSchemeやらの不完全な設計実装ではそういう
計算(論理の物質化)の事情は出てくるかもね。
私はそれを不完全だと思ったので自分で
Lisp、Schemeのデータ構造をひっくりかえして
設計実装しなおしてみたら、
完全に、値と関数は一致する論理構造となり、
EVALだけで関数型プログラミング言語がつくれました。
http://spacetimeprogramminglanguage.github.io/contents/entries/entry0/entry.html
まあ、数学とプログラミングは同じものだし、
値と関数の区別なんてないので、あたりまえのことです。
余談ですがLisp・Schemeのアカンところは、
セルでしたっけ、あの接続方向が、既存のセルの方向じゃなくて、
これから接続するセルの方向に向いているので、ターミネーターのセルが必要で、
![enter image description here](http://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)
データの末尾を示すため終端にnilという空データをにつける
という妙なルールがあります。
このルールどおりのものをPureList(純リスト)とし、
LISPのS式はそれで構成されているのですが、
このルールをぶちやぶって任意のアトムを終端につけることだって可能です。この場合はPureList(純リスト)じゃないのでS式なんて構成しない。
セルを自由自在に組み合わせられる、柔軟な表現方法だとおもいきや、
こういう妙なルールがある。
そしてルールどおりにするならば、
新たなリストを既存のリストに結合する際には、
終端のnilを一旦外し、
そこに接続するという2ステップの置換になる。
自由に接続じゃなくて、置換です。
そこで私はLispのリストデータ構造を逆にしてみました。
![enter image description here](http://spacetimeprogramminglanguage.github.io/contents/img/003.svg)
こういうパーツがあるところまでは同じ。
でも、最初のパーツは必ず自分自身を参照させることにした。
![enter image description here](http://spacetimeprogramminglanguage.github.io/contents/img/004.svg)
要するに、リスト構造の頭に、数学の0(ゼロ)に対応するものを用意した。
![enter image description here](http://spacetimeprogramminglanguage.github.io/contents/img/005.svg)
こいつは、当然、無限再帰構造を成します。
数学の0が無限と対称になっているのと同じ構造です。
この0もしくは無限を起点に
![enter image description here](http://spacetimeprogramminglanguage.github.io/contents/img/008.svg)
こうやってどんどん別のパーツを接続していけば、
何をどうやろうと、全部が全部「純リスト」になります。
ターミネーターをつける置換も必要ありません。
LispやらSchemeの「特殊形式」
` (list 1 2 3 4 5 6 7 8 9 10)`
`'(1 2 3 4 5 6 7 8 9 10)`
みたいな論理破綻も出てきません。
こういうデータ構造を表現するために「特殊形式」が必要なのは、
Lisp/Schemeのデータ構造の設計がおかしいことの証左です。
 
私が設計したほうのリスト構造では
操作
の区別がつかなかくなります。
詳細な論証は、
http://spacetimeprogramminglanguage.github.io/contents/entries/entry0/entry.html
ここに書いてあるとおりです。
そしてこの構造をそのままプログラミング言語として実装したら、
関数型言語になります。
EVALひとつだけの設計実装です。
「関数を評価するため」のAPPLYなんて必要ありません。
値と関数って同じものだから当然そうなります。
まあそういうことで、
EVALとAPPLYが違う、
だからおまえが観察する関数が遅延評価されている、っていうのは
値が遅延評価されている、っていう階層が違うものを
同一視して混同しているからだ!
おまえは言葉の意味がわかっていない!異端だ!
数学勉強しろ!
みたいなことを言われましても、
まあ私は数学のお話をしているだけなんで、
そんな戯言なんて、
「『権威』や他の人がいうことを鵜呑みにするんじゃなくて、
もうちょっとしっかり自分自身で頭つかって考える習慣を身につけりゃいいのに」
と思うだけで、あなた達がなんぼワーワー言おうが、
間違っているのはあなた達のほうなんで何の影響もないわけです。
でも100人中100人がそう思っている、とか言われて、
ちょっとおもしろいな、と私に思わせて、
こうやって記事を書かせる程度の影響は与えることに成功したようです。
おめでとうございます。
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment