匿名質問者

Haskellについて調べています。Haskellにおける遅延評価とメモ化のメリットについて。

これらの機能についてメリットがあるのは分かるのですが、そこまで強烈なものに感じません。
遅延評価のメリットとして計算の最適化があげられると思いますが、そもそも無駄な計算が発生しないように書くと思います。具体的には条件分岐の自由度が増す程度で、あまり抽象化としての効果は高くないのではないかと思ってしまいました。
メモ化についても自動最適化ということだと思いますが、そもそもアルゴリズムを個別に学習せねばならず、アルゴリズムの中に必要ならばメモ化が組み込まれているケースばかりだと思います。
メリットがある言語を学びたいのは山々ですが、学習コストと効果の大きさ、シェアの少なさがネックです。
Haskellや関数型言語に詳しい方、自分の解釈に違いがあったり意見があれば教えてください。お願いいたします。

回答の条件
  • 1人50回まで
  • 登録:
  • 終了:2014/10/17 16:05:04

回答1件)

匿名回答1号 No.1

「最適化」ととらえている限り、遅延評価の本当の効果は実感できないと思います。積極評価の発想のまま、その一部が良くなった、という見方だからです。

遅延評価を前提にすると、コードの書き方が発想の段階から違ってきます。そちらの発想からすると、積極評価は「逆最適化」をやってるようなもので、それを回避するには遅延評価ですっきり書けるコードをわざわざ回りくどい方法で書いてやらないとならない、ように見えます。

ただ、こういう発想の違いを短い例で示すのは難しいですね。短い例だとどちらで書いてもそれほど複雑になりませんから。一応、定番の文書として『なぜ関数プログラミングは重要か』http://www.sampou.org/haskell/article/whyfp.html がありますが、例に出ている問題の大規模版を書いた経験が無いとメリットがピンと来ないかもしれません。

質問者さんは、既にある程度まとまった大きさのHaskellコードを書いてみた後で、メリットがわからないとおっしゃっているんでしょうか。だとしたら、もともと合ってないのかもしれません。それなら敢えて学習する必要もないのではないかと思います。

実際にHaskellのコードを色々書く前の段階で迷っていらっしゃるなら、学習コストなんか気にならなくなるくらい興味を惹かれるようになるまで、置いておいたら良いんじゃないでしょうか。シェアが少なそう、とか、時間を投資する見返りがあるかどうか不安、なんて思っているようじゃ、まだ本当に興味を惹かれてないってことですよ。今使ってる言語で満足してるなら、それでいいじゃないですか。

匿名質問者

自分が調べている限り、最適化が目的という意見が多く、自分も仕組みを知る過程でそう考えています。
違った発想とのことですが、まだ完全に習得していない人間からすれば最適化と言っていいのではないか思ったので質問させていただきました。
ある程度書くまでにそのメリットデメリットを判断し、学ぶ価値があるかどうかを探るのはそんなにおかしいことでしょうか?すでに学んだ人から教えていただける内容があるなら、と思い質問したのですが。

2014/09/18 03:31:30
匿名回答1号

「最適化」という言葉に、違うニュアンスが載る場合があります。広く使われる(言語処理系が行う)最適化のニュアンスは、例えばCコンパイラの-Oオプションでイメージされるものだと思います。プログラムの根本的な構造はそのままに、重複する計算を省くなどして速度を上げる、というような操作です。こういった最適化は、その最適化が無くてもプログラムはちゃんと動作するけれど、あれば速くなる(あるいはコードが小さくなる)、といった性質のものです。

しかし、「最適化」と呼ばれる操作のうち、プログラムの構造の選択自体に影響を与えてしまうようなものがあります。例えば「末尾呼び出し最適化 (TCO)」。これが保証されている言語とそうでない言語では、ある種のアルゴリズムの書き方自体が変わってしまいます。TCOありの言語処理系では状態機械は関数呼び出しの連鎖で綺麗に書けますが、TCO無しで同じように書くとスタックを食いつぶして実用になりません (理論上は無限のスタック領域があれば等しいですが、現実的には使えないコードです)。TCOの有無で、同じ書き方をしたコードにO(n)かO(1)かという差が出てくる、そのためにTCOが無い処理系ではプログラムの書き方自体を変えなければならない、という点が、-Oオプションによる最適化とは一線を画します。-O2のプログラムを-O0でコンパイルしても大抵は定数オーダーで遅くなるだけで動きますからね。

遅延評価も、後者の意味では「最適化」と言えるでしょう。けれども、遅延評価を前提に組まれたアルゴリズムには、遅延評価無しではO(1)→O(n)どころか、永遠に終了しなくなる、というものがよくあります。だから遅延評価ありで自然に書けるアルゴリズムを、遅延評価無しの言語に移植するには、アルゴリズムの設計段階から変えなければなりません。(もちろん、積極評価の言語上で遅延評価ライブラリを使う、という手はありますが、そういう話をしているわけではないですよね。)

遅延評価でさくっと書けるけれど、積極評価では遅延評価ライブラリを使うか回りくどい書き方をしなければならない、というコードを書いたことはありますか? 積極評価でコードを書きながら、「ああ遅延評価が使えれば綺麗に書けるのに、うざったいなあ」と感じたことはありませんか? 元のご質問からではそういう経験が無いのじゃないかな、という印象を受けました。

もし既にそういったコードを書いた経験があって、その上で遅延評価のメリットを感じないのであれば、おそらく関心のある問題領域が遅延評価に向いた領域ではないということでしょうから、「もともと合っていない」のだと思います。実際、私も主力のツールは積極評価の言語で、一部だけ遅延評価の仕組みを載せて使うことが多いです。それが私のスタイルに合っているので。

一方、もし上の印象が当たりなら、そういったコードをいくつか書いてみるまではいくら言葉で説明されても理解できないだろうと思います。同じレイヤの別の技術、例えばyet anotherオブジェクト指向言語だとか、yet anotherフレームワーク、に関しては、「学習コスト」や「シェアの多寡」で学ぶかどうかを判断して良いと思うのですが、違うレイヤの概念に関しては一旦その空気を自分で味わってみないことには、判断のしようがないわけです。もし本当に興味をお持ちなら、飛び込んでみませんか。結果的に使わないとしても、そこで学んだ概念はきっと今後書くプログラムに役に立つと思いますよ。

2014/09/18 05:08:53

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません