はてなキーワード: モナドとは
基本情報・応用情報試験みたいなのとか、CPUの仕組み、コンパイラの実装、分散システムやデータベースとかそういうエンジニアリングガチ勢みたいなのをイメージして大学でCSを学ぶとけっこうショックを受けるぞ。
俺の知ってるCSは、チューリングマシンの表現能力とか停止性問題とかYコンビネーターとかチャーチ数とかの世界で、コンパイラといってもε-CLOSUREみたいな話をじっくりやる感じ。
具体的な話が全然出てこない数学の一ジャンルってイメージかもな。
競技プログラミングみたいなアルゴリズムもそれほど時間をかけない。ベイズ推定をギリやるかどうか。
そういう知ればすぐ身につくものよりも、めちゃくちゃ考えて濃厚なパラダイムを時間をかけて吸収するような学問だった。
で、そんなCSを学んで直接役に立つのは多くの人の場合計算量のオーダーとかくらいかも。
モナドみたいな概念に抵抗なくなるとか、ラムダ式の意味を深く理解できるというのもあるけど、それSIとかWebやスマホアプリの開発業務で必要かというとね。
賢い人は、ちゃんとSNSのユーザー同士の関係性とかレコメンデーションみたいのにもCSの知識を応用できると思うけど、一般人は賢い人が作ったライブラリを使う側だよね。
Haskellと圏論を結びつける主張には前々からずっと疑問を感じている。
およそ、その主張の根拠は「圏論の概念であるモナドを借りてきたからだ」というのだが、その言葉の意味を突っ込んで追求した人はいないのだろうか。
数学科として、ある程度圏論を学んだ身として疑問に思ってしまうのが、
つまり、総合的に、「Haskellは圏論を用いることで副作用や参照透過性などのプログラミング言語の課題を解決したのだ」というよくある主張が、全然ピンと来ない。
この辺突っ込んでちゃんと解説している専門書はないのだろうか?
第一、第二、第三の疑問いずれに対しても、満足のいく回答は得られず、ただ「モナドは圏論由来の概念だ」というだけだ。
もしかして何か、圏論という一般にはよく理解されていない概念の言葉を良いように使って、なんだか深淵で素晴らしいもの聞こえるよう、同業者を適当にだまくらかしているんじゃないのか?とすら思えてしまう。
最近はGoが流行っているが、それならJavaだって同様に良さそうな気がする。
- nullがたまにうざい
- なんか重厚な感じがする
- ORMとかが重厚なのが多かった
- 故に環境構築が大変だった
- strutsがしんどかった
- xml地獄からアノテーション化したりいろいろと模索していた
- ちょっと昔には「俺たちイケてるプログラマ」はみんなRailsに移っていった流れがあった?
- Effective Javaよいが、そもそもそういうtips意識せずにそう書けるような言語仕様になってほしかった気もする
- 非同期処理やスレッド処理がやや難しかったか、あるいは言語側でのサポートが薄かったか(?)
言語仕様的な批判と、エコシステム的な批判に分けられそうなきがするな。
関数型言語の関心はScalaやClojureに全フリしてもらって、Javaはシンプルな機能を持つGoの方向性なModan Javaになっていってくれれば良さそうな気も。
httpサーブレットとかそのへんが微妙だったかもしかして。Goみたいにnet/httpライブラリが標準であればそれをベースにすることでオレオレフレームワークの乱立を避けることができるか、と思ったけどJAX-RSとかがあるな。
Goだって冗長な記述が必要な言語だが、好かれているし、Javaも悪くない言語な気がするんだよな。
まあ何でもいいが。
ロジカルに考えているようで結局なところ雰囲気的なところに左右されているエンジニア多い気がする。
まあわいも、人気な言語に乗っておいて高単価を得られたほうがいいのでそうするが。今の所Goが肌にあっているんだよな・・。3年ぐらい使って熟練度上がってきたし、さほど悩まずにコーディングすることができる。
PHPの人が好きな、あるいはRubyのmethod_missingなど活かしたテクいコードは、書いているやつは気持ちいいかもしれないがわいは明示的にinterfaceがわかるコードが書かれていたほうが好きだ。型で振る舞いがわかったり制御されていないと分かりづらくない?複数のプロジェクトを掛け持ちするから、読むときに前提知識が少なく読めるコードがいい。
まあJavaもリフレクションでテクいことができる気がするな。
Goがいい。誰が書いてもだいたい同じコードになるから、誰かに作業を振ったとしてもレビューしやすい。
まあこれからJavaを書く気はしないが、GoでAPI書いているマンから見ると、JAX-RSとかでゴリゴリAPI書いていくの全然悪くないんじゃないかと思うのであった。
最悪別にGeneric入らなくてもいいかもな。別にそんなに困ってない。はいってくれるなら、はいってくれたほうがいいが。sliceに対してmap, each, filter, existsなどのメソッドが生えることになるイメージかな。まあそれは欲しくなるけどな・・・。
Scalaもいいんだが、たまにイキったコードを書くと分かりづらくなる時がある。イケてるコードを書こうと思ったとき、結構パワーを使う言語だ。なんかモナドってジェネリックを更に強くしたやつだとも捉えられるような気がするな。ゴリゴリ関数型で書こうと思った場合、プロジェクト全体に影響がある話なのでアーキテクチャ設計に力がいる気がする。
年をとると大事にするポイントが変わってくるな。昔はスーパープログラマになりたくて関数型言語とかやっていたが、今はいかに効率よく仕事をする=金を稼ぎ自由を得るかを重視している。職業プログラマとなったわけだ。仕様固めたりリリースしたり不具合対応したり運用したり、フリーランスなら税金計算したり、金儲けの方法考えたり忙しいんじゃ。今は結局スーパープログラマとは何か悩ましいよ。「プログラマとして」キチガイレベルにすごい人間というのはまだ見たことがないかもしれない。コーディングが早い?バグ修正が早い?パフォーマンスのやばいコードを書ける?設計が優れている?
最近はレバレッジが効く言語とフレームワークを好きになるようになってきた。
もう言語何でもいいわ。やっぱ静的言語がいいのと十分に熟練度がついてきたのでAPI開発ではGolang使って開発するのは良い。PHP(Laravel)、Ruby(Rails)はやはり生産性が高いので良い。ScalaもMonad Transformerを使ってモナドのスタックを解決していく程度あれでやっていき、あまり悩まないような構成になっていればサクサクやっていけそう。
実はJavaが一番いいんじゃないか…。Springガッツリやったこと無いけど、トランザクションとかもいい感じに効いてくれそうだし、そこそこ生産性高そうだし。
知らんけど。
なんでもいいや。
うるせぇIOモナドぶつけんぞ!
実を言うと、普通のプログラマはオブジェクト指向以前のプログラミングも理解できないんだけど、あれらはまだ手続き的な要素を内在してるから、そっちだけを受け取ることはできる。
それまで手続き的な要素+宣言的な要素だったプログラミングが、関数型プログラミングへと移行する時に手続き的な要素を切り捨てたのね。より純粋な手法に進化するために。
だから、それまで手続き部分だけを受け取って喜んでた普通のプログラマは急にわからなくなりヒステリーを起こした。
だけど、プログラミング上級者はオブジェクト指向以前にも宣言的な部分しか見てないから普通のプログラマが何を騒いでるのかわからない。
普通のプログラマって、部品化の凄いやつが関数型プログラミングになるとか勘違いしがちだけど(staticおじさんもその変奏)、全く質の違うもの。
部品化って、重複コードをひすたらサブルーチンに括り出すようなもの。副作用がある。
日本のSIer(日立NEC富士通とか)って教養がない極東の田舎者だから、副作用を理解できない。すぐに「部品化」を持ち上げる。怖いんだろう。自分に理解できないプログラミングが。モナドですら大多数は理解できないんだもの。あんな教科書的なものですら。
とにかくアジアってIT後進国なのね。トップの日本ですらこうなのだから。"NTT"データがHaskellでレガシーシステムを脈絡なく解析してホルホルしてるレベルだもの。
まず日本に生まれた時点で、関数型プログラミングを理解するには圧倒的に不利。こんなこと言うと、「普通のプログラマにもわかやすく説明できるのが一流ダー」みたいな恥ずかしい駄々っ子が沸いてくるけど、プログラミングって歴史上一度も大衆を相手にしてないので。
OSSの恩恵で、普通のプログラマもコンパイラを無料で使えるようにになっただけで泣いて喜ぶべき。
そしてあれは、将来のスポンサーとコミッタの入り口としてやってるの。1000人に1人、将来コミュニティに貢献する人材がいるかもしれないと信じて。
シリコンバレー住人にもOSSコミッタにもなれない普通のプログラマはまあ、おこぼれで"文化的"コスプレしてQiitaでもやればいいんだと思うよ。
Haskell を書いてるわけではないんだけど Haskell でメモ化したい関数ってどうするんだろう
という条件なので、キャッシュを取って、キャッシュになければ計算して返すクラスを作った
純粋関数型でこれをやろうとするとモナドになったりして面倒臭そう
しかしながら
と思ったのですがどうなんでしょう。
第一に、それは、ストリーム(FRPの値の定義)の問題であって、ユニットテストすれば良い。もしくは単にFRPのログを取れば良い。
グローバル変数ではそういうことはできない。FRPでは、岡部氏のFRPライブラリも特にそうだけど、基本的にミュータブルな値同士が関数でリアクティブに連携されて常に整合性を保っているのだから、グローバル変数の、各所で更新されたそれぞれの値によって全体の整合性が損なわれないように気を配らなければいけないという(テスト自体困難な)問題は発生しない。それがFRPの唯一とも言えるメリットだとも言える。
使用する関数の問題じゃないし、「印」として引数に加えても別に構わないと思うが、君のいうグローバル変数の問題と一緒というのはまったく違う。
いや、それがそもそもの発端であるとブログの経緯には書かれている。説明されている方式でGUIアプリまで書けるのか?と疑念が呈されたことがきっかけ。
この論点は聞いたことがない。岡部氏がこだわっているのは非手続き型の宣言型で、純粋がどうとか議論はされてないように思う。
あと、OCamlでGUIを状態渡しで書いたら簡潔で無いのを「書けない」、「不可能」って言ってるのはわざと印象操作しようとしてるよね?
原理的に可能かという議論ではなく、実用的な範疇か?という議論。反対派ブログで出てきたコードは、本人が認めるように普通のやり方ではなく、実用的なコードだとは思えない。あと、FRPと状態渡しは同じ複雑さだという主張も崩されている。そこが重要。
段階を踏んだ上で、非FRPのHaskellのIOモナドのコードを誰かが書いたらいんじゃない?当面、最初はOCamlの話だったのに、いきなりHaskellやElmのコードで書いて、そういうのがごちゃまぜに、何がどの言語でできるのかできないのか、誤魔化しがあると見做されたから制限されたんでしょ。実際には、OCamlの関数型では冗長でしか書けないと実証されたけど、そういうのがバレないように、別の言語を利用していたと看破されて当然の状況だと俺は思うね。
ストリームを関数の外部に持つFRPを純粋関数型っていうのは少数派でしょ。
ユーザからの入力をリアルタイムに処理するプログラムにはFRPは有効だよね。
「OCamlでは」じゃないの?
全部純粋関数型(引数と戻り値に収める、状態渡し)にするのを良しとするHaskellと違って、OCamlは副作用も部分的に使うのが普通で、IOモナドみたいな入出力までも純粋に書くための道具立てが揃ってない、それでちょっと冗長になる、ってことでしょ?
OCamlの元々の推奨スタイルならもっと短く書けるんでしょ?
俺はそう読んだけど。
それっぽい書き込みほどそうやって、事実誤認だ、と強調するから、なんで当事者でもないのに、そんなことが断言できて、電波だということになるんだ?
だって駱駝でも住井でもない面識も無い俺の書き込みが住井扱いされるんだもの。
いやだから、どの関数で読み書きされようと、誰が書き換えようとも、時間にたいしてイミュータブルな定数なんだから、定数は定数なのよ。
FRPライブラリのサブタイトルに、 library that provides first class reactive value 'over time' と書かれている、これ拡張じゃないのか?
https://www.npmjs.com/package/timeengine
IOモナドをDisってるのかどうかまでは知らない。しかし、すでに出たサンプルからはFRPの効力がまざまざと見せつけられている。
荒れるのは自由だけど、両方正しいとかそういうのじゃなくて、間違っている電波だみたいな叩きしかなくて、要するに感情論で反対派は反発しているだけでOK?
あるよ。
関数がどのパラメータに依存して、何を結果として返すのか明確になる。
グローバルな値を参照したり書き換えたりしてたら、関数の中身読まないとわからなくなる。
短いプログラムならそれでもいいけどね。
別の誰かが書いてたように、上位スコープ内に定義されてるDOMでも、数学ライブラリでもなんでも、引数で関数に渡すのか?
グローバルな値を参照したり書き換えたりして
いやだから、定数なんだから書き換わらないんだよ、FRPのストリームはconst 定数なんだから。
オブジェクト指向と対比して考え方をまず学ぶって、岡部路線、住井グループはそれを目の敵にしていて集団的に攻撃している様をみたプログラミングコミュニティは逃げ、その後、不毛な大地のみが残った。
「OCamlでは」普通に副作用を使うライブラリしかないからスケールしない、って書いてあるのに
なんで勝手に一般化して、Haskellとかでもスケールしないことにしたいの? 本当に牽強付会のオンパレードですね。
http://qiita.com/nonstarter/items/2763f5d85f2b8df3b18b#comment-d9a8cdf2efc67044c158
>OCaml の全ての GUI ライブラリは状態は副作用を使うことを前提にメインループが設計されているからです。これを乗り越えるとすると @Lambada さんのようにメインループ自体を自分で書く事になり、一般的にはスケールしません。Haskell の GUI ライブラリでは普通は状態は State なり IO を含む GUI モナドを使って書く事になりますが、そのような GUI ライブラリを OCaml 上で作れば同じような事が出来るはずです。OCaml でそこまで純粋関数型のコードを書く事に実用的意味があるとは思えませんが。