Topics

・関数型プログラミングとオブジェクト指向のパラダイムとしての対立 国内の【自称】関数型コミュニティと海外の論調の違い

ガラパゴス・ネットスラング=「関数型ポエム」という呪詛、先入観的読書と、フェアなレビューの登場

Qiitaの騒動から派生して、東北大学の住井 英二郎@esumii氏、らくだの卯之助@camloeba氏その他が、犯罪者集団に合流して2ちゃんねるでの誹謗中傷チームの「8賢者」「ウィザード組」とかアホなことをやってる件について

JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン

2016年のnode、ES6、React、Babel、Atomエディタ界隈の方向性

Dockerじゃないsystemd-nspawn+machinectlが非常に良い

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その1】「計算機科学のほんとうの基礎」を理解していない。IQ145のJKと同じ事を語るMITの権威とSICPという聖典の権威を借りてマインドコントロールを解いてみよう

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その2】関数型プログラミングのイミュータブルな世界観とイミュータブルな実世界を完全に統合

10年先を行く斬新な関数型(FRP)データベースについて説明する 99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その3】

[React (.js Facebook)解説 関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間 サポート記事【静的HTML編】React 解説【動的HTML-FRP編】

量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説01量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説02

『関数型プログラミングに目覚めた!』のレビュー(Day-1)について

LISPデータ構造の問題点の指摘と抜本的解法としての新プログラミング言語の策定/純粋関数型言語「SPINOZA」

著書『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』 [Day1]たち読み記事 無料公開中

『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』を大変多くの方々にお買い求めいただき、感謝します。本書の全目次を公開し、質問を受け付けます。

2016年5月17日火曜日

本来のFRPを理解せず中傷を重ねる連中への再度宿題

TimeEngine お絵かきアプリ(関数型リアクティブプログラミング/FRPのトイプログラム)について、

はてラボはてな匿名ダイアリーで、またいろいろ思い込みの激しい勘違いした批判が行われているので引用しながら、ひとつひとつ反論していきます。

ちなみに、今回も東北大の住井 英二郎@esumii、
自分が読み解けないFRPライブラリの実装について「スパゲッティ・コード」と書きなぐるだけの
らくだの卯之助@camloebaも居るようです。オモテで名前出してやったら?卑怯者が、というところです。


http://anond.hatelabo.jp/20160517094425

kenokabe氏のコードでもマウスが動くたびに同じ__drawFrom.tへの破壊的代入が行われるんですがそれは

..

http://anond.hatelabo.jp/20160517022608

それをユーザから見て命令型変数への破壊的代入ではなく
参照透明な関数型インターフェースで実現するのが
いわゆるモナドや(誰かの独自解釈ではない本来の)FRP。
http://elm-lang.org/examples/time

view : Model -> Html Msg
view model =
  let
    angle =
      turns (Time.inMinutes model)

    handX =
      toString (50 + 40 * cos angle)

    handY =
      toString (50 + 40 * sin angle)
  in
    svg [ viewBox "0 0 100 100", width "300px" ]
      [ circle [ cx "50", cy "50", r "45", fill "#0B79CE" ] []
      , line [ x1 "50", y1 "50", x2 handX, y2 handY, stroke "#023963" ] []
      ]

HaskellのライブラリもElmのような言語も、サンプルもJavaScript実装も
ググればWikipediaで出てくるレベル。
https://en.wikipedia.org/wiki/Functional_reactive_programming#Implementations


まず、これなんですが、

いわゆるモナドや(誰かの独自解釈ではない本来の)FRP。

「(誰かの独自解釈)」というのは、おそらくこの投稿をした自分自身のことを自嘲的に言ってるのだと判断するしかないですが、
(誰かの独自解釈ではない本来の)FRP、というのは、ここで最前から書いておるように、再掲すると、


念の為ですが、TimeEngineのプロジェクトgithub.io ページ
http://timeengine.github.io/
にも書いていますが、1997年の論文で、http://dl.acm.org/citation.cfm?id=258973

Fran (Functional Reactive Animation) is a collection of data types and functions for composing richly interactive, multimedia animations. The key ideas in Fran are its notions of behaviors and events. Behaviors are time-varying, reactive values, while events are sets of arbitrarily complex conditions,

Fran (Functional Reactive Animation) として、初めてFRPを明示的にプログラミングパラダイムとして導入したことで知られているConal Elliottは、 
http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming
において、こう宣言しています。

I do resonate with Laurence G’s simple description that FRP is about - “datatypes that represent a value ‘over time’ ” -. Conventional imperative programming captures these dynamic values only indirectly, through state and mutations. The complete history (past, present, future) has no first class representation. Moreover, only discretely evolving values can be (indirectly) captured, since the imperative paradigm is temporally discrete. In contrast, FRP captures these evolving values directly and has no difficulty with continuously evolving values.
Dynamic/evolving values (i.e., values “over time”) are first class values in themselves. You can define them and combine them, pass them into & out of functions. I called these things “behaviors”.

面倒なんで全部訳しませんが、ポイントは、

  • FRP is about - “datatypes that represent a value ‘over time’ “
  • Dynamic/evolving values (i.e., values “over time”) are first class values in themselves.

FRPは「時間軸上の値を表現したデータタイプ」についてのパラダイムである、
動的に時間発展する値(つまり時間軸上の値)はファーストクラスである、
ということです。


これで間違いありません。
私の以前から解釈しているFRPの特性とは、Conal Elliottが1997年に実装して発表し、
その後も各所で解説していて、
http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming
においても広くその見解の妥当性が認められているFRPの特性、概念と一致しています。

TimeEngineは、この
FRPは「時間軸上の値を表現したデータタイプ」についてのパラダイムである、
動的に時間発展する値(つまり時間軸上の値)はファーストクラスである、
ということを簡潔に実装したFRPライブラリです。

ちなみに、

HaskellのライブラリもElmのような言語も、サンプルもJavaScript実装も
ググればWikipediaで出てくるレベル。
https://en.wikipedia.org/wiki/Functional_reactive_programming#Implementations

という「レベル」なるものについてですが、この多くは、
FRPは「時間軸上の値を表現したデータタイプ」についてのパラダイムである、
動的に時間発展する値(つまり時間軸上の値)はファーストクラスである、
という「本来のFRPのパラダイム」が中心でなかったり、本末転倒なものが多く紛れ込んでおり、
「ググればWikipediaで出てくるレベル」というのが惨憺たる状況である多くの例のひとつであるといえます。

たとえば、この人物がいう(おそらく匿名で繰り返し言ってる)「Elmのような言語」ですが、
海外の掲示板では以前から

Neither Rx nor Elm are FRP. If you want FRP, look at Conal Elliott’s work.

「RxもElmもFRPではない。FRPがほしけりゃ、Conal Elliottの仕事を見ろ」
などと「本来のFRP」とのパラダイムのズレが指摘されていました。
パラダイムっていうものは、かようにWikipediaのリストごときで十把一絡げに簡単に論じれるようなものではなく、
関数型、オブジェクト指向しかり、たいがい論争に発展するようなものであり、
いろいろ意見を言うのは結構だが、そんなググってWikipediaのリストで「レベル」がどうのこうの断じるのは、この人物のレベルの底が知れるというものです。まあ、例の東北大の住井にしろ、あいかわらずいつもの匿名による発信なんで、文責も負わない、恥もかき捨てで結構なことですよね(笑

次に、

命令型変数への破壊的代入

とかいう、まあ、上記で示した本来のFRPの「意味」ってのを理解してないので、こういうことを平気で言えるんでしょうが、

TimeEngineによる、たとえば、

const __a = __();

として、定義されたものは、上記のとおり、
「動的に時間発展する値(つまり時間軸上の値)はファーストクラス」
であり、その集合のうちの現在時間を指し示すものが、
__a.tです。

JavaScriptのDateで考えれば、

Date.now()
であり、「現在時間」というのは、本来的に「それ以外のシンボル」では表現できません。

__a というのは、
「動的に時間発展する値(つまり時間軸上の値)はファーストクラス」
という集合値であり、名実ともに、Constantでイミュータブルな値です。
そのうちの「現在時間」というのは、「読み出した時点」で一意に自明的に決定されるわけで、
__a.tというのは、

命令型変数

でもなければ、「破壊的代入」するものでもありません。

たとえば、それこそ東北大の住井らしき人物がまた匿名で、

http://anond.hatelabo.jp/20160516112619

kenokabeさんの心の中ではそうなのかもしれませんが、ライブラリのユーザから客観的に見れば(分析哲学ではなく関数型言語の意味で)参照不透明なので、関数型プログラミングのメリットは享受できない、命令型の破壊的代入と等価ですね。

であるとか、

http://anond.hatelabo.jp/20160516192742

実際、timeengine.js を読み込んだ状態で、以下のようになります。

> const __x = __();
undefined
> __x.t = 1;
1
> __x.t = __x.t + 1;
2
> __x.t;
2

これは岡部健氏が著書で「論理破綻」と批判していた、命令型言語の破壊的代入そのものです。
なお私を他の誰かと決めつけるのは、その方たちにご迷惑ですのでおやめください。
……と言っても聞き入れていただけるとは思えないので、私ももうこれ以上の書き込みはやめます。
できるだけ丁寧に技術的な誤りだけを指摘したつもりですが、やはり誹謗中傷しか返ってこないようで残念です。

http://anond.hatelabo.jp/20160517094425

などと書いているのですが、いま説明しているように、

Date.now = Date.now + 1

というステートメントが、概念的な意味を成さないように、
=の両辺が等しいという、関数型プログラミングのパラダイムにおいては、

__x.t = __x.t + 1;

というFRPライブラリの使用は概念的な意味を成しません。
なんでこういうことをするのか?というと、なんか悪意があるか、
それとも、FRPが「時間軸上の値を表現したデータタイプ」についてのパラダイムである、
ということを全く理解していないから、こういう文句のつけかた、それこそ誹謗中傷をして平気なのでしょう。

あえてこの住井らしき人物がわざとやらかした「破壊的代入」という命令型パラダイムにおいて、考えてみると、この人物の意図によると、
「右辺の現在値」を「左辺の現在値」に代入するという命令型の時系列的意図しかありえないでしょうから、

右辺の現在値に1を加えて、改めて、左辺の現在地とする

ということです、つまり、左辺、右辺の現在時間が異なる、FRPライブラリにおいては、
.tによって表現される時刻による「時間軸上の値」は異なって当然であるということになります。

よって、

__x.t = __x.t + 1;

というのは、
右辺を評価した現在時間における
__x上のある値に1を加えたものを
次の瞬間以降の
__x上の値として更新する、という意味合いになります。

もちろん、これは、=の左右で値が異なるという命令型ステップの解釈であり、
そういう命令形パラダイムを大前提とした記法においては、TimeEngineの振る舞いはこう解釈される、
ということにすぎませんし、そのような記法を禁じるようなSanityCheckを実装しているわけではありません、
ご自由にどうぞ、といったところでしょうか。

また、

次に、

http://anond.hatelabo.jp/20160516113354

関数型って時間はパラメータで与えて結果を得るんじゃないの

刻々と変化する「現在時間」を抽象化したインデックス

を変数で持ってたら、命令型じゃないの

などという意味不明な書き込みもあります。

「お絵かきアプリ」みたいな
「現在時間におけるマウス座標」を保持するときには、

Date.now()
であり、「現在時間」というのは、本来的に「それ以外のシンボル」では表現できません。

と書いたとおり、
「>>刻々と変化する「現在時間」を抽象化したインデックス」
つまり、nowやらt以外では、原理的に不可能です。

さーて、この勘違いした連中がいったいどういう魔法を使って
「現在時間における状態」について
「関数型って時間はパラメータで与えて結果を得る」のか是非見てみたいものです。
100%無理でしょうが(苦笑

「関数型って時間はパラメータで与えて結果を得る」とか書いてるってことは、
もはや、限定された「状態渡し」ではない、「この連中なりの独自解釈におけるFFP」のお話をしているつもりなのでしょうから、
FRPをつかって、「関数型って時間はパラメータで与えて結果を得る」という設計で、
お絵かきアプリを実装してみせてください。これが当方からのこの連中への課題ということになります。

さて、この件について、「非常に悪質な誤魔化し」が現在進行中であることも当然抑えておかなければなりません。それがすなわち、冒頭に示したコードです。

それをユーザから見て命令型変数への破壊的代入ではなく
参照透明な関数型インターフェースで実現するのが
いわゆるモナドや(誰かの独自解釈ではない本来の)FRP。
http://elm-lang.org/examples/time

view : Model -> Html Msg
view model =
  let
    angle =
      turns (Time.inMinutes model)

    handX =
      toString (50 + 40 * cos angle)

    handY =
      toString (50 + 40 * sin angle)
  in
    svg [ viewBox "0 0 100 100", width "300px" ]
      [ circle [ cx "50", cy "50", r "45", fill "#0B79CE" ] []
      , line [ x1 "50", y1 "50", x2 handX, y2 handY, stroke "#023963" ] []
      ]

これは、アナログ時計のコードなんですが、
アナログ時計のコードって、「現在時間」を表現していますが、
現在の状態について、「時間はパラメータで与えて結果を得る」コードでもなんでもありません。

この時間の離散値を得た上で、FRPに流し込むというのは、
TimeEngineで、前からさんざんやっていて、それはだから、物理の斜方投射のDemoでもっと高度な形でやっているわけです。

http://timeengine.github.io/

Demo #3ですね。

const t = __
      .intervalSeq(Immutable.Range(), 10)
      .__((count) => (count * 10 / 1000));
    const x = __([t]).__(([t]) => V0 * Math.cos(THETA) * t);
    const y = __([t]).__(([t]) => V0 * Math.sin(THETA) * t - 1 / 2 * G * Math.pow(t, 2));

というわけで、Immutable.jsの無限ストリームを10マイクロセカンド解像度で、時間軸にマップして
const t を得ています。

このなんか嬉しそうに貼り付けてきたアナログ時計っていうのは、ようするにそれの劣化版でしょ?
それでですね。こういう時刻の離散値ストリームを本来のFRP値として、このように、

const tとして表現することなんて普通にできるわけですが、
このtをもって「現在時間値」を表現することは「不可能」です。
だって、tが表すのは、「動的に時間発展する値(つまり時間軸上の値)」でしかないわけで、
「現在値」というのは、それ以外のシンボルでは表しようがない、
なにかカウントされたインデックスで表せるわけがないわけで、それを抽象化したものを.tとし、
t.tとするしか方法はありません。

TimeEngineは当然私が自分自身で実装したので仕掛けは熟知していますが、
この、

const t = __
      .intervalSeq(Immutable.Range(), 10)
      .__((count) => (count * 10 / 1000));

というのは、根本的には、SetIntervalもしくはSetTimeoutのラッパーで、
タイマーのイベントドリブンの周期をImmutable.jsの無限ストリームで表現しています。

angle =
      turns (Time.inMinutes model)

もこれは、根本的には、タイマーのイベントドリブンです。

タイマーのイベントドリブンでやってるのと、
マウスのイベントドリブンでやってるのは同じだし、

システム時刻t=0,1,2,…に適用して状態f(0),f(1),f(2),…を得る

なんて動作はこのアナログ時計のコードはやっていません。

実際に、私は「お絵かきアプリ」のトイコードを書くときに、
const t なんてものをインデックスとして取得することなどしていません。
それは単に、根源的にはタイマーイベントであり、
マウスのアプリは、マウスのイベントでアプリは挙動するからです。
アナログ時計のアプリが、タイマーのイベントを取るのは当たり前で、
それは、

システム時刻t=0,1,2,…に適用して状態f(0),f(1),f(2),…を得る

という「FRPの根本原理(笑)」だから、そうなってる、わけもありません。

現在の状態は、システム時刻のインデックスでやるのが、関数型で、FRP、とか、まあ大嘘で、
この連中が無知と勘違いでデマや嘘を垂れ流している様子にはいい加減辟易しています。

http://anond.hatelabo.jp/20160517023637

命令型プログラムをFRPとか言ってる人が決定的に理解していない点は、
ライブラリユーザは現在時刻から状態への写像fを
参照透明な関数なりストリームなりで記述して、
それを処理系が実際のシステム時刻t=0,1,2,…に適用して
状態f(0),f(1),f(2),…を得る、という本来のFRPの基本原理だと思う。
まさに実装は命令的だけど(誰かさんもそこは正しい)、
ライブラリユーザは参照透明な関数型の記述が可能。

うんだから、この人物が言う「本来のFRPの基本原理」というのは完全に間違っているし、
書き換えてあげると、
処理系の実際のシステム時刻t=0,1,2,…を
- FRP is about - “datatypes that represent a value ‘over time’ ”
- Dynamic/evolving values (i.e., values “over time”) are first class values in themselves.

FRPは「時間軸上の値を表現したデータタイプ」についてのパラダイムである、
動的に時間発展する値(つまり時間軸上の値)はファーストクラスである、

という時間軸上にマップして、

const t = __
      .intervalSeq(Immutable.Range(), 10)
      .__((count) => (count * 10 / 1000));

別の状態に再度マップする、

   const x = __([t]).__(([t]) => V0 * Math.cos(THETA) * t);
    const y = __([t]).__(([t]) => V0 * Math.sin(THETA) * t - 1 / 2 * G * Math.pow(t, 2));

ことくらいは、こっちはとっくの昔にやってみせているわけ。いいかな?

そうじゃなくて、ここでの問題は、再三いいますが、

http://anond.hatelabo.jp/20160516113354

関数型って時間はパラメータで与えて結果を得るんじゃないの

刻々と変化する「現在時間」を抽象化したインデックス

を変数で持ってたら、命令型じゃないの

だとか、

http://anond.hatelabo.jp/20160517022608

それをユーザから見て命令型変数への破壊的代入ではなく
参照透明な関数型インターフェースで実現するのが
いわゆるモナドや(誰かの独自解釈ではない本来の)FRP。

http://anond.hatelabo.jp/20160517023637

ライブラリユーザは現在時刻から状態への写像fを
参照透明な関数なりストリームなりで記述して、
それを処理系が実際のシステム時刻t=0,1,2,…に適用して
状態f(0),f(1),f(2),…を得る、という本来のFRPの基本原理

とか、君独自の勘違いFRPの解釈「本来のFRPの基本原理」で、書けるもんなら、
そのインデックスで、
システム時刻t=0,1,2,…に適用して状態f(0),f(1),f(2),…を得るという本来のFRPの基本原理で、
現在の状態を表せるとするFRP方式で、「お絵かきアプリ」をささっと実装してみせてください。

Date.now()であれ、
__a.tであれ、
「現在時間」というのは、本来的に「それ以外のシンボル」では表現できないので、
どういう魔法を使うのかたいへん興味があります。

以上、「本来のFRP 」を理解しておらず、出来もしない絵空事、机上の空論をあいも変わらず垂れ流してる例の自称関数型コミュニティへの宿題でした。

0 コメント:

コメントを投稿

Popular Posts