「参照透過性」という用語は裸の王様と言えない愚者のための概念
関数型プログラミングの本を書いた。
2021年末に基本フリーで誰でも読める形で関数型プログラミングの入門書をUPした。構想だけをしていたり、トライアンドエラーでゼロから書き直したりする時間全部ひっくるめると2年ほどかかった。かなりの長編ではある。
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
ここで、少なくともこのフェイズで2年間ほど、どうやって初学者に関数型プログラミングの概念を必要十分に伝達できるだろうか?ということを結構僕なりに真剣に考えてきたと思う。
そして、この2年より前から2015年頃から、まあだいたい7年ほどかけて痛感しているのは、「参照透過性」という用語は裸の王様と言えない愚か者のための概念である、ということだ。
ここで説明しよう。というか2022年になる前に説明しておきたい。
なぜならば、2021年末この著作をUPしてから、馬鹿がTwitterでネガキャンはじめて、2015年のQiitaの馬鹿げたネガキャン騒ぎについて再言及してきたからだ。
やっぱ放置しておくのはよくないよね。
すでに本ブログで書いた、これ、である。
やはり岡部某か…。
— 斜月三星堂 (@littleHaskeller) December 10, 2021
Qiita で暴れてた頃は参照透過性も理解できてなかったからなぁ…。 https://t.co/LfxGk0guYc
Qiita でみんなに否定されまくったのにメゲないそのメンタルには感心するよ。
— 斜月三星堂 (@littleHaskeller) December 10, 2021
言ってる内容はメチャクチャだけど🤣🤣🤣🤣🤣🤣
ここで、この馬鹿がいう「みんな」とは、同列の馬鹿のことであり、「参照透過性の理解」というのは、この馬鹿どもが参照透過性なんて言葉を理解なんてしていない、あるいは理解したつもりになっているが、なんのことか本当にわかってるわけもない、あるいは「王様は裸だ」と言えない愚か者である、ということを意味する。
と逐一追加しておかないと、ツイート一つするにも精神が安定しないのか、非常にアレ界隈のアレであることは見て取れる。
だいたい参照透過性界隈のおバカさんはこういう感じなのだろう。
まず、前回も論じたが、
これが納得いった説明だとかよく言われたりする。
以上の説明で、最初の3つ
-
プログラムは関数定義の集合であり、関数呼び出しによってそれらを組み合わせる。
-
関数は first class object である。
-
文という単位は無く、プログラムの実行とは式を評価することである。
はまあまあ良い。
特に、3つ目の、
-
文という単位は無く、プログラムの実行とは式を評価することである。
というのは、著作でも最初から最後まで一貫して強調していることだ。
上の説明が「駄目」なのは、
-
プログラムは関数定義の集合であり、関数呼び出しによってそれらを組み合わせる。
-
関数は first class object である。
という最初2つが、その3つ目に統合されるので、冗長な説明である、ということだ。
はっきとした定義があろうがなかろうが、論理的に冗長であって統合できるのであれば、それは統合して構造化して初学者に提示すべきなのだが、「はっきりとした定義がない」という権威(オーソライズ)されていないと見るや否や思考停止というか、巷で言われていることを適当に列挙してそれで誤魔化してしまう。
書くなら以下のように構造化して提示すべきだろう。
1.関数型コードとは式だ。←これがメインテーゼ。
2.そして二項演算、つまり二つの式をくっつけてつなげる、という「式」がほとんどすべてで、その二項演算とは実は二項の関数と同じものだ。
3.そしてその式=値には関数も含まれる、従って、関数を値として取り回せること=FirstClassOjectである必要がある。
こう書くべきだろう。
- プログラムは関数定義の集合であり、関数呼び出しによってそれらを組み合わせる。
とかいうのは、「関数型プログラミング」という言葉なので、とりあえず「関数」については言及しておかなければいけないだろう、という書き手の安易な発想であり、
正確には、
- プログラムは式の集合である。
からはじめるほうが正確だし、
「関数呼び出しによってそれらを組み合わせる。」
というのは、関数合成、高階関数のことをざっくり言ってるつもりなのかはしらないが、「関数呼び出し」によって、それらの組み合わせが生じるというのは概念的にはデタラメで穏当にいっても冒頭の定義としては適当すぎる。
そして問題の箇所にさしかかる。
まず、何が致命的に駄目なのか?
というと、基本的にこの書き手、解説者は、初見者にむけて概念を教えるつもりなんてない、ってことだ。
関数型言語とは
とかいう、初見であると想定される未知の概念説明のときに、別の未知の概念を利用してはいけない。
理解とはすでに理解している概念の地道な拡張であり、無理解の上に無理解の概念を重ねて理解が生まれるはずない。原理的に。
そして何より、関数型プログラミングの理解のために、本当にこの「参照透過性」なることば、概念が必要なのか?
「最も重要なのは参照透過性」というのは本当なのか?
という疑念がある。もしこれが嘘であるならば、まったく本質でない概念に依存する形で、未知の概念を構築しようとしている。土台がない、ってことだ。
結論をすでに書いたので、「参照透過性」なんてものは関数型に最も重要な概念でもなんでもないので、嘘の説明の仕方をしている。
なるほど。前回のエントリで僕はこう書いた。
1+2=3
とかいう小学校の頃から慣れ親しんでいる二項演算は、二項関数と等価であり、この式こそが関数型コードだ、みたいな説明こそが大事だからです。
自分が読んだ本、あるいはこういう持ち上げられている解説ページに、小学校の頃からやってる二項演算が関数型コードの式である、という単純明快な解説がなされているのをこれまで見たことがありません。
そして二項演算ってのは、数学の定義上、ここで言われる参照透過性があるわけですが、誰が、これまで二項演算やるのに、参照透過性が重要だ、みたいな教育を受けたことがあるのでしょうか?
1+2=3
という二項演算の式=関数型コードのあり方を理解するためには
「参照透過性」とは完全に不要な用語です。
こういう説明を読んでいる閲覧者は例外なく自身の体験として理解していることだろうけども、これまで彼ら、我々が義務教育からはじまっておそらく大学教育を終えるまでに、あらゆる分野の数学を学習するときに「参照透過性」なんて言葉は学校で教えられたことなど一度もなかったはずだ。
なんか、数学と独立した範囲内で、なぜかプログラミングの分野だけに、特に関数型プログラミングの初紹介を受ける際に限って、この珍妙な「参照透過性」がもっとも重要だ、みたいに言われる。
だってね、
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
なんてことは、数学ではアタリマエのことじゃない(笑
そして、こんな義務教育から一貫してアタリマエの作法として受け入れられてきたことに、これまで教師は一切「特別な名称」を与えることなどしなかったし、我々生徒は、それが何かのもっとも重要な概念だ、みたいに特別扱いされたステージで概念認識することもなかったはずだ。
-
これの意味するところは、式の値を計算するのに、その時点での状態というものを考慮する必要がないということである。例えば、もし
f(x)
という式の評価結果が2になったとしたら、f(x)
を何回呼び出しても常に2を返す。
これも結局同じことを書いてるよね。
-
手続き型言語に参照透過性がない原因は、変数の値が途中で変わることと、式の構成要素以外のもの(大域変数など)に依存した計算ができることである。
そして、こういう説明が悪い。
結局の所、著作でも書いたとおり、手続き(命令型)プログラミングでは、数学ではアタリマエであり続けた作法を捻じ曲げているわけだが、その事を
「手続き型言語に参照透過性がない原因」
つまり、アタリマエではなくしている原因、という説明に、「参照透過性」という無用に新しく登場した用語をもって、原因がどうのと説明している。
わかりますか?
XXには以下のような特性があります。
まずここに、ホニャララという概念があり、それがもっとも重要なのです!
ホニャララはこれまで我々がアタリマエのように理解して実践してきたことです。
XXでないものが、ホニャララでない原因は、アタリマエじゃなくなっているからです。
だいたいこういう論理構造の説明の仕方で、このホニャララとかいう言葉っている?
XXとその他の「比較」アタリマエに知っていることの「差異」として紹介されるのならともかく、わざわざ耳慣れない命名された特別な概念として、もっとも重要だ、みたいにしなければいけない?結構狂った世界ではある。
大枠では
1.義務教育以来、理解して実践してきた、「式の構成要素がすべて同じなら、式の値は常に同じになる」というアタリマエの数学の知識、作法
2.命令型というそれがアタリマエでなくなった作法
3.関数型というアタリマエに戻す作法
という流れがあるわけだが、この至極単純な事実を説明するために
「参照透過性」ということばをデッチ上げて、学習者惑わせているわけである。
そして、多くのプログラマはこの「参照透過性」という混乱を招いているだけの無駄で無意味なことばを「最重要」と信じてやまない。
なんでか?こういう説明でもそう書かれているし、
「みんながそういってるから」だよね。つまり
裸の王様と言えない愚者のための概念だったこと。
こういうやつのこと。
やはり岡部某か…。
— 斜月三星堂 (@littleHaskeller) December 10, 2021
Qiita で暴れてた頃は参照透過性も理解できてなかったからなぁ…。 https://t.co/LfxGk0guYc
Qiita でみんなに否定されまくったのにメゲないそのメンタルには感心するよ。
— 斜月三星堂 (@littleHaskeller) December 10, 2021
言ってる内容はメチャクチャだけど🤣🤣🤣🤣🤣🤣
ここで、この馬鹿がいう「みんな」とは、同列の馬鹿のことであり、「参照透過性の理解」というのは、この馬鹿どもが参照透過性なんて言葉を理解なんてしていない、あるいは理解したつもりになっているが、なんのことか本当にわかってるわけもない、あるいは「王様は裸だ」と言えない愚か者である、ということを意味する。
あと、
の元記事である、
では、同列の愚者がコメント欄に湧いていて、
Wikipedia の「参照透過性」の項目には
参照透過性(さんしょうとうかせい、英: Referential transparency)は、計算機言語の概念の一種で、文脈によらず式の値はその構成要素(例えば変数や関数)によってのみ定まるということを言う。具体的には変数の値は最初に定義した値と常に同じであり、関数は同じ変数を引数として与えられれば同じ値を返すということになる。
と書いてあります。
またオンライン版の『Learn You a Haskell for Great Good!』にも
if a function is called twice with the same parameters, it's guaranteed to return the same result. That's called referential transparency ...
と書いてあります。
これらの文章を読めば UCLA を卒業した岡部氏でなくても分かると思いますが、関数に関して言えば、「参照透過性(参照透明性)」とは「ある関数に同じ引数を渡せば、必ず同じ値が返ってくること」です。
ところが Data.new() は引数としては何も渡していないのに、毎回異なった値が返ってくるんですよね。これのどこが参照透明なんですか?
それと、どちらかの方(コメントの芸風があまりにも似過ぎていて私には区別がつきかねます)のコメントに
Date.now()の場合、具体的には、暗黙の了解としてユーザの現在時刻Tがnow()の引数になっています。
と書いていますが、そもそも引数とは明示的に関数に渡すものではないですか?
Date.now() がユーザーの現在時刻を元に値を返すなら、それは Date.now() がユーザーの現在時刻を「参照」しているだけではないのですか?
もしかしたら、岡部氏や qiitapost さん、chimetorch さんは私たちとは違う次元に住んでいて同じ言葉でも違う意味になるのかもしれませんね。
異次元に住んでいる人たちと交流できるなんて、Qiita ってすごいですね。
あるいは、
(編集済み)
ブログ上でOCamlでGUIアプリを作成せよと述べたにもかかわらず、岡部氏自身はFRPを用いた実用的なGUIアプリを提示していない。
JavaScriptのDateは関数型プログラミングのストリームであり、.now()関数の返り値も参照透明と主張。
あるいは、
すみませんが、これまでに何度も具体的に誤りを指摘されてきた岡部氏と全く同じご主張のようですので、これまでの議論をお読みください。特に、参照透明の定義は、岡部氏と全く同じ誤解をされているようですので、英語版Wikipedia
https://en.wikipedia.org/wiki/Referential_transparency_%28computer_science%29
や、英語版Wikipediaから参照されGoogle Scholar
https://scholar.google.com/scholar?q=referential+transparency
でもトップに来る標準的な学術論文
http://www.itu.dk/people/sestoft/papers/SondergaardSestoft1990.pdf
をご覧ください。一つ目の英語版Wikipediaの現時点での記述は(ここでの議論に関連する範囲では)二つ目や三つ目のような数多くの(というか確認できる限り全ての)査読付学術論文と整合的で信頼できます。ご参考までに、例えば以下の記述があります。
today() is not transparent, as if you evaluate it and replace it by its value (say, "Jan 1, 2001"), you don't get the same result as you will if you run it tomorrow. This is because it depends on a state (the time).
(私訳:「today()は参照透明ではありません。評価して値(例えば"Jan 1, 2001")で置き換えると、明日に実行するのと同じ結果が得られないからです。これはtoday()が状態(時間)に依存しているためです。」)
逆に(時間にせよ何にせよ)プログラム上に存在しない暗黙の引数を考えれば参照透明などと言い出したら、状態に依存したどのような関数も参照透明になってしまい「参照透明」という概念の存在意義がなくなってしまいますので、そのような定義があり得るとは思いません。
追記:「ご回答よろしくお願いします」とのことですが、これまでの議論ですでに明白な、岡部氏と全く同じ誤りを繰り返すばかりで、誠に失礼ながらいわゆる「荒らし」が目的としか思えませんので、これ以上はご回答しかねます(他の方に有用な情報が提供できそうな場合はするかもしれませんが)。2ちゃんねるへの書き込みも私ではありません。ご了承ください。
@Lambadaは、前エントリで示したとおり、当時のTwitter名もつけると、
らくだの卯之助 (@camloeba)
プロフェッショナルな関数プログラマと紹介されているが、2chの僕を標的にした誹謗中傷スレッドで活躍していた。
さて、すでに前半で概論は説明したが、さらに踏み込んでいかにこいつらが間違っているのか解説していこう。
Data.now() は引数としては何も渡していないのに、毎回異なった値が返ってくるんですよね。これのどこが参照透明なんですか?
-
JavaScriptのDateは関数型プログラミングのストリームであり、.now()関数の返り値も参照透明と主張。
(私訳:「today()は参照透明ではありません。評価して値(例えば"Jan 1, 2001")で置き換えると、明日に実行するのと同じ結果が得られないからです。これはtoday()が状態(時間)に依存しているためです。」)
ここで、かろうじてまともなことを書いているのが
これはtoday()が状態(時間)に依存しているためです。
だ。
著作では、
(引用終わり)
に該当する。
ここで、Date.now()
というのは、時間に「明示的に依存している」のは明白です。
これはtoday()が状態(時間)に依存しているためです。
とも書かれているだろう。
【参照透過】という無意味なBuzzワードが、言ってることは結局の所、
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
なんてことは、数学ではアタリマエのことじゃない(笑
ってことでしかないので、
nowだのtodayという、時間依存の関数であると明示されている場合には、数学的な矛盾など起きない。
なぜならばそれは、
常にユーザの現在時間を指し示すインデックスであるNowをもって、
Time(Now)という関数に概念的に一致するからだ。
これで命令型で起きるような不整合があれば、示せばいいだろうが、そんなことは彼らにはできないだろう。
Date.now() がユーザーの現在時刻を元に値を返すなら、それは Date.now() がユーザーの現在時刻を「参照」しているだけではないのですか?
そうだよ、だから?
その論理ならこの、わけのわからん造語である「参照透明」のスペックは満たしてるだろう?
「(私訳:「today()は参照透明ではありません。」というのは、単にその論文の主張が間違っている。
せいぜい僕の主張よりも権威は認められる、と主張するのは自由だが、学問ってそういうもんじゃないよね?Wikipediaからリンクされてる、うん、それで?(笑
だいたいこの輩は、あとから引用するけど、オリジナルから捻じ曲げられた「参照透明」という言葉の経緯はわかって書いてるのか?
こいつがいうところの「参照透明」ってのはどういう意味で使ってるんだ?こいつのオレオレ定義か?どの意味の「参照透明」?そんな定義すらろくにされていない用語はまともな論文として通ってるのか?アホらしい。
逆に(時間にせよ何にせよ)プログラム上に存在しない暗黙の引数を考えれば参照透明などと言い出したら、状態に依存したどのような関数も参照透明になってしまい「参照透明」という概念の存在意義がなくなってしまいますので、そのような定義があり得るとは思いません。
実際に
Now
とか
Today
が、それぞれ引数として
Time(Now)
Time(Today)
というように暗黙じゃなくて明示した現在時間のインデックス値として引数にしてやっても、そうじゃなくても、どっちでもどうでもいいとおもうけど、いずれにせよ、
これ、時間依存の関数だって、明示されているのと一緒だし、実際そういう意味だってコンセンサスはあるわけだよね?(苦笑
そして、こういうくだらん、無意味な議論を引き起こすことこそ、この参照透明、参照透過というくだらない造語が害悪であるという証左。
「参照透明」という概念の存在意義がなくなってしまいますので、そのような定義があり得るとは思いません。
うん、そのとおり、非常にくだらないし、こんな「概念」の存在意義なんぞないよ。定義したのがそもそもの間違いで、王様は裸だといえないこういう馬鹿連中を量産している。
(編集済み)
@Q_Jirou さん、お疲れさまです。
私はこれまでの一連の書き込みを見て、「根本的に議論が成り立たない相手」が存在するという事実に脅威を覚えています(笑)以前私が書き込んだ「参照透過性」の定義を読んだ後にまだ「Date.now() は参照透過である」との主張を曲げないんですから、毛の人は根本的なところでの言語理解力が乏しいか、私たちの言語体系とは違った世界の住人なのだと思うことにしました。
相手が人でない場合、「人の道」を説くの無意味だと思います。残念ながら…。
@totemring
あなたはこれまでのコメントの中で何度も「コンセンサス」という言葉を使ってきていますが、あなたの「Date.now() は参照透過である」という主張はどの程度のコンセンサスが得られているのですか?
もちろん、哲学や意味論や物理の世界ではなく、我々が議論している「関数型プログラミング」の世界での話ですよ。あなたがこれほど主張しているのですから、「関数型プログラミング」に関する学術論文の中に「Date.now() は参照透過である」と書かれている論文がさぞや沢山あるのでしょう。そのうち 4〜5 編でいいので題名と著者を教えてください。
「そんなのは自分たちで調べればいいだろう」などという『悪魔の証明』を提案しないでくださいね(笑)
@totemring さん、コンセンサスの話題はスルーですか?(笑)
上記確認済みのように「値」が言語外にしか存在しない、と意味論的に正しい解釈をしていれば、そんな間違った発想はでるわけがない。
私はあくまでも「関数型プログラミング」の範疇で話をしているので、言語内の値の話をしてますよ。
哲学の話や意味論の話は聞き飽きました。「関数型プログラミング」における「参照透過性」の話をしてください。私の書き込んでいる「日本語」が理解できますか?
理解できるよ。
こいつが「哲学の話や意味論の話」を聞き飽きようが、こいつの主観がどうであれ、
そもそもの「参照透明性」「参照透過性」という厳密な議論や定義がある哲学用語、意味論のはなしを、なんか意味を捻じ曲げて混乱を引き起こすだけのBuzzワードとして「関数型プログラミング」ローカルで、数学のアタリマエの作法を言い表すためだけの目的で狂った形式で輸入された事実は変わらない。
「関数型プログラミング」における「参照透過性」の話をしてください。
うん、だからやってるじゃない。
これが馬鹿げた無意味な造語としてプログラミング分野に輸入されたにすぎないって狂った状況を説明しているんだ。
おまえが納得しようがしまいが、経緯と事実と、王様は裸だって言えない愚者が量産されてる狂った現状は変わらない。
関数型言語のプログラマたちは、それら命令型言語を「参照透過」とは呼びたがらないでしょうから、そういった複雑な数学的・観念的オブジェクトを「値」であると認めることも嫌がるでしょう。それでいてそれらの状態変換器が、彼らの好むところの文法や「モナド」などというバズワードによって取り込まれるや、「値」と呼ぶことに抵抗がなくなるようです。この姿勢は一貫性に欠くではないかと言わざるを得ません。たとえ彼らの「参照透過」の考え方にある程度の統一性が認められたとしてもです。
歴史を紐解くと、なぜこのような混乱が生じたかが、かすかに見えてきます。
つまり、ボトムラインとして、この記事のコメント欄で、わいてる一連の馬鹿どもは、定義からして結構デタラメなバズワードについて曖昧な定見で、さもわかってるように「参照透明」という言葉を使いまわしていた事実は間違いない。
僕は、なんか連中の通報でアクティブなアカウントが凍結されていたので「捨て垢」でとことんこいつら馬鹿の相手をしていたのだが、連中は自分らが寄りかかっていた「定義」がグラグラであることに気づいて、単に反論のための反論で食い下がってきた。
繰り返すけど、関数型プログラミングにおける「参照透過性」というバズワードの意味なんぞ、このエントリの前半で示したとおり、
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
数学ではアタリマエのことじゃない(笑
程度の意味しかない。
そして、探究心旺盛なひとが書いた記事のように、こういう人は本当に頭がいいと思うし、こいつら馬鹿どもと異なって、王様は裸だ!と言える人なのだが、オリジナルの参照透過性とは、もっと深い意味論の話であって、そんな意味論はたかだか
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
数学ではアタリマエのこと
という関数型コードのスペックを示すのに、何の関係もないし、必要どころか、害悪でしかない。
「関数型プログラミング」での「参照透過性」の概念が他の分野とは違うと書かれているのに、どうして総論的な結論が出てくるんですか?
くだらない混乱まみれの用語の自分らの過剰評価、王様が裸であることを認めたくないがために、その混乱ぶりを擁護する、そして
私は「関数型プログラミング」の範囲に限定して「Date.now() が参照透過である」ということを証明してくださいといってるんですが?
くだらん、馬鹿造語をもって、そんな破綻した概念をベースに「証明」なんぞできないんだよ。
せいぜい、
Date.now()っていうのは時間依存の関数であることは誰でも知っていて、
DateTime(Now)としでもするならば、時間依存の引数があると整合的に解釈できるし、
逆に(時間にせよ何にせよ)プログラム上に存在しない暗黙の引数を考えれば参照透明などと言い出したら、状態に依存したどのような関数も参照透明になってしまい「参照透明」という概念の存在意義がなくなってしまいますので、そのような定義があり得るとは思いません。
とかほざいてるけど、
状態に依存したどのような関数も参照透明になってしまい
なんてことはなくて、
Date.now と today()
なんて時間依存だって字面に書いてる特別な時間関数なんで、
「状態に依存したどのような関数」の話なんてしてないよね?ごまかさないでね?
そして、
「参照透明」という概念の存在意義がなくなってしまいます
そのとおりだよ。
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
数学ではアタリマエのこと
の意味しか、オリジナルと違って関数型の世界ではせいぜい、その程度の意味しかないんだから。
Date.now と today()
ってのは、字面で診ても、それぞれの関数定義においても、
時間に依存する関数だ。
今、今日という構成要素がこの数学の式には入ってる。定義としてね。
式の構成要素がすべて同じなら、式の値は常に同じになるということ。
今、今日というユーザの現在値という「引数」に呼応する値は常に同じだよな?
HaskellのIOモナドも、全部時間依存の関数というタイプをそろえているだけで、関数合成して、あとで、ランタイムがWorldっていう時間引数を入れるだろ?
それと何が違うの?馬鹿どもが。
以上です。
Quoraでの「関数型プログラミングが『銀の弾丸』であるという非常識な常識 2022」の書評
2021年末に基本フリーで誰でも読める形で関数型プログラミングの入門書をUPした。構想だけしてたりトライアンドエラーでゼロから書き直したりする時間全部ひっくるめると2年ほどかかった。かなりの長編ではある。
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
さて、
というのは、僕がQuoraでそこそこ熱心に活動していた頃に、Quora日本語版の運営からの要請を受けて、「Quoraスペース」のアルファ版の一環として僕がオーナーとしてQuora日本語版の最初の最初のプログラミングスペースとして立ち上げたものだ。
僕はもう昔から人にものを教える、伝達するという行為が好きで、QuoraというQAのSNSは性に合っていたし、そこそこの認知や評価もいただけていたとは思う。
最終的には、ウイグル人権問題が問題になりだした少なくともSNSレベルでは黎明期に、ひたすら中国共産党の代弁者みたいな中国人と揉めた結果BANされたわけだが、別にそれによって自分の政治的主張というか、単に想像を絶するレベルの人類への犯行についての批判、今、折しも北京五輪ボイコットで問題となっていることや、ましてやプログラミングの考え方が誤っていたからBANされたわけでもなんでもない。
このスペースは、なるだけわかりやすく初学者の皆さんへ向けてプログラミングの魅力を伝えられたらなという、自分が教えるのが好きというライフワークの一環として立ち上げたものでもある。
Quoraをやっていたころから多少関数型プログラミングに関するお話をしていて、僕の個人スペースなどもフォローしてくださっていた宮西さんという方が、今回の僕の著作を、この僕が立ち上げたプログラミングスペースで好意的に紹介してくださった。
すると、
まあ、毎度のパターンです。
必ずこういう輩が「電光石火」の如くネガティブなコメントを投下する。
なんでSNSってこういう人様への人身攻撃についてだけはこれだけ素早く熱心なんでしょうかね?
QuoraでアカウントBAN食らったのは、上述のとおりだし、曲がりになりにも自分で書いてもいる。
その他SNSについては、今回はてなに作ったこのブログエントリでも書いた。
2chの頃から続いているスレっていうのは、僕は刑事告訴した誹謗中傷スレッドだけど、この人物は、そのスレを半ば肯定的に紹介している時点で、まあしょせんはそういう人だ、というのはわかる。
というか、実際その刑事告訴した誹謗中傷スレに
スエナガって名前を見るんだよね。
どんな人物なんだろう?とQuoraのプロフィールを見たけど正体不明。まあ2chの誹謗中傷スレ関係者なんで当然だろう。本名かどうかも怪しい。
もちろん、自分がこの人を調べたらどうか?と訳知り顔に書き込んでるスペースが僕がアルファバージョンの頃に立ち上げたスペースだってことも知らない新参なんだろうし、書き込んでる人が僕のQuora時代からの知友ってことも知らないんだろう。
関数型プログラミングに目覚めた!IQ145の女子高校生の先輩から受けた特訓5日間
については、2015年の仕事だが、ES6以前のコードだし、なるだけ専門用語を使わずに概念だけを物語形式に埋め込んで解説しようとしたけど、用語の正確性についてはたしかに大切だし、自分自身満足した仕事か?と問われると反省点は非常に多かった。
そのためにも今回の著作があるわけである。自身の至らなかった部分も統合的に解説できるようになったし、なによりES6とTypeScriptの恩恵が非常に大きい。
それでも当該Amazon評価では、
そんなにわるくもない。そこそこの母数でそこそこの賛否両論と言える以上の評価だと思う。この人物がいうように★1レビューが目立つのは、とりもなおさず、こういう電光石火で人様の書いたものや人物を刑事告訴までした反社会的な2chスレすら肯定的に扱うような誹謗中傷好きの人間がアンチ活動に懸命だからだ。
実際に、良心的なレビューでは、
という感じ。ありがたいことである。
世の中とは、悪意に満ちた人間と、良心的な人間、前者はSNS時代の今、社会問題にもなっているが、こういう実名(かどうか怪しい)顔出し(かどうかもわからない)正体不明の人間でも恥ずかしげもなく一生懸命やっているということなのだろう。
QuoraというSNSは僕は政治案件でウイグル人権侵害を正当化する工作員みたいな中国人との喧嘩で最終的にBANされてしまったけど、誹謗中傷という点ではSNSのなかでも非常に気を配っていて安全な場所だと思う。
BNBR(BeNiceBeRespectful)というポリシーがあって、いくらBANされたユーザだろうが、こういう悪意に満ちた評判を貶めるような真似は控えるべき場所だ。
僕がまだ有効なアカウントがあれば、この、末永という正体不明の人物についてはBNBR違反として通報するだろうし、彼のこのろくでもない書き込みについては削除されることは確実である。
これに関連して、Quoraが比較的良心的なSNSであることは、そもそも僕が立ち上げたスペースに、知友が親切に紹介コメントをアップしてくれたこともそうだし、末永というろくでもない人物についてはそれなりに反論コメントが自然とつく、ということだろう。世の中悪いことばかりではない、というのが示されるのがQuoraの良心性をうかがわせる。
こちらの方は末永氏とちがって正体不明ではなく社会的属性も確認できる。
僕は実際にこういうブログエントリは書くような人間なので、人格批評はご自由に、といったところだが、大枠として、この人は反論を先人切ってやってくれた。その心意気についてはまず感謝申し上げたい。
ただし、「内容はそれなりに筋は通っており、まったくの間違いという事はないです。」
というのは、「まったくの間違い」からの否定と評価を限定的にする以上、また「それなりに筋は通っている」というのは、もし何かおかしいところがあれば、きちんと明示すべきだと考える。
「この解説から入って、さらに勉強を深めていく分には何ら問題ない教材と思いますよ。」
というのであれば、せいぜい「まったくの間違いという事はない」というような教材は甚だ不十分だと思うし、あえて反論のようなことをすると、
自分が実用性を求めて関数型プログラミングをするにあたり、このレベル以上に「更に勉強を深めていく分」というのはほぼほぼ存在しない。
やるのもちろん自由だが、せいぜい圏論がどうとかの分野で理論的基礎については、これでカバーできるように書いた自負がある。
むしろ、巷で理不尽によく引用されているモナドの説明が、IOモナド専用の説明であることがほとんどである、というかなりデタラメな状況について、ほぼ誰も何も言わないというかなり異常な状況こそが批判されるべきものであって、ここまでギリギリまで本質部分を切り込んだ文献はまず見当たらなかったので自分がはじめて書いたような感覚で、それこそが執筆のモティベーションでもあった。
正体不明の末永氏はくいさがる。
読む価値はあるよ。
というかなんで、どこの馬の骨とかもわからない数学愛好者の中級者の書きなぐりが「指摘」として「正しい」ということに自動的になっており、僕の反論が「読む価値は・・・」みたいに漠然とした印象操作で終わってるんだろうね。
しかしよくも全部ネガキャン記事3本もぱっと出してくるものである。
僕は非常に不愉快で面倒くさいけども、「いつものごとくの反論」とか揶揄してるんだけども、こういう人間が近い将来こうやってネガキャン記事を耳揃えてだしてくるだろうと事前に予測していたから、結構面倒くさい気持ちも押し切って、「読者の良識」みたいなものは、こういうネガキャンの前では無力化されるから、著者本人として最低限でも反論を紐付けようとしたんだね。今こうやってこういうQuoraのネガキャンにたいして反論するのも、内心「くだらない」とウンザリしているが、同じようなネガキャン再生産の種として近い将来悪用されるにきまっているのでこうやって年末の朝方の生産性のたかい貴重な時間を割いて書いてるわけ。
僕は、
以下、このTwitterで「ネガキャンやるぞ」と決心した人間について、いかにトンデモかということをそれなりにハッキリとした証拠に基づいて論証したわけだけど、こういう人物については真実なんてどうでもよいのだろうし、なんでこの正体不明の末永という人物がトンデモ中級者による「間違い」の「指摘」とやらが無条件に正しいものとして受け入れているのかは、一切合理的な説明はない。
おそらくこんな人間に、正しい判断なんてできる知見なんて最初から存在しないのだとおもう。
少なくともここまで僕の著作について間違いだと断定するのならば、そのTweetの指摘がトンデモではなく正しいことを追証すべきだろうとおもう。
文脈より、ここの「反論」とは、ネガキャンやってる中級者によるレビューのことらしい。実際に彼らの僕の著作への論評なんぞ「たいした内容じゃない」し「言いがかりをしたい人が重箱の隅をつついている程度」であるのはそのとおりだ。
まさに、僕がそれこそ各記事のコメント欄で地道にこういうブログエントリのような「反論」をひもづけていることもきっと役立っているだろう。
伝わっているようであれば嬉しいことではある。
これに喚起されたのがさらに良心的なコメント。
以下、それなりにしっかりとした知見のある方だとわかるし、末永氏のように正体不明でもなく、社会的属性がしっかりと確認できる。
なにより購入していただいた、と著作の価値を認めていただいたことに感謝申し上げたい。どうもありがとうございます。
>圏論に関しては結構丁寧に説明して有るのですが、私的にはモノイドについてもっと言及して欲しかったです。
モノイドについては、圏論の範囲で論証するのは大変面白いのですが、かんたんなことではないのは巷の文献からみても明らかです。
圏論におけるモノイドというのはかんたんではありませんが、実際本書ではそこそこ分量を使ってモノイドの性質についてはあくまで小学校から学ぶ+やらの二項演算の代数学の範囲で説明していますし、それで十二分だとおもっています。
>実際モナドの連鎖は同一の型のモナド間でしか行えないのは、このモノイドの特性に由来しているのではと思っています。
これはFunctorの章で説明もしていますが、そのとおりです。
>(勉強中なので断言ができるレベルには至っていません。関数合成は受け渡しを行う関数の間で値が一致していればOK)
値ではなく型(Type)の一致です。
関数適用の演算子はパイプラインオペレータで、これはIdentityFunctor=IdentityMonad
であるので、当然型(Type)の一致が必要で、
より複雑な構造をもつ
MapFunctorでも同じように型(Type)の一致、この場合ではArray[] ですが、一致しています。
ただし、IdentityFunctor=Monadと同じレベルで自由に合成はできないので、
flatMapFunctorにすることで、= flatMapMonadで、identityMonad=パイプライン演算 と同等の自由度が獲得されます。
>、Javascriptでは自然な形でカーリー化ができないので、どうしても無理やり感が否めません。f x y = x + y に f 1 を投入して普通に y を引数とする y + 1 の関数を返す事が出来ません。コードを作成して対応は出来ますが、引数の数が変わる度にコードを書き換える必要が出てきます。それに無限配列が使えないのは意外と地味に不便で、演算開始段階で明確な終了条件が決定出来ない場合のカウンターとして使用できません。λ計算で有名なYコンビネーターも同様にそのままでは実現出来ません。実務で使う場合にはこれらが無くても問題は無いのですが、関数型プログラミングを学習しようとすると物足りない感があります。という事で、しっかりした?関数型プログラミングを学習するには、今一つ感が拭えないのが正直な所です。
これについては何が問題とされているのか対象がよくわかりません。
JavaScriptでもHaskell同様にunaryFunctonでのカリー化した扱いは同等にできるので、JavaScriptの自然なカリー化
f x y = x +y
というのは
f = x => y => x + y
となるだけですね。
おそらくHaskellでは
JavaScriptでいうところの
f(x,y) = が自然と
f x y と暗黙unaryFunctionのカリー化記法ができる、ということをおっしゃってるのでしょうが、この記法の違いはHaskellは簡潔さですぐれいるがJSのアロー記法でもさほど問題なく、本質的な違いは生まれないと思いますが。
>関数型プログラミングでは有りませんが、関数型言語の説明は以下のページが自分的には、一番しっくりきたのでアドレスを張っておきます。11. 関数型言語 - プログラミング言語論 ドキュメント
については、自分は全く評価しません。
これまでこの手の関数型プログラミングの説明を山ほど読んできましたが、それによって、自分が今回著作としてまとめたような概念は手に入らなかったし、具体的にどういうのが関数型コードか、ということがわかったことはありませんでした。
たとえば、二項演算を著作では一貫して強調していますが、Haskellのモナド則にしろ、あれはすべて二項演算で表記されています。
圏論でいえば集合の圏の範囲だけが、射は関数に、対象は集合となるので、関数型コードの範囲となるので、モナドは二項演算になるのが当たり前で、二項演算とは、二項関数のことにほかなりません。
という二項演算であるのは「誰の目にも明白な事実」なのですが、
モナドが二項演算であることは、まるで説明されていません。
なんででしょうか?僕には意味がわからないですし、誰も文句を言ってるようにも見えません。それどころか、
で引用したとおり、
FunctorとMonadは二項演算か?
誰がどう見ても、Haskellモナド則でも二項演算でしかない、Haskellのモナドについて、説明しているのを読んだ後か、読んでもいないのか知らないけれど、
Monadは二項演算か?
などと重ねて疑問を呈してきて何も感じない、平気ぽいのが、このHaskel界隈の現状で、僕はこれ病的なレベルだと思っています。
間違い
二項演算なのだから当然、二項演算子がある。
というのが正しい。
Monadについては「二項演算」だけじゃないだろって感じですが。
とか書いてるのは、この中級者による数学用語の使い方がデタラメで、この中級者は、
「二項演算」という代数構造がなんたるか全く理解できていないのは読めばわかることです。
こんなもんをもちあげる、しかも僕の著述、解説が間違いだと指摘していると公の場で発言できるということは、末永氏のことですが、同レベル以下であることが明白です。
恥ずかしくないのだろうか?というレベルです。
しかし実際にこういうトンデモが出回っているのがHaskell関数型界隈の病的な実情で、僕自身は、最初そういう言語界隈を無条件に信用していたので本当にひどい目にあいました。なんでも無いことを理解するのにとんでもない遠回りを強いられました。
同じ苦労を初学者の人々に味合わせるのは忍びないし、自分がわかったならちゃんとわかりやすく解説する義務責任があると一種の使命感をもって著作をかきあげたのです。
その行為については褒められても、
「内容はそれなりに筋は通っており、まったくの間違いという事はないです。」
「この解説から入って、さらに勉強を深めていく分には何ら問題ない教材と思いますよ。」
と書かれたとしても、君ら本当にわかってたのか?
わかってたらなんでこんな有様になっている?と疑念を呈さざるを得ません。
実際に、
に戻りますが、
参照透過性
というのは、別エントリで年内、今日にでも決着をつけるべきテーマなのですが、この概念によって関数型コードがわかるようにはなりません。
なぜならば、
1+2=3
とかいう小学校の頃から慣れ親しんでいる二項演算は、二項関数と等価であり、この式こそが関数型コードだ、みたいな説明こそが大事だからです。
自分が読んだ本、あるいはこういう持ち上げられている解説ページに、小学校の頃からやってる二項演算が関数型コードの式である、という単純明快な解説がなされているのをこれまで見たことがありません。
そして二項演算ってのは、数学の定義上、ここで言われる参照透過性があるわけですが、誰が、これまで二項演算やるのに、参照透過性が重要だ、みたいな教育を受けたことがあるのでしょうか?
1+2=3
という二項演算の式=関数型コードのあり方を理解するためには
「参照透過性」とは完全に不要な用語です。
そしてこのページに不要に、それこそデタラメな定義というか定義もされておらず不要に使われている「その時点での状態」あるいは「変わらない」「変更してはいけない」
という言葉の使い回しこそが、本書で解説している「時間」に依存するグラフ構造、のことで、こっちのほうを、わけのわからない「参照透明性」をあたかもわかったように解説していることより、解説対象として注目すべきなのですが、解説してるつもりの張本人である書き手がおそらくそんなことは気にもとめていないので、このわけのわからない「参照透過性」という正体不明の用語が再生産されて拡散されています。ありがたがられるように。
11.4. モナド
についてもひどいものです。
モナドという二項演算の代数構造は、参照透過性という概念とは独立事象です。
たとえばパイプライン演算は、IdentityFunctor=IdentityMonadですが、
1 |> plus(2) = 3
というのはモナドの二項演算ですが、参照透過性という概念とは関係ありません。
というより、二項演算という代数構造で参照透過じゃないものなんて存在しないのだが、そんな代物をもって、説明しよう、できると思ってる時点でかなり異常な世界なんですね。
参照透過?といわれたら、二項演算なんでそりゃ当たり前に参照透過だろう、と言い捨てるしかない、モナドという代数構造について、参照透過という概念でモナドを説明しようとしている。相当頭がおかしい世界なんですね。
で、僕がそういうことを書くと、なんか叩いてくる連中がいる。彼らには合理的な説明ができないのはご覧のとおりです。
当該ページを引用すると、
参照透過性は関数型言語の重要な性質だが、それでは困る場合もある。
-
乱数を使う場合。
random
が毎回同じ値を返しては乱数にならない。 -
入力を行う場合。例えばキーボードから一行入力する
getLine
は、人間が入力した値を返すので、呼び出されるたびに違う値になる。
-
複数の出力を行う場合。例えば
putStrLn("1")
とputStrLn("2")
を評価すると、1と2のどちらが先に出力されるかわからない。
上のような事態に対応するため、Haskellはモナド(monad)を導入した
これらはIOで、このページの解説でもキレイにすっとばしている「時間」に依存する式のことです。
なんのことはない時間に依存するならば、時間に依存するような数学構造を定義してやればいいだけのことですが、Haskell界隈では、非常にこの辺苦労したみたいで、IOモナドという、IO専用の関数合成の仕組みを導入しましたが、大方は意味なんて理解していないので、こうやって、なぜかモナドという二項演算の解説の冒頭にIOという全く関係ない独立事象をもって紹介するのがHaskell界隈のモナド解説の非常に病的なクセです。
そして、流石にまずいと感づいてはいるのか、
などと、とってつけたようなモナド自体の説明をするのだが、こんなもんがモナドの説明になっているわけもありません。
「データに対して付加的なデータをくっつけた新しい型を作り、その型のデータを複数の関数の間で受け渡す仕組み」
JavaScriptのMapメソッドの拡張であるflatMapメソッドで確認してみましょう
[1].flatMap(a => [a +1]) // [2]
ではあるが、
「データに対して付加的なデータをくっつけた新しい型を作り、その型のデータを複数の関数の間で受け渡す仕組み」
という言葉で、なんかモナドのことがわかる、という初学者は全世界に誰一人として存在しない、と断言できます。
そして、参考資料としてあげられているのが、
ですが、これ両方とも例にもれずIOモナドのこと「だけ」を書いています。
2個めは表題からも明白ですが、1個目は、
これは表題として「モナド入門」と決め打ちしています。
関数型界隈のブログ執筆でそこそこ有名な人ですね。結構検索にひっかかります。
気まぐれと偶然となりゆきで、ここ2,3回はモナドを話題にしました。googleで「モナド」を引いてザッと眺めると、「モナドはむずかしいー」とか「モナドで挫折した」みたいな雰囲気が感じられて、説明芸人の血が少し騒ぎましたね。「なら、予備知識ゼロでモナドの説明をしてやろうじゃねーか」と。
タイトルはだいぶ煽っちゃった…… けど、ハッタリじゃないつもり…… けど、実際はどうかな?
プログラミングでモナド機構を使うと、関数、値、計算などの概念を一気に拡張することができます。うーん、ステキ。でも、モナドを採り入れているプログラミング言語の例をHaskell以外は知りません(たぶん他にもあるでしょうが)。そもそも、モナドが少しだけポピュラーになったのもHaskellの影響でしょう。
これに関しては正しい部分もあるけど誤解を招くアルアルです。
ただ少なくとも、IOだのピュアだの現実世界だのモナドそのものとは独立事象と絡めてしか説明できないアレな人々よりはかなりまともなアプローチだとは評価できます。
これ、Monadに先立って、絶対に説明しなければならないのは、本書でもMonoidの次に説明したFunctorです。
正確には、
プログラミングでファンクタ(Functor)機構を使うと、関数、値、計算などの概念を一気に拡張することができます。うーん、ステキ。
と書かなければいけません。
本書で解説していますが、Monadの良いところはせいぜいFunctorに二項演算合成してもパイプライン演算(IdentityMonad)のときのように壊れなくなる、あと構造に少しアプローチ可能になるというメリットくらいで、ここで言われている
機構を使うと、関数、値、計算などの概念を一気に拡張することができます。うーん、ステキ。
の旨味は「すべてFunctor」から来るからです。
MonadはEndoFunctorの特殊なケースです、念の為。すべてのMonadはFunctorでもある。
●こんな課題を考えてみよう:副作用付き計算
モナド概念は非常に普遍的なので、モナドの実例はとんでもなくイッパイあります。モナドの実例をいくつか出されると(例えば、リストと状態遷移と例外と入出力)、それらがモナドという単一の概念でくくれること、共通性を持つことが信じがたいでしょう。
そこで、モナドの実例を1つだけ選んで、その特定事例をシッカリ説明することにします。その実例とは副作用付き計算です。副作用とは、関数、メソッド、手続きなど(計算/処理の単位)が、外部(環境)に影響を及ぼすことです。例えば、ローカル変数以外の変数への値のセット、ファイル入出力、画面への描画などは副作用です。
副作用がなくて、純粋に計算だけを行う処理単位を純関数と呼びましょう。純関数の値(計算結果、戻り値)は、その引数値だけで決定されます。同じ引数を渡すなら、いつでもどこでも何度でも同じ値を返します。それが純関数ってもんです。
でました。さっそくIO、副作用の話です。
なんで、この人らは、Monadという二項演算の話を、Functorもすっとばして、いきなりIOという「別の概念の話」しかもプログラミングで扱うのに「時間」のグラフ構造の代数も考えるので、結構面白くもあり非常に大事な話をこうおいう「おまけ」みたいにしてモナド(Monad)の説明にしてしまうのか?
かなり異常な世界ではありますが、誰も言わない、僕ぐらいがいう、そして本書けば、こういう異常な世界になれてるのか、なんか僕の解説のほうが異端で、先にすすめば「より正確な」IOの説明がある、みたいにゆってくる。
ここで繰り返し声を大にして言いたいが、モナドというせいぜい関数型の世界では二項演算という代数構造の具体的な説明をするときに、IOなんていうそれ自体クセがある概念と絡めて説明すべきではない。
Haskellで苦労して導入されたIOモナドの歴史があろうが、そもそもあんなもんはIOファンクタであっても結果は同じです。
関数合成ならばファンクタはモナドになるんだから。
そしてその後延々とIOモナドの実装の話が続きます。
●そして、これがモナドだ
ここらで今までの経緯をまとめて、モナド概念を正式に導入しておきます。
振り返れば我々は; 関数から副作用を取り除き(汚れ作業はCountupMainに押しつけ)、代わりに戻り値に副作用の意図を詰め込み、それによって失われた関数結合の自由さを関数の拡張により取り戻しました。これらの背後には、次のような約束事/手順があります。
「モナド概念を正式に導入」と書いているので期待感をもって読むが、まだIOの話をしています。関係ないのに。
一般的なモナドも同様で、次の3つで定義されます。
- 型Tから新しい型M(T)を創り出す型構成子M
- fun:T→M(S)という関数からext(fun):M(T)→M(S)という関数を作り出す関数(高階関数)である(M用の)ext
- 型Tの値を、M(T)型のデータにする関数である(M用の)unit
なんでに二項演算だと説明しないのだろう?
Functorというベースとなる構造の拡張であると説明しないのだろう?
モナド(M, unit, ext)は、3つ組なら何でもいいわけではなくて、モナド法則という法則を満たす必要があります(今は触れません)。
いや、モナド法則とは二項演算の式だし、
「今は触れない」のは、それは、僕が本書でやったようなMonoidの説明、左右の単位元の説明をやってないのでできるわけがない。
大方、
世界で一番か二番くらいにやさしい「モナド入門」
というのは、こういう、IOという関係ない概念に依存していて、肝心の二項演算の結合性とか左右の単位元とかいう代数的性質については一切語らずに終わります。
そして、読むべき参考文献として列挙されています。
いや、こういう解説は僕の本の「先」の位置づけとしては、ないですよ?
と言っておきたい。
フェアに読み比べてみれば良いと思う。
あと、僕が読んだ世界で一番悲惨なモナド解説は、
こういうのがありました。
あとこういうの
ふたつとも「世知辛い現実世界」だとか「ピュア、純粋」だとか副作用がどうとか書いています。
たとえば、MonadのベースとなるEndoFunctorでは「一切」こんな言葉は使われずに結構正確に説明されていることがほとんどですが、ちょろっといじってMonadに拡張した途端にこういうわけのわからない現実世界と妖精みたいなファンタジーランド、IO一辺倒の世界観になるのは、本当に異常な界隈だと思います。
そういうのが普通で、普段こういう輩については黙認していたり本気で勉強になったとおもってるぽい連中が、まあ僕の本については間違っていないみたいな論調でなんか言ってくるのは本当に勘弁してほしいし、これが関数型界隈の病的なあり方である、という事実を確認しておきます。
念の為ですが、至って擁護的に長文をもって書評していただいた、そして実際に購入もしていただいた事でも明らかですが、Matsumoto Kazuhisa 氏には上記の僕の考えがあることを添えながらも、今一度感謝申し上げます。
Ohkubo Kohei氏には、まあ個人批判に便乗しながらも一応は問題ないと先陣切ったという点には感謝申し上げます。
宮西さんにはいつも有用なフィードバックもいただいている上にこのように好意的な紹介については感謝いたします。
正体不明の末永という人については、まあこういう人らには本当にうんざりしています。なんら中身がなく悪意があり、教育側面でいえば悪い効果しかもたらしていないでしょう。BNBR違反でもあります。
【『関数型プログラミングに目覚めた!』のレビュー(Day-1)】へのレビュー
まず直近の著作としては、2021年末に公開した
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
がある。
その上で、2015年初に紙の書籍として出版した本へのレビューが
Qiita上にあり、
これは、当時、誹謗中傷、名誉毀損で刑事告訴して事件化していた犯人界隈がQiitaの捨てアカウントを使ってコメント欄で議論を茶化す、妨害するという惨憺たる結果となったレビューである。
主犯はこいつ。現在も継続している。
$ analyze @Sacchii-aum
投稿した記事
No data
LGTMした記事
No data
回答した質問
No data
またスパム捨て垢を急遽こしらえて荒らしに来たんだ?
@Sacchii-aum は僕が刑事告訴した誹謗中傷犯
ちくわ 芦田真一
でQiitaにも捨てアカウントを継続的に作成しながらネットストーキングしている。
https://twitter.com/tikuwa_zero
上のアカウントデータでも明白なとおり、極めて特異な挙動を示しており、本件専用にコメント欄を荒らす目的でQiita上に急遽作成した捨て垢。しょせんこれがQiitaの炎上の正体。
元のレビュー主は、今回の著作である
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
につっかかってきた連中
と同類のアレであるが、
自分はQiitaを「その当時の経営陣(今はもう売っぱらって総入れ替わりしている)」からBANをされて、うまく立ち回れなかったので、十分に誤りを指摘して反論する機会に恵まれなかった。
結局は、あろうことか、当時のQiita運営がこういう匿名炎上目的のアカウントの思惑に乗っかる形で、僕の反論コメントを消してしまったので、現状、間違ったネガキャン情報がそのまま残っている。
Qiita で散々やってたじゃん。
— 斜月三星堂 (@littleHaskeller) December 10, 2021
それでも理解できない君に、今さら同じような説明をしても無駄でしょ?🤣🤣🤣🤣🤣🤣
説明された内容を忘れたのなら、Qiita を読み直したら?
君と君の分身が書いた内容は読めなくなってるけどね。🤣🤣🤣🤣🤣🤣🤣
とか、今さら来るので、ああ馬鹿相手の沙汰でもちゃんとカタつけておかないと、馬鹿が延々やってくるんだな、と確認したので、本エントリでは一連のネガキャンを是正する。
まず、この本はES6(ES2015)以前の時代の著作であり、直近の本のように洗練されたことはなにもできていない。
これは当時のJavaScriptの限界であって、その総括もしたくて直近の本を書いたということもある。
2015年当時のその仕事は、現在の基準ではけして満足がいく仕事ではないが、至らない部分に目をつけられて不当なレベルでネガキャンをやられてしまったという不当性は、2022年バージョンの現在に至っても、同じようにネガキャンやられてるところをみると、結局は内容の不備とか、結局連中にはどうでもよくて、実際後で書くけれども、自身のいい加減な主張でも相手が差し出す渡船があれば乗ってしまう茶番とか、内容なんてどうでもよいなだろうなと強く再確認できる。
それに加えて、前述のような刑事告訴した誹謗中傷犯がQiita上で攻撃してきたので、このレビュー記事はグダグダになってしまっている。
0 から 9 まで列挙した配列、この本の問題として本質的ではないという意見。しかし、この例を選んでしまっているところにリスト、配列、空間コスト、評価戦略などの関数型プログラミングの大切な概念に対する無理解が見て取れるため極めて象徴的であるのです
— Jun Furuse 🐫🌴 (@camloeba) May 9, 2015
という文句もあるが、今回の2022年の著作でも踏襲した。もっとも適している題材だし、この人物は、
らくだの卯之助 (@camloeba)
プロフェッショナルな関数プログラマと紹介されているが、2chの僕を標的にした誹謗中傷スレッドで活躍していた。
プログラマでもなんでもない、橋にも棒にもかからない、じょうきの「ちくわ」はそのスレで、こういう技術的になんか言いいた中級プログラマ連中と一緒になって、個人攻撃をからめてありとあらゆる方策で攻撃を試みていた。
素人としては深入りを避けたいと思いますが、そうだとすればそもそもJavaScript選んじゃったのが関数プログラミングへの無理解を象徴的に示すものなのだということになるような気がします。)
結局はこれ。
ES6(2015)以降はかなり、こういうものいいは減ってきたものの、2022年になろうとしている今でも、JavaScriptと関数型プログラミングの相性が悪いというのは、こういう文句垂れの連中の一貫したテーゼだ。
ほぼ全員が同じことを言ってくる。
要するに、僕をコケにしたい裏にはベースとして、連中がそういうHaskellやらMLやらOCamlやら関数型言語と認識されている自分の世界で愉しんでいて、そこで得た考えから、JavaScriptは違う、と信じている。というより、自身の言語選択の好みをスキをみては押し付けてくるという感じか。
誤解のないように言っておきたいのだけど、僕は本書でもTC39を批判というか糾弾に近いことをしているし、言語としてJavaScript最高!みたいな信者でもなんでもない。
TypeScript含めて専門ではあるけれども、関数型の入門として、誰がMLの本を読みたいのか?と正直思うし、実際シェアとしてはJavaScriptは圧倒的で、小学生の入門言語としても採用されている実情があるので、その路線でアプローチしたいというのは、2022書籍の冒頭で書いている通りだ。
こういうMLやらOCamlの連中は、自己中心的な連中でそういう初学者に誘導という考えなんてない。
そして初学者むけに姿勢をさげたら、その姿勢をさげる、というのを弱みみたいにおもってなおさら攻撃してくるのがかなりタチが悪い。ようするに「ナメてくる」わけである。
「問題の論理」?
これについては、2022年書籍でいうところの「課題の本質」だ。
しかし、たとえば「与えられた配列
s
をソートせよ」という問題を与えられたらどうするんでしょうか。s.sort(isGreater)
と書け、ということなんでしょうか。肝腎のそのsort()
はどうやって書けばいいのかは、およそ「問題の論理」からは出てこないように思います。
まあそのとおりだね。
「課題の本質」か「課題の解法」が導かれるのではないのは自明のこと。
ここで書いているのは、「課題の本質」ではない制御構文、フローについて余剰の解決をする必要があるということ。
どうやら「クールなコード」を書こうとする限り、ソートを行うコードを書くことはできないようです6。とすると、「神の目」はどうやら役立たずだということになるでしょう。
「課題の本質」に即したコードを書こうとする限り、課題の解法は得られないようです。。。とか言ってるのと同じで、まあ単なる揚げ足取り。
ネガキャンやりたいんだなーってのが伝わってくる。
「関数という論理操作」?
これについては、まあ揚げ足取りの続き、とみなすこともできるが、ある程度正しい批判はしている。
ただし、関数が写像だ、なんてことはわかっており、あまりにも初心者の日常生活に寄せすぎて、アナロジーがうまくない、ということ。
実際これはありがちなミスであり、モナドをIOモナドの説明と同一化して、妖精がどうちゃらピュアな世界がどうちゃらとか書いてる悲惨な解説があるので、この要素については文句垂れたい気持ちは共有できる。
「『まとまり』は美しい単一の論理構造」?
これについても指摘は正しい。
といっても表現の問題ではある。
今らならこれはこんな抽象的なことではなく、Monoidという代数構造である、と変に数学的な概念をさけずに、ストレートに説明すべきだというのはわかるが、当時は、まさに「妖精とピュアな世界とモナド」みたいなアホなアナロジーが機能すると過剰評価していたきらいがある。
追記(2015/05/30):デスクトップアプリケーション??
これについては、最新のコードは、おおむね、FRPで
として公開している。
FRPでなければならない。
そのことは、
状態機械の数学的構成では状態遷移が状態と入力から状態への関数として表現されるというだけのことではあり(状態渡し)、状態遷移が複雑になれば状態遷移を純粋な関数として表現する作業も複雑になり困難になるので(そしてそれはしばしば綺麗な関数合成では上手くいかないようなものになることが多いので)
と書いてる本人も理解しているようだ。しかし、
結局のところ少なくとも現状のFRPも(イベントのシグナルから状態のシグナルを構成する際に状態遷移をそうした関数で表現する必要が出てくるので)本質的には銀の弾丸にはならないと言わなければなりません(関数プログラミングで書けるということの恩恵はもちろんあるとしても)。
というのは、間違いで、
(イベントのシグナルから状態のシグナルを構成する際に状態遷移をそうした関数で表現する必要が出てくるので)
となにかわけのわからない共通項をデッチ上げて有効性を否定するポーズは見せているがなんのことやらわからない、というのが事実。
ほかにも、著者が本書の執筆期間にStackOverflowというサイトに投稿した質問(
reduce
をmap
で定義するにはどうしたらいいかという質問です)を見れば、著者がmap
とreduce
について何も理解しないままに本書を執筆していたことは明らかです。
これは、2chででっち上げられたデマであり、このQiita記事を書いている人間が、その2chスレの住人であることを確認できた事案であった。
これは、直近の2022書籍でいうと、mapFunctorの挙動で、MonoidのFoldを表現することが可能か?ということを考えており、reduceからmapが構成される、なんてことは百も承知である。
StackOverflowの回答者の不遜さは当時特にひどかったので、その不遜さも、あたかも僕がコケにされたという印象を連中に利用されることになっていた。
誹謗中傷犯が2ch界隈でわーっとなっているタイミングでは「良い攻撃材料を見つけた」ということで頭がいっぱいになっているわけで、所詮この書き手も、ネガキャンやりたいのでその事実を最大限に拡大しようとしていることが見て取れる。
実際にmapではなくてモナドであるflatMapでは配列構造にアプローチできて、要素の数を増やすということができるので、当時、では要素の数を減らすことができるのか?と手っ取り早く確認するためにSOで質問したにすぎないのだが、回答者は馬鹿にするだけのアレだったし、その結果を悪用されたにすぎない。
従って、
逆に
reduce
を用いてmap
をどう定義すればいいかも関数プログラミングの勉強を始めたその初っ端に出会う練習問題に過ぎないような本当に基本的な話題に過ぎません。このような著者に対して関数プログラミングに関して技術的になにか意味のある「反論」を期待することはできず、つまるところ本書と著者についてはもはやこれ以上なにをしようもないのです。
というのは、誹謗中傷に過ぎない。
次のコメント
だが、こいつが、
— Jun Furuse 🐫🌴 (@camloeba) May 9, 2015
らくだの卯之助 (@camloeba)
による捨てアカウントである。
逆に、岡部氏のコードはよく見ると state = x; という部分で
カウンタ変数への破壊的代入を行っており、何ら関数的ではありません。
(無駄に複雑なスパゲッティ・プログラムですが、よく読むと要するに
state = state + 1; と同じ破壊的代入です。)
これについては、2022年書籍についても、まったく同様で「破壊的代入」を使っている。
その正当性はこういう中級者除けのためにもうちょっとうまく説明できていて、
からはじまり、
(引用終わり)
ということです。
FRPの実装では、「必ず」いずれかの時点で破壊的代入が行われています。
その理由については本書の
を読めばわかるでしょう。
もっというとこれでわかると期待したいのですが、もしわからないのであれば、加筆対象になりえます。
岡部氏は
『関数型プログラミングのパラダイム内で、そういうマウスボタンが押されているのか、押されていないのか?入力の状態が時間遷移していく場合、上記ブログエントリでも論じたSICPでも、拙書でも解説しているとおり、FRPの実装が必ず必要となります。
「時間」が本質的だから、時間をを集合、SICPの言葉でいえば「遅延ストリーム」とした実装が必要です。』と断言しているにも関わらず、現に私やnonstarter氏のコードのように
「時間」も「ストリーム」も出てこない関数的状態渡しによる実装が
容易である以上、岡部氏の誤りは明らかだと思います。ご参考まで。
基本的に、このOCamlのらくだなんとかは、FRPのなんたるかは勉強していないことが伝わってきます。
継続渡しなんぞ誤魔化しのテクニックでは、複雑な関数合成などでは通用しないとのはこのQiita記事書いてる人間もわかってることで、応用範囲の広いフレームワークはあくまでFRPです。
(編集済み)
hiyakashi_さん
著者がFRPを実施しているとは言えないと私は考えています(ブログに掲出されたクリックカウンターのコードでカウンター用の変数を破壊的に更新していることに鑑みても)。
foldp
については、以前に私がElmを試した際にfoldp
に渡す関数がやたらと複雑化・肥大化してしまったことの印象が強いせいもあるのでしょう。私の扱い方がヘタクソだっただけかもしれません。私はシグナルのもっとも重要な用途が状態の保持であると思っているので、先行する状態に依存する状態を与えるために必要なfoldp
(やその相当物)がFRPにとって非本質的だとは思っていません。ともあれ、ご指摘に対応して本文の該当箇所には手を加えました。
Lambadaさん
ご指摘についてはその通りかと思います。
まあ、なんかかなり適当なことを書いていますね。
2022の書籍では最後の方でReactiveFunctorからのMonad化と精緻に解説している。
基本的な考え方は2015年当時となんら変わっていない。
こいつらが、「ご指摘についてはその通りかと思います。」とかやってるのはネガキャンやりたいばっかりの茶番である。
たとえば、最初は
状態機械の数学的構成では状態遷移が状態と入力から状態への関数として表現されるというだけのことではあり(状態渡し)、状態遷移が複雑になれば状態遷移を純粋な関数として表現する作業も複雑になり困難になるので(そしてそれはしばしば綺麗な関数合成では上手くいかないようなものになることが多いので)
状態渡しでは複雑な応用局面になると困難になる、とわかっていた言及をしていたのに、FRPを否定したいばっかりに、
現に私やnonstarter氏のコードのように
「時間」も「ストリーム」も出てこない関数的状態渡しによる実装が
容易である以上、岡部氏の誤りは明らかだと思います。ご参考まで。
となんかネガキャン材料を渡されたら、
「ご指摘についてはその通りかと思います。」
と、ころっと立場を買えてしまったw
再度断言しておく。
状態渡しなんぞではできることは限られている。
FRPではすべての局面で利用ができる。
とりあえず現時点でUPしておく。
あー最後に。
参照透過性については別エントリでやる。
あと、
特に、状態渡しでFRP不要説をぶっこいている連中は、
本書(2022)で、
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
(引用終わり)
このコードは、そのOCamlの継続渡し(こっちが言ったんじゃない、かんたんに実装できるからFRPはいらんみたいなことをそちらが主張したんだ)でどうなるか、やってみて?
もしクリアしたら次の課題もだすから。
型はオブジェクト(対象)であり集合の圏なら集合 カリー=ハワード=ランベック(同型)対応
「関数型プログラミングが『銀の弾丸』であるという非常識な常識2022」の感想 - Qiita
- [考え方]
それな感。型はカリー・ハワード対応等で集合の様にも使えるけど、集合そのものではないよな。あとあの記事の理屈なんか全体的に対象がモノイドである事が普遍的な前提みたいなものを感じるんよな。何なんだろうアレ
2021/12/16 15:24
去年の年末に本書の超アルファ版をUPしたときに、冒頭に
のことを書いた。
まさに冒頭に結構なウェイトをもって書いたので、すこぶる評判が悪かった。
結局の所、こういう関数型の本を書くときには、目線は初学者に向いていなければならないという根本的な方針を徹底することとした。
なぜならば、自分自身、これまでの経験として、ほんとうに鬱陶しい障害となるのは、こういうちょっとわかった風の中級者連中であり、人様の本への論評にかこつけて、なんか偉そうにドヤって、あたかも著述の内容が正確ではない、というような風評を流すことがあるので、彼ら除けの「お札」みたいに権威を貼り付ける、という最低限の作法だけにしようと思ったからだ。
それが、「型は集合」の章であり、このブログでもなんどもしつこいように貼り付けているnLabの項目だ。
ここでもう一度繰り返そう。ここで二つの言い分がある。
ひとつは、どこの馬の骨ともわからない中級者が匿名アカウントでハテなブックマークに殴り書きしたようなコメント
それな感。型はカリー・ハワード対応等で集合の様にも使えるけど、集合そのものではないよな。
もう一方は、数学の引用文献としてそこそこ権威がある
「集合そのものではないよな。」という漠然とした言及が、極めて具体的に「初学者」むけではない解説記事に詳細があるのに、なんでそれを上書きできると思ったのかよくわからない。
おそらく、
型はカリー・ハワード対応等で集合の様にも使える
というハッタリ文句が効くと思ったぽいのは想像にかたくない。
本書の前バージョンから、この「カリー・ハワード対応」というお札を引っ込めた途端に、その分だけ、なんか言ってくるんだな、ほんとうに鬱陶しいと毎度実感する。
今回、おそらく「チューリングマシン」だとか「計算理論」とか、グラフ理論のところで、「関係がある」とだけ書いたら、それについてはなーんもイチャモンつけてこない。
モナドと圏論については、それについて集合の圏では二項演算である、とまさにそれがせいぜい、HaskellのMonad則のページで書かれている全部の範囲なわけだが、そいつはその演算子の定義のコードを自分で出しておきながら、いきなり集合の圏に限らないモナドの定義の話をしだした。
結局の所、くだらない連中には、手間がかかってもお札を貼り漏らすことがあっては行けないということを再度確認しなければいけない。
型はカリー・ハワード対応等で集合の様にも使える
という言及に、こいつは、nLab引用した部分の言及以上にいったい何の価値を感じているのだろうか?
と書いているのだが、ここで
と、まず基底は、圏は集合であり、射は関数となる、集合の圏が基底であると示している。ただし、こんなもんは、イチャモンつけたいこういうごく一部の、まあどうせろくに読みもしない読者対象から外したい連中しか気にもとめないだろう。
いちおう初学者向けに将来にむけて、という意味は断固あるものの、半分くらいはこういう連中除けのお札であることは否めない。
上記の図では、型はオブジェクトに対応している。
これは、ある程度の偶然もあるが、
のオブジェクトにも対応している。集合の圏では、集合だ。
カリー=ハワード=ランベック対応
において、
このカリー=ハワード=ランベック対応は直観主義論理、型付きラムダ計算およびデカルト閉圏との間の対応として知られる。ここでは
オブジェクトは型
あるいは命題に、モルフィズムは項あるいは証明に解釈される。
と書かれているそのものである。
元のQiitaのネガキャン記事では、型が集合ではない、とおもうという主張を、このブログ記事でも糞味噌に批判したが、TypeScriptの実装が、とかかなりトンデモな理路でやらかしているわけで、そういうトンデモにどのように「それな」と同調できるのか意味なんてわかるわけもない、まあこの人物がトンデモだという説明しか成り立たないが、せいぜい
型はカリー・ハワード対応等で集合の様にも使える
と、ボサーっとした意味不明なnLabの引用文を上書きするだけの論旨があるわけもない、
集合そのものではないよな。
ってのは、メタな観点ではこのような有用な観点で同一視されているものを、メタではない観点では、そりゃ
は、繰り返すとここで論じているメタな観点の同一視ではないレベルでは「そのものではない」のは自明なので、こういう主張の仕方するやつらって世の中で消えることはないけど、有害だよなあ、と思った次第。
基本的に、僕の書いたもんに文句つけてくる人間っていうのは、一様になんか思い込みが激しくて、最後には、自分の好きなPureScriptとかうAltJS使えとか、ML使えとか、自分の趣味領域の好みの発露をしてそれで満足みたいな、議論には適正のない、ましてや書評とかやってほしくない単に自己中心的な人種ばっかりで、迷惑だなあと思う。
JavaScriptには関数の末尾再帰最適化がないので関数型には不向きだというデマ
冒頭報告
当方を不当に侮辱、誹謗中傷した人間から謝罪文が掲載されている。
nantonaku-shiawase.hatenablog.com
本論
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022のなにがダメなのかわからない人が多いようなので、個人攻撃をまったくせずにダメ出しする。
また読まずにダメ出しするというアレが出てきた。
しかも、また致命的なレベルで勉強不足の分際で「しかし、簡単にダメ出しできる」とか宣っている。
こういう変な界隈の連中は非常に思い込みが激しいのと同時に、まともに勉強なんてしていないので、とんでもない勘違いワールド世界の住人である自覚もないのだが、ひとりで趣味でやっている分には「勝手にしろ」とか思うが、いざそれをこういう形で喧伝したり、ましてや他人様の著作にミソをつけるのが動機でやられたなら、こっちは黙っては居ない。
これまでこのパターンのアレな連中にさんざんこの類型の不条理なネガキャンをやられてきたし、問題は、それが間違ってると知ってる連中は黙ったままだし、問題のネガキャン当事者以下のアレはそろって、同意する、とかいって、あろうことかそのデマに「信憑性」のようなものを与えてしまう。非常に悪質である。
あの記事はめちゃくちゃ長いのに末尾再帰に触れていない
記事内を「末尾再帰」で検索してみよう。1か所もヒットしない。「末尾」でも1か所もヒットしない。そう、あの記事はめちゃくちゃ長いのに末尾再帰に触れていないのである。では「再帰」ならどうだろう。11か所ヒットした。しかし、具体的な再帰のコードはまったくない。長い記事内にあれだけ多数のコードを書いているにも関わらずである。
再帰については、まさに冒頭のreduceそのものに帰着して説明は完了しているので、特に必要ないかな、とは思ったが、ああやっぱ馬鹿な中級者はこういう角度から勘違いsて攻撃してくるんだ、とわかったので、このエントリ終わったら加筆に取り掛かってやろうとは思う。
末尾再帰の重要さ
「末尾再帰って何?」とか「再帰ってそんな重要なの?」と思う読者も多いだろうから、末尾再帰の重要さだけ説明しよう。
あの記事は、forやwhileを使わないプログラミング手法を前提に書かれている。記事内を「制御」とかで検索すればわかる。
末尾再帰はforやwhileの代わりになるもので、そういったプログラミング手法には欠かせない。forもwhileも末尾再帰も使わないとなると、ツリー探索などのアルゴリズムを書くことが困難になる。(こういったことが苦手な私に思いつく他の方法は、setIntervalを無理やりforループの代わりにするくらい)
「あの記事は 前提に書かれている。」
とか読んでもないやつがねー(苦笑
for や whileは、だから記事に書いているとおり、Fold/Reduceになるんだよ(ばーか)というか読めよ?
と言ったところだろうか。
というかなんでこいつら「読んでない」ということを誇らしげに言いながらこういうトンチンカンなこと言って生きてて平気なのだろうか?
異常者だと思う。
JavaScriptはたいてい末尾再帰をサポートしていない
そもそも、ほとんどのJavaScript実行環境は、末尾再帰をサポートしていない。つまり、JavaScriptはforやwhileを使わずに込み入ったプログラムをまともに書けるような言語ではない。あの記事に書いてあるようなことをする言語ではないのである。私は別にそれでもいいのでTypeScript使いまくってるけど。classとか好きだし。
あの記事がJavaScriptを使っている理由は、JavaScriptが人気だからだろうか?もしそうだとしてもダメである。あの記事は「JavaScriptは、ほどんどの実行環境が末尾再帰をサポートしていない、このプログラミング手法に適していない言語である」といったこと自体に触れていない。人気のある言語を使いたいなら、他の末尾再帰をサポートしている人気言語を使えばいい。
末尾再帰をサポートしていない、そのとおりだ。
そんなもんなくても関数型コード書けるし、末尾再帰が必要なコードっていうのは、理論的にはラムダ計算からの再帰ループを実装することでチューリング完全性を示したり、数学の漸化式の数列をそのまま実装することで理論的にはみるところはあるが、リアルなコードでそれをそのまま書くのは「アホ」だ。
これは、リアルなコードでYコンビネータをもってFold/Reduce式を書く人間がいないのと同じ意味で「アホ」なのだが、
Factorial(階乗計算)やらFibonacci数列のコードでは再帰の概念の説明に役立つのでサンプロコードとして示されていることは多くて、特にHaskellに足突っ込んでる系の中途半端に関数型プログラミングを知ってる「つもり」の中級者がひたすらそのアホなコードを再生産していて、以上の引用文のようなアホなデマを流していて甚だ有害である。
あの記事は「JavaScriptは、ほどんどの実行環境が末尾再帰をサポートしていない、このプログラミング手法に適していない言語である」といったこと自体に触れていない。
触れてないことなんて山ほどあるし、解説の流れの優先度ってもんがあるからね。
JSが末尾再帰をサポートしていない、なんてまったく重要な事柄ではないし、このプログラミング手法=関数型に適していない言語である、っていうのは、こういう勉強不足で知識不足の馬鹿連中の間違った知識にもとづくデマでしかない。
しかし、こういうデマを流して、しかも賛同する同類がいるとわかった以上、なるだけ早く触れざるをえないだろうということはわかった。非常に厄介である。
岡部さんの記事への反論。自分も筆者に同意する。>「関数型プログラミングが『銀の弾丸』」の記事がダメなところ https://t.co/T5ueeT18K4
— SEAHAL (@seahalcom) December 15, 2021
おまえがおかしいんだよ。
— ken (@ken80297274) December 19, 2021
おまえの勉強不足によって、僕の著作について不条理なデマ、誹謗中傷はじめたのはおまえだろーが。
こっちはそういうのでこれまで散々迷惑かってるので、今後は見逃さないし徹底的にやる。
おまえは侮辱されて当然の主張をしてるわけ。
かの有名な岡部さんとバトル中でござる。でも、拙者は末尾再帰は好きじゃないけど、無限ループを作り出す上で仕方なく使うという認識なのだが、岡部さんは末尾再帰はスタックオーバーフローとは無関係だという。
— SEAHAL (@seahalcom) December 18, 2021
だれも「末尾再帰はスタックオーバーフローとは無関係だ」なんて主張はしてないけどね。
— ken (@ken80297274) December 19, 2021
なんでおまえらはそうやって嘘の引用とかして平気ナノ?
Fold/Reduceの使い方を知らず、末尾先最適化が必要な再帰関数を書くしかないとおもってそういうコードを書くやつが低レベルでアホだと言ってるだけ。
以下、すでにこいつの返信は一部スパム認定されて見られないのでこちらの返信だけ引用する。しかしそれで十分である。
なんでろくに読みもしないで、駄目なところがどうとか、こんだけ上メセのわかった風の匿名連中ばっかで、同じ考えだとかいうアレが多いんだと思う?
— ken (@ken80297274) December 18, 2021
だいたいそういう言語のより好みをもって全否定してくるけど、factorialにしてもfibにしても末尾再帰のコード書くってこと?
— ken (@ken80297274) December 18, 2021
実際ディレクトリ構造とか知れた階層の再帰構造以外で再帰を活用しなければ解けない、JavaScriptじゃ無理な課題て何?
駄目な実例は出せる?
一応ブログや本で論評するから。
そもそも末尾再帰を使う必要もないのに、使うコードを書かなければいけないという思い込みがあるわけでしょ?
— ken (@ken80297274) December 18, 2021
あなたが考える末尾再帰を使わなければいけないような課題てなんですか?と質問している。
ディレクトリ構造など課題そのものが回帰は除く。それは階層は知れているので問題にならない。
思わないねメモリ消費が問題になるレベルの末尾再帰を使わないいけないような構造の課題って、たとえば何があるんですか?あなたは何に末尾再帰を利用してるんですか?と質問している。
— ken (@ken80297274) December 18, 2021
[1..] みたいなベクター値が解決できない
— ken (@ken80297274) December 18, 2021
言ってる意味がよくわからない。
もっと具体的にどうぞ。
だから、FactorialとかFibonacciとか漸化式の数列を求めるときに、再帰とかでやってるってこと?
— ken (@ken80297274) December 18, 2021
なんで?教科書にそういう例が乗ってたから?w
どんだけレベル低いんだよって話だよね笑
結局さ、末尾再帰ないと困るとかアホな主張してるやつらって、アホなコードしか書けないからなんじゃないの?ww
— ken (@ken80297274) December 18, 2021
いやまじで、自己参照の再帰のループでしかコード書けないとかおもってるんだ?
— ken (@ken80297274) December 18, 2021
どんだけレベルが低いんだよw
こちらの結論からいうと、
— ken (@ken80297274) December 18, 2021
javascript で関数型コードが書けない、とか断言してる連中はひとり残らず無知で、勉強不足だなとしか思っていないし、MLのやつにしても自身のその好きな言語でやれ、って言ってくるなんか自己中心的な連中ばっかで、いろいろ問題ありそうですね、なるほどなあ、て思う。
なんというか「混成だから」「堕落しちゃう」とか、属人的で、JavaScriptで関数型コードが書けない客観的な論証としては成立していない、というか、堕落した論調で、説得力ないな。
— ken (@ken80297274) December 18, 2021
大多数が否定なんて逃げないで自分の好みで否定してるてはっきり宣言すれば良いんじゃないかな。
別にletもconstも両方あるけどconstだけ使えばいいじゃない。
— ken (@ken80297274) December 18, 2021
純粋関数型言語じゃないと、関数型コードのメリットが享受できない、ってのは命題としたらFalseだと言ってる。
別にVSCodeという大規模開発の成果物でもなんでもTypeScriptで構築されてるけどね。
— ken (@ken80297274) December 18, 2021
君がHaskell好きとかマウンティングしてくるやつがML好きとか、結構どうでもいいけど、なんで他言語の関数型アプローチをそんなに否定したいの?
くだらない属人化までしてさ。そういう変な性格?
普通さ、大規模開発になると、コードスタイルも決まってて、あっちはOOPでこっちはFPなんてことは起こらない。
— ken (@ken80297274) December 18, 2021
ハイブリッドパラダイムではFPは無理なんて、狂った主張は、属人性によって正当化されるなんてことはないね。
別にJavaScriptに限らず、FPで階乗やらフィボナッチやら求めるのに、再帰ループ書かなければいけない、なんて縛りなんてないけどな。
— ken (@ken80297274) December 18, 2021
なんでそんなメモ化やら末尾再帰が必要になるようなパフォーマンスわるいコード書いて平気なの?
階乗の数列を求めるのに再帰なんて使ったら計算量が爆発して、メモ化でもしないとパフォーマンス落ちるでしょ。
— ken (@ken80297274) December 18, 2021
末尾再帰なんてもんは、そういうアホなコード書きたい人のために用意されてるんじゃないの?
別にやりたきゃやればいいけど、漸化式の数列求めるのに、再帰使わないとできないとか、低レベルの主張をしたのが君で、だから末尾再帰がない言語は、関数型アプローチで解決方法がないとかトンデモ主張してるのが君なんだけど。
— ken (@ken80297274) December 18, 2021
ツーか君、ループは全部再帰でやるのが関数型で純粋のHaskellはそれ一択とか思い込んでる?
— ken (@ken80297274) December 18, 2021
変な教科書読んで独学したの?
数学のFoldとかいう概念知らない?つかわない?
普通に考えても漸化式て、外側から多重に計算しながら、やる、みたいなもんは理論的には簡潔な定義ではあるが、計算するときは
— ken (@ken80297274) December 18, 2021
1x2=2
2x3=6
6x4=24
って手計算でもやるよねw
だれが再帰でメモ取りながら手計算するんだよ。
安い教科書の受け売りで自分で考えられないからそんなトンデモ君になるんだ。
計算機科学は数学がベースにあり、漸化式の数列を計算するのに末尾最適な再帰関数でしかできない、それ以外でどうやってやるのか?とか阿呆な質問してくるやつが、抜かすなよ。
— ken (@ken80297274) December 18, 2021
計算機学徒が聞いて呆れる。
ある学問がよりPrimitiveな学問がベースにある場合、たとえば関数型プログラミングはラムダ計算が基礎だが、そういうベース、基礎にある、ってことはそれぞれの存在の不要性を主張してるわけでもなんでもないよね。
— ken (@ken80297274) December 18, 2021
勉強不足の低レベルな自称計算機学徒が屁理屈ぶっこいて食い下がってネガキャンか?
僕が苛つくのは、曲がりなりにも「学徒」と自称するやつが、Foldで再帰構造をボトムアップに計算する、それは手計算でやるのと同じ方向の計算だし、もちろんメモ化も末尾最適化も両方必要ない。
— ken (@ken80297274) December 18, 2021
そんな基礎的なこともしらずに、末尾最適ないJSはFP無理だとかアホなデマ流して無自覚なこと。
ちょっとは恥じるってことはないわけ?
— ken (@ken80297274) December 18, 2021
学徒と自称するなら、
すみません、勉強不足でいいかげんなデマ流して他人様の著書に間違った誹謗中傷をしてしまいました。
勉強になりましたありがとうございます、すみません、じゃねーの?
-----
Haskell は勉強しても、飽和する感じがしないのよね。永遠に、理路整然としたわからないものが続くというか。
— SEAHAL (@seahalcom) December 17, 2021
まあたしかにそうだな。Haskell界隈の関数型の解説はかなり筋が悪い。永遠に、理路整然としてものが続くのは当たり前なんで、自分で理路整然としてものを書いたら、こういう馬鹿が読みもしないでネガキャンの挑戦してくるわけだ。
はなし聞いてた?
— ken (@ken80297274) December 18, 2021
Fold/Reduceつかえば、recursiveな計算できるって、Wikipediaのタイトル記事見せたのに?
大丈夫?
質問するのは自由だけど、与えた情報咀嚼できない人?
ちなみに見せた記事はこれ
https://t.co/o7HJmaMU0S
— ken (@ken80297274) December 18, 2021
In FP, fold (..) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the results of recursively processing its constituent parts, building up a return value.
In functional programming, fold (also termed reduce, accumulate, aggregate, compress, or inject) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the results of recursively processing its constituent parts, building up a return value. Typically, a fold is presented with a combining function, a top node of a data structure, and possibly some default values to be used under certain conditions. The fold then proceeds to combine elements of the data structure's hierarchy, using the function in a systematic way.
関数型プログラミングでは、fold(reduce, accumulate, aggregate, compress, injectとも呼ばれる)とは、再帰的データ構造を解析し、所定の結合操作によって、その構成要素を再帰的に処理した結果を再結合して戻り値を構築する高階関数群のことである。
通常、foldには、結合関数、データ構造のトップノード、および場合によっては特定の条件下で使用されるいくつかのデフォルト値が提示される。そして、foldは、その関数を体系的に用いて、データ構造の階層の要素を結合していく。
Fold/reduce「再帰的データ構造」を結合操作する高階関数、これは本書でもじっくりと書いたこと。
On lists[edit]
The folding of the list [1,2,3,4,5]
with the addition operator would result in 15, the sum of the elements of the list [1,2,3,4,5]
. To a rough approximation, one can think of this fold as replacing the commas in the list with the + operation, giving 1 + 2 + 3 + 4 + 5
.
In the example above, + is an associative operation, so the final result will be the same regardless of parenthesization, although the specific way in which it is calculated will be different. In the general case of non-associative binary functions, the order in which the elements are combined may influence the final result's value. On lists, there are two obvious ways to carry this out: either by combining the first element with the result of recursively combining the rest (called a right fold), or by combining the result of recursively combining all elements but the last one, with the last element (called a left fold). This corresponds to a binary operator being either right-associative or left-associative, in Haskell's or Prolog's terminology. With a right fold, the sum would be parenthesized as 1 + (2 + (3 + (4 + 5)))
, whereas with a left fold it would be parenthesized as (((1 + 2) + 3) + 4) + 5
.
In practice, it is convenient and natural to have an initial value which in the case of a right fold is used when one reaches the end of the list, and in the case of a left fold is what is initially combined with the first element of the list. In the example above, the value 0 (the additive identity) would be chosen as an initial value, giving 1 + (2 + (3 + (4 + (5 + 0))))
for the right fold, and ((((0 + 1) + 2) + 3) + 4) + 5
for the left fold. For multiplication, an initial choice of 0 wouldn't work: 0 * 1 * 2 * 3 * 4 * 5 = 0
. The identity element for multiplication is 1. This would give us the outcome 1 * 1 * 2 * 3 * 4 * 5 = 120 = 5!
.
まあこの辺のことは、Wikipediaのタイトル記事(別に数学的にWikipediaがおすすめ記事と言ってるわけではない、Wikipedia記事であってさえも、というニュアンスがある)でも、普通に記載されている。
には、
再帰呼出しの例[編集]
ここでは、階乗計算を再帰呼び出しにより実装する例を紹介する(自身の再帰呼び出しが、その計算における最後のステップになっているような末尾再帰は再帰呼び出しの特別なケースであることに注意)。
C言語での例:
という、コードが掲載されている。
実はこれは無名関数=ラムダ式であってもこのような再帰関数を定義することはできて、それがラムダ計算だけでも「繰り返し処理」ができるという重要な証明となっていて、チューリング完全だ、とか理論上は重要だ。
それは大変結構なことなのだが、理論上の重要性だけにとどめおかないで、これが階乗計算の関数型スタイルの作法だ、みたいに伝言ゲームをやらかしているアホな教科書や教師、そしてそれを鵜呑みにして疑わない、この記事で紹介した中級者みたいな2人あるいは3人のような人間がいる。
リアルのコードで階乗計算にトップダウン方向の再帰関数を書くようなプログラマーは「アホ」である。
それこそ末尾再帰のメモリ効率化の問題やら、なんども非効率に同じ計算が指数関数的増加するのでメモ化が必要になって、デメリットしかない。
課題そのものがディレクトリ構造のように再帰構造ならばまだ許容できるが、
本書で掲載したコードを引用すると、
と、普段普通に階乗の手計算でやるのと同じボトムアップでFoldするreduceを使えば良いことだ。そしてこれは本書の冒頭からずっと継承して説明しつづけているコードでもある。
本人の該当ツイートが消えているのが残念だが、それが上記のツイートであり、特に彼は「他にどういうやり方があるんですか?」みたいに聞いてきたので、その返答が、これである。
ツーか君、ループは全部再帰でやるのが関数型で純粋のHaskellはそれ一択とか思い込んでる?
— ken (@ken80297274) December 18, 2021
変な教科書読んで独学したの?
数学のFoldとかいう概念知らない?つかわない?
続きをかくと、
最初の最初に、どういう事例があるんだ?って質問したのが僕で、その事例として漸化式の数列計算を出してきたのが君で、それは末尾最適化のある再帰関数でしかメモリの問題は解決できないとか、トンデモ主張をして、僕が鼻で笑った、っていうのがこれまでの流れ。
— ken (@ken80297274) December 18, 2021
いいよ?最初に戻りたいのなら。やれ
「チューリング完全ならば、同じことができる」そのとおりだけど、聞いてて思ったけどFoldのrecursiveな用法の知識すらないやつが、大風呂敷広げてもなあ、と鼻で笑い続けてるよ。
— ken (@ken80297274) December 18, 2021
御託はいいから、さっさとやってみたら?
現状君ひとりが右往左往して恥さらしてるだけなんだから。
オーケーじゃないよ。
— ken (@ken80297274) December 18, 2021
最初の最初から末尾最適がないことによって解決不能な課題ってなんだ?と質問しているの。
で、一発目に出してきたのがRecursiveな数列で、Recursiveな数列はRecursiveなFoldで計算できる、と君が恥をかいた。だから頑張れよ?
パッとツイートも出来ないのか。
— ken (@ken80297274) December 18, 2021
えーっとどれくらい?
時間もかかるんなら、あらかじめそう言っといて。
漸化式の数式の計算は末尾最適化されてないと問題があるみたいなトンデモ主張はさっとだせるんだから、同じレベルで別のなんか勉強不足のまま勘違いして覚えてデマながして学徒として恥も知らないみたいな事例がすぐデてくるんじゃないのか。
— ken (@ken80297274) December 18, 2021
今から考えるってこと?
なんでPCが必要なの?
問題はコラッツ予想の再帰を Functional Programming in JavaScriptで書いた場合と、命令形言語よろしく while で書いた場合の比較ですよ。末尾再帰を使わないと、前者は後者よりも求められる数が制限されるはずです。
— SEAHAL (@seahalcom) December 18, 2021
だから繰り返しになるけど、命令型のループは、関数型のfold/reduceに置換されるのだし、ImmutableJSというライブラリ使ったら無限数列の遅延操作もできるので、そんな命令型で出来て関数型で出来ない問題など発生しない。
— ken (@ken80297274) December 18, 2021
まあチャレンジしてみたら?
FPinJSの堅牢さの証明になるメリットはあるから。
で、これどうなってるの?
— ken (@ken80297274) December 18, 2021
負けを認めろみたいに言ってきたわけだし、学徒自称するなら、すみません間違いでしたデマ流してしまいました。勉強になりました、ありがとうございます、すみません、じゃないの?
人の著作誹謗中傷してほったらかし?
諦めたんじゃなかったのか。1週間位?
— ken (@ken80297274) December 19, 2021
年内にカタはつけてね。
おい、岡部健に粘着されているんだが、どうしてくれるのだ!ただでさえ、関数型言語の人には変な連中が多いのに、どうして彼はこんなにまでキチガイじみた攻撃性を持って侮辱してくるのだろうか?それとも、俺がおかしいのか?気が狂ってしまいそうだ!
— SEAHAL (@seahalcom) December 18, 2021
だから、パソコンが手元にないから時間がかかるっていうだけだろ。そうカッカするなよ。
— SEAHAL (@seahalcom) December 18, 2021
とりあえず一旦UPする。
どうせ本書に追記しようとはおもうので、
ImuutableJSを使ったコードはどっかに残ってるはずだし、コピペできるかもしれない。
【+α+タイプコンストラクタ編】本書いたら数学愛好者の中級レベルのプログラマーからマウンティングを試みられた話
本書いたら数学愛好者の中級レベルのプログラマーからマウンティングを試みられた話
https://ken-okabe.hatenablog.com/entry/2021/12/12/102301
ken-okabe.hatenablog.comhttps://ken-okabe.hatenablog.com/entry/2021/12/12/130747
マウンティングを試みているが墓穴を掘り進んだ中級レベルの人が書いた素材はこれ
「関数型プログラミングが『銀の弾丸』であるという非常識な常識2022」の感想 - Qiita
まずはこれまでの総論というか、なんで中級レベルの彼がトンデモだと思っているのか、取り残した素材とあわせて論評。
本書で一貫しているのは、関数型プログラミングの力の源泉は数学そのものであり、プログラミングというのは、なるだけ簡素にその表記であれば事が足りる、ということです。
「なんで二項演算にこだわるのか?」というイチャモンに過ぎない雑音が多いですが、単に、モノイドでも
1+2+3
という二項演算子+があり、簡素に演算を表現できているが、少なくともJavaScriptでは他の本質的には二項演算として簡素に表現可能なものが、そのとおり表現できないので、この障壁を取り払おうとしているに過ぎません。
なんでJavaScriptなんだ?とか言ってる雑音集団はこういう中級者君のオレサマ今MLやってて気に言ってる最高、とか、その他何名か知ってるけど名前ひっぱってくるのは面倒くさいから容赦してやるけど、だいたい同類です。
基本的に、僕はJavaScriptTypeScript向けに関数型プログラミング入門を書きたいのだし、リーチできる初学者層が非常に多いのは書きごたえがあるわけです。
もうすぐRustにこの本を翻訳する予定ですが、とりあえずオレサマお気に入りのMLの啓蒙しろ、そのほうがよい
氏がそこまでJavaScriptにこだわる理由は私には分かりませんが、「アテにならない」TC39が支配するJavaScriptに無理やり二項演算子を定義するのではなくてもっと筋の良い言語の啓蒙に勤しむ方が活動として有意義だと私は考えます。
とか言ってくる分には、うっせーわ、人の本批判するにかこつけて、だまってろや?と口汚く罵るしかありません。一択でしょう。
MLなんぞの関数型本に巷の初学者には需要なんてほぼないでしょう。入門書書きたければてめーで頑張って書けばいいけど、ネガキャン乗じて「活動として有意義」みたいな趣味趣向のわけわからん政治的要求してくんなやド阿呆と口汚く罵る一択です。
まずこの辺から、この中級者に限らず文句垂れてる外野の属性っていうのはだいたい揃っていてヤバイ連中だな、と痛感しています。トンデモ臭もしますね。少なくともこういう連中は初学者の役になんて一切立ちません。関数型が難解であると思われてる元凶でもあります。
型は集合というnLabやらELMの作者やら権威を少なくとも彼らが黙り込むレベルの権威付をしてやると、行き場を失って右往左往しますが、今Twitterみたら、
誰か「型って何?集合との違いは?調べてみました!」みたいな記事を書いてくれ
— mod_poppo (@mod_poppo) December 12, 2021
集合を集めたものは再び集合になるけど、型を集めても型にはならない、みたいな説明はアリか?
— mod_poppo (@mod_poppo) December 12, 2021
型のユニバースがあった
— mod_poppo (@mod_poppo) December 12, 2021
もう必死に悪あがきしているようです。
仲間ももうnLabやElm作者があそこまではっきりと明言してるんだから、、と権威にはからっきし弱い、自分の頭で考えることが苦手な連中ですから、もうろくな助け舟も出ません。無理筋だとうすうす気づいてるんでしょう。
見るに見かねた人に
型です。画像はネットから引用 pic.twitter.com/Lz67K2llB9
— あなもぐら (@moggwai1) December 12, 2021
とおちょくられる始末。末期ですな。
なんで、同一視すれば楽に俯瞰できる、とこれだけはっきりと提示されているものに、
誰か「型って何?集合との違いは?調べてみました!」みたいな記事を書いてくれ
とか誰かに必死に頼まないといけないような差異を見つけ出すことに必死なんでしょうか?
この辺がこいつら中級者集団の浅はかなところです。
少なくとも彼らの知見から何かを学ぼうとしてる人は無駄だと思ったほうが良いでしょう。
僕は、同一視する、という概念を重視していて、それはより高い視点、メタな視点を獲得できるとおもっていて、初学者のひとらに必ず役立つ、楽に習得しやすいと、入門書を書く立場として大事なことだと思っています。
僕はそういう視点をもって、二項演算子の導入のメリットやら、型は集合である、と権威付もしながら紹介するわけですが、こいつら中級者はネガキャンはって妨害してきます。最終的には上のTweetでも明白でも自分のメンツだけです。
ネガキャンマウントとろうとしたがボコボコに返り討ちにされちゃって恥かいてメンツ保つことだけに必死です。
「型=集合」か?
「型」が何かというのは(私にとっては)難しい問題です。
初学者向けには「型は集合のようなものだよ」という説明で良いかもしれません。
初学者向けには、とか中級者ぶっていますが、実際こんなもん中級者君が何がわかってる、ってわけでもありません。
僕自身のことでいうと、いろいろ見ていて、ああ型は集合のことか、という直感というか同一性が自分でわかったので、そういう風に解説したいがどうせ中級者どもがわかった風に誹謗中傷してくるだろうな、と予測したので、軽くぐぐったら、nLabやらElm著者の記事やらがヒットしたのでそれをありがたく、そのとおりだよなー的に引用させてもらっているわけです。
と直接的に言及されている、ごく一部分だけを引用翻訳していますが、リンク先の全文を見れば明らかですが、これは中級者君が主張するような「初学者向け」のコンテンツではありません。
全文その他にブログリンクもあり結構詳細に高いレベルで議論されています。
彼ら中級者は自分の頭で考えることが苦手だから今でもこういう状態だし、本は読むんでしょうが、実際出版されてる本でも、その著者の視点のスコープが限られていたらそこでオシマイです。そして実際こいつら中級者が、こんだけ大慌てしてるところをみると、本に書かれてなかったんでしょう。もちろん自分で気づくってこともないし、こうやって僕が情報をnLabの引用つきで書いても、読まずにどこですか?とかマヌケなことを言ってくるし、それを読んでもまだ納得もできない。
こういう連中は学問をするにあたって本当に適正がないです。頭がよろしくない。センスがない。
そして僕のアウトプットをトンデモレッテル貼りたがって、さらに評判を下げようと必死な連中っていうのは、だいたいこういう中級者の連中です。
とりまきは中級者以下なんで、そーだそーだ岡部のいうことは変だーと同調するだけで、なんかわけのわからん風評被害が醸成されていきます。ろくでもないですね、ほんとうに。
しかし、私が思うに、型は集合よりも幾分抽象化されています。ここでの抽象化というのは、できる操作が限られているという意味です。例えば、
あなたがおもう「幾分」ってどれくらい?って話になりますが、事例を出すそうなので、その「幾分」ぶりを精査してみよう。
- 集合は自由に和集合 (union) や共通部分(交差, intersection)を取れますが、型について和や交差を取れるかどうかは型システムに依存します。
- 例えば、今のTypeScriptにはunion typeやinteresction typeがありますが、リリース当初のTypeScriptにはどちらもありませんでした(union typeはTypeScript 1.4から、intersection typeは1.6からです)。
- 別の例で言うと、Haskellにはそもそも部分型関係がないためunionもintersectionもありません。
なるほど。「型システムに依存する」と、その実例としてTypeScriptの実装の歴史を語っている。Haskellの実装の不備のことを不満に思っている。
XXかとww(自粛
なんで、数学構造、数学の理論が各プログラミング言語の型システムという実装に依存する、とか言ってるのでしょうか?
逆なら真であり、実装が数学理論に依存するのです。
数学理論が実装に依存する、なんて馬鹿げた話なんてありえません。
型システムが高度化していく歴史の下敷きには、その先に型理論があるわけで、それは究極的には集合論のことだ。
「抽象化」のはなしをしているのに、なんで実装の違いの話をしているんだろう。
「できる操作が限られている」のが実装の至らなさであるのならば、それは「抽象化」の問題とは言わない。抽象概念を実装するという「具体化」の問題なんだ。
>集合は自由に和集合 (union) や共通部分(交差, intersection)を取れますが、型について和や交差を取れるかどうかは型システムに依存します。
集合論という抽象的な概念、数学があり、それをどうやって具体的な実装をしてコードに表現できるかだろう?
これで、なんで集合は型ではない、という論証になると思っているのか。そうとう頭が(自粛)ですね。なんで僕の仕事を批判できるとか思ってるんだろうか?よくわかりません。
- 集合に対しては冪集合 (power set) という構成がありますが、型に対する類似物はあまり聞きません。ある型の部分型全てを集めた型…となるのでしょうか?
- 【追記】「
A -> Bool
がそうではないか」という意見を頂きました。特性関数と部分型を同一視すればそうなりそうですが、筆者としては「部分型を集めた」感がないなあ、と思ったのでこの記事の当初の版では言及しませんでした。
- 【追記】「
うん、結局、集合のほうがより明確に抽象概念化されているんだ。これは本書ですでにまとめていて、たとえば
この表ひとつとっても、集合論のほうは細分化されているけど、型は型としてしかないのはわかります。他の分野では区別があるものでも型は区別されてない。
という点で型と集合は違うものだと考えます。
?どういう点で?
君ひとりが混乱してます、って言ってるだけ、あるいは、型のほうは集合論みたいに十分整理されていない、あるいは整理しにくい現状だ、あるいは、TypeScriptで十分実装されてない、って言ってるだけだろう?
それをもって「型と集合は違うものだ」という論証としてなんて成立していない。
論証成立もしてないのに、してる、とおもえるならばトンデモ重症レベルだと思う。
繰り返しますが、私は初学者向けに「型は集合のようなものだよ」と説明することを否定はしません。
はっきり言うけど、君は「初学者向けに」みたいに豪語できるような知見がある立場になんていないよ。
しかし、Twitterで「こいつ @mod_poppo は、型が集合である事実すらしあず」と仰っているからにはKen Okabe氏は本気で「型=集合」と考えているようです
そうだね、そう考えてるよ。何か問題でも?
FunctorとMonadは二項演算か?
これについては、もう十分論評したとおもう。
Haskellのコードでゴネてたけど、Haskellのモナドで全部二項演算子だし。
ゴネた挙句に、関数がファーストクラスになる実装によってモナドの二項演算になっている、とか、また、実装を数学構造の定義や差異の要因にしようとしていた。
TypeScriptの実装のバージョン違いが、型と集合の数学構造の抽象度と関係あるとか、この形式のトンデモ理論を振り回すのが好きな中級者なんだろうと思う。
はなしにならん。
「タイプコンストラクタ」の用法
詳しい人向けの解説:氏の文書では「タイプコンストラクタ」を「(モナド等の)単位射」の意味で使っています。これは間違いです。
デマ。
詳しい人向けだろうがそうでなかろうが悪質なデマ。そんな事実はない。
本書の範囲には含めなかったが、タイプコンストラクタは
というように、あらゆる階層に存在する。
こういう高階のタイプコンストラクタは、高カインド型とも言われている。
本書でもまる一章かけて解説した高階関数が
f > g あるいはg(f) というように関数をパラメータとする関数である、という同じ意味での高階(HihgerOrder)。
関数は値のコンストラクタとすると
型コンストラクタはその型レベルのはなし。
- 1階のタイプコンストラクタ
では、単に
F<A>
というようになり、本文を引用すると
となるから、それで良い。
これはモナドの単位射に他なりません。
まあそのとおりだね。モナドはそうなるように定義されてるんだから。
用語に関してついでに言うと、Ken Okabe氏の文書ではMonadを返す関数のことを「Monad関数」と呼んでいるようです。Haskellで言えば
a -> m b
みたいなやつです。圏論の文脈的には、これにはKleisli射という名前がついています。
そのとおりだね。
そして中級君は、あんまり自分の頭で考えるのが苦手だから、用語は本の丸写しみたいな思考しかしていないのがわかるけど、君はクライスリ圏の概念の意味とかちゃんとわかって発言している?自分の言葉でちゃんと説明できるのかい?
どうせできないんだろう?せいぜい本の引用だけだろう?
クライスリ圏っていうのは結構、特異な発明であって、基本は集合の圏だ。発明者たちの特殊な思考フレームワークを特別に信奉したいという事情でもない限り、関数型プログラミングは普通に集合・関数の圏(Category of sets)で関数合成からはじまって必要な部品は揃うんだから。
自分で意味も理解してないような用語を振り回して、
圏論の文脈的には、これにはKleisli射という名前がついています。
とか書くことに一体なんの意味があるんだい?
まともに論じる能力もないのに中級者として背伸びして難しそうな用語でハッタリ効かせようと思っているだけなんだろう?
Ken Okabe氏の22.9には
基本的に、プログラミングを含む工学では、なるだけ既存の数学的な概念と用語を踏襲すべきであって、同じ意味の造語を無闇に増やすことはあまり意味がないどころか、混乱をもたらすだけだと考えます。
という記述があります。私としてはこの記述に非常に同意します。Ken Okabe氏自身がこれを徹底していればもっと良かったと思います。
そうだね。でも中級者君は口では「非常に同意します」とかいうだけで、使えもしない、つかってもいないクライスリ圏の射という概念を、集合の圏で十分なところに積み増してるよね。
実行できてないじゃない。
僕は徹底しているからそんな用語は無用に使わないようになりました。初学者に教えることが目的で、君のように権利を借りて背伸びしてハッタリ効かせる、てのはむしろ目的の障害になるんですね。
だいたい、Haskellのモナド関数でも、普段いちいち射(Morphism)だ、みたいに取り扱っているのかい?クライスリの射だ!とか普段やってる?やってないだろ?
それは「関数」と呼ぶんだよ。巷をみるとたとえばStackoverflowでもMonadFunctionでこの概念はやりとりされている。クライスリの射という用語自体のQAはあるんだろうが、モナドの関数の呼称としてやってるのなんて’見たこともない。自分でも普段そんなの使ってないくせに、なんで初学者に教えるようなフェイズで、突然えらそうに大上段から、
Haskellで言えば
a -> m b
みたいなやつです。圏論の文脈的には、これにはKleisli射という名前がついています。
みたいなことを言う必要がある?学習者ビビらせて偉そうにしようとしてる?
あと、僕に対してマウンティング取りたいだだけだろう?閲覧者にむけて良いカッコつけてメンツ保ちたいだけだろう?
全部キミの都合じゃないw
最後にうまいこと言ったと思ってるんだろうけど、自分でできてないことを賛同する、僕ができてることを、彼がもっと徹底できていればもっと良かった、とか、うまいこと言ったつもりなんだろうけど、正直、鼻で笑っているよ。
いかに中級者君のような態度が初学者の学習の妨げになっているのか自覚してほしいね。そんで僕の仕事に茶々入れてくんな、迷惑だし有害だし、君にそんな知見なんてないんだからさ。
以上かな!
【追記への反論編】本書いたら数学愛好者の中級レベルのプログラマーからマウンティングを試みられた話
関数型プログラミングが『銀の弾丸』であるという非常識な常識2022
を書きました。
本書いたら数学愛好者の中級レベルのプログラマーからマウンティングを試みられた話
の続編です。
Qiitaのトンデモな記事に反論していきます。
結局の所、自分で勝手に火がついて、よし岡部の本をネガキャンするぞネガキャンするぞ、とやっておいて、結構不条理でトンデモなデマを流されているわけです。
その上で、「自分には時間が無制限にあるわけではない」というような、身勝手な被害者ヅラをした挙句、ちょっとこちらがちゃんとした反論をしたら
氏のはてなブログによる反論を受けて記載したものです、とくる。
こちらは時間も手間もかけて書いた著作を愉快犯の誹謗中傷みたいにやられて、徹底的にやると思ってるんで、時間が、、、とか言うなら足りなくなるんじゃない?
すでに書いたように、僕は君の事は中級者というよりむしろ理不尽で意味不明な攻撃してくるトンデモだと思っているし、そこを放置したら、またややこしいことになるので、徹底的に詰めます。
【追記】もちろんC++やRustでも演算子オーバーロードはできますが、C++やRustを含む多くの言語では演算子としてあらかじめ決まった種類のものしか使えません。「パイプライン演算子がないから
|>
を演算子として使おう」ということはできないのです。一方で、上の段落で挙げたML系言語では(言語が許す種類の文字からなる)任意の記号列を演算子として定義することができます。元の文書の主題からすると任意の記号列を演算子として使える方が好ましいかと考えたのでStandard ML, OCaml, Haskellを挙げました。
「あらかじめ決まった種類のものしか使えません」
どーでもいいですね、そんなことは。
それに、|>というシンボル自体になにか数学的な意味が関与しているわけでもなんでもありません。で、またML最高の話ですか?
自分のより好みをもって、人の著作を批判とかしなさんなよ?って話です。
僕の本の内容の正しさとあなたの好みとか、「演算子のシンボルが限られてること」なんて関係ないでしょ。
【追記】このセクションは特に私の「感想」色が強く、人によって意見が異なることは自然なことだと思います。なので、あまりとやかく言い争う気はありません。
「感想」というか、あたかもこちらの技術的アプローチに問題がある、というようなニュアンスで中級者君は好評したんだね。誰でもそう読み取れる。
JavaScriptにおいて二項演算子を導入するメリットは大きく、それは本書の表記に大きく関与していて、文字数が多くなっただの行儀が悪いだの、ご丁寧にサンプルコードまでつけて、ネガキャンやった。
それで「感想」で人によって意見が異なる、とか、しれっと言う。まあ論評は自由だけど、理不尽なネガキャンはバズるので、こちらとしては看過しないし、言い争いは当然する。
【追記】initialValueを省略した場合に「加法の場合は0となる」「乗法の場合は1となる」という説明は間違っています。だって空配列に
.reduce(add)
を適用しても 0 は返ってこないでしょう?氏の反論記事では空配列のことを無視しており、私の文章の書き方が悪かったかなあと反省しております。
間違ってはいない。サンプルコードにおいては実際にそういう挙動になる、と整合的に理解できて、それは二項演算のFoldの理解に大変重要です。
空配列、空の値、Noneその他は、まるで別の問題で、各言語のFold/reduceの実装と一緒くたに論じるような話ではありません。
空の値のはなしはTypeの話であって、TypeScriptで空配列をどう扱うかにも関係してきます。
僕が中級者君がトンデモだと思うのは、数学の代数構造の話と、言語に実装されたreduceの仕様の挙動を一緒くたにして平気だということです。文章の書き方以前の問題だと思う。
【追記】私は「型≠集合」という立場なので関数型プログラミングのモナドが集合圏上のモナドと同じものだとは思いません。
あなたは勝手にすれば良いが、こちらの立場を否定するな。
それはnLabやELM作者の主張と同一であり、それは引用して明示している。
最初読んでもなかったよね?
この役に立つ視点は、初学者にとっては非常に有用。
そしてnLab原文リンクを開いてみればわかるとおり、これはそもそも初学者相手に解説されているわけでもありません。
そして中級者君の勝手な趣味的な自己満足立場をもしこちらの立場が間違っていると印象操作する形で押し付けるならば、それは学習者全てにとって有害だ。
自分の考えを表明するのは自由だが、こちらがnLabその他の文献をひっぱって明確にしてるもんを否定する形で発言しないでほしい、迷惑なんで。
こうやって反論することでようやく彼らがフェアな判断ができるようになる。
なんで、nLabの元文献とか引用しない?
Qiita記事の閲覧者に読まれたら自分の主張が揺るぐ、賢明な読者ならばどっちの立場が正しく有用なのか、判断されて自分のメンツがつぶれることを恐れているからだろう?
君のメンツでこちらの著述が否定されることが本当に腹立たしい。
行儀の悪いやりかたしか君はできないんだね。
【追記】私は「型≠集合」という立場なので関数型プログラミングのモナドが集合圏上のモナドと同じものだとは思いません。
それに、二項演算のはなしだよね。
>>= という二項演算子をもって、
二項演算の等式としてモナド則(Monadlaws)でもなんでも書かれているんだけど、
中級者君のトンデモ主張っていうのは、この眼の前の現実と合致しない。
中級者君の勝手な立場は黙ってくれたらそれで有害ではなくなるけども、
関数型プログラミングであつかう集合の圏のモナドは、
このように間違いなく二項演算子、として掲示されている現実がある。
現実のコードと、君の勝手な主張が不一致ならば、
間違っているのは中級者君であるのは間違いない。
いくらゴネようとも、もう無理筋だって閲覧者にバレていることだろう。
今回は以上です。