命令型ではなく純粋に機能的にプログラミングするときに発生する可能性がある最悪の漸近的なスローダウンが何であるかを誰かが知っていますか(つまり、副作用を許可する)。
itowlsonによるコメントからの明確化:最もよく知られている非破壊アルゴリズムが最もよく知られている破壊アルゴリズムよりも漸近的に悪い問題はありますか?
命令型ではなく純粋に機能的にプログラミングするときに発生する可能性がある最悪の漸近的なスローダウンが何であるかを誰かが知っていますか(つまり、副作用を許可する)。
itowlsonによるコメントからの明確化:最もよく知られている非破壊アルゴリズムが最もよく知られている破壊アルゴリズムよりも漸近的に悪い問題はありますか?
回答:
Pippenger [1996]によると、純粋に機能する(そして、レイジーではなく、厳密な評価セマンティクスを持つ)Lispシステムを、データを変更できるものと比較すると、O(n)で実行される不純なLisp用に書かれたアルゴリズムを変換できます。 O(n log n)時間で実行される純粋なLispのアルゴリズムへ(ポインターのみを使用したランダムアクセスメモリのシミュレーションに関するBen-AmramおよびGalil [1992]の作業に基づく)。Pippengerはまた、それがあなたができる最善のアルゴリズムがあることを確立しています。純粋なシステムではΩ(n log n)である不純なシステムではO(n)である問題があります。
このペーパーについては、いくつかの注意事項があります。最も重要なのは、Haskellなどの遅延関数型言語に対応していないことです。Bird、Jones and De Moor [1997]は、Pippengerによって構築された問題が遅延関数型言語でO(n)時間で解決できることを示していますが、かどうかにかかわらず(また、私が知る限り、誰も持っていません)怠惰な関数型言語では、突然変異のある言語と同じ漸近実行時間ですべての問題を解決できません。
Pippengerによって構築された問題は、Ω(n log n)がこの結果を達成するために特別に構築されている必要があり、必ずしも実際の現実の問題を表すものではありません。問題には少し予想外の制限がいくつかありますが、証明が機能するために必要です。特に、この問題では、将来の入力にアクセスできずに結果がオンラインで計算され、入力が固定サイズセットではなく、無制限の可能な原子のセットからの原子のシーケンスで構成されている必要があります。また、この論文では、線形実行時間の不純なアルゴリズムの結果(下限)のみを確立しています。より長い実行時間を必要とする問題の場合、追加のO(log n)線形問題で見られる要因は、実行時間が長いアルゴリズムに必要な追加の操作のプロセスで「吸収」される可能性があります。これらの説明と未解決の質問は、Ben-Amram [1996]によって簡潔に検討されています。
実際には、多くのアルゴリズムは、変更可能なデータ構造を持つ言語と同じ効率で、純粋な関数型言語で実装できます。純粋に機能的なデータ構造を効率的に実装するために使用する手法の適切なリファレンスについては、Chris Okasakiの「Purely Functional Data Structures」[Okasaki 1998](彼の論文[Okasaki 1996]の拡張版)を参照してください。
純粋に機能するデータ構造にアルゴリズムを実装する必要がある人は、岡崎を読むべきです。バランスの取れたバイナリツリーで可変メモリをシミュレートすることで、操作ごとに常に最悪の場合O(log n)のスローダウンを得ることができますが、多くの場合、それよりもはるかに優れています。償却作業を段階的に行う時間的なもの。純粋に機能的なデータ構造は、操作や分析が少し難しい場合がありますが、コンパイラーの最適化、並列分散コンピューティング、バージョン管理、元に戻す、ロールバックなどの機能の実装に役立つ参照透過性など、多くの利点があります。
これはすべて、漸近的な実行時間についてのみ説明していることにも注意してください。純粋に機能的なデータ構造を実装するための多くの手法は、それらが機能するために必要な追加の簿記と問題の言語の実装の詳細により、一定量の一定の速度低下をもたらします。純粋に機能的なデータ構造の利点は、これらの一定の要因による減速を上回る可能性があるため、通常は問題の問題に基づいてトレードオフを行う必要があります。
確かにいくつかのアルゴリズムとデータ構造があり、そのために、遅延性があっても、漸近的に効率的な純粋に機能的なソリューション(純粋なラムダ計算で実装可能な最初のソリューション)は知られていません。
ただし、「命令型」言語ではメモリへのアクセスはO(1)であると想定していますが、理論的にはこれは漸近的に(つまり、無限の問題サイズの場合)は不可能であり、巨大なデータセット内のメモリへのアクセスは常にO(log n)です。 、関数型言語でエミュレートできます。
また、現代のすべての関数型言語は変更可能なデータを提供し、Haskellは純粋さを犠牲にすることなくそれを提供することも覚えておく必要があります(STモナド)。
この記事は、union-findアルゴリズムの既知の純粋に機能的な実装はすべて、それらが公開しているものよりも漸近的な複雑さを持っていると主張します。
他の回答が違いは決してないと主張しているという事実と、たとえば、純粋に機能的なコードの唯一の「欠点」は、並列化できるということであり、これらの問題についての関数型プログラミングコミュニティの情報/客観性のアイデアを提供します。
編集:
以下のコメントは、純粋な関数型プログラミングの長所と短所の偏った議論が「関数型プログラミングコミュニティ」からのものではない可能性があることを指摘しています。いい視点ね。おそらく、私が見ている支持者たちは、コメントを引用すると、「読み書きができない」だけなのかもしれません。
たとえば、このブログの投稿は、関数型プログラミングコミュニティの代表と言える人物によって書かれたものだと思います。「遅延評価のポイント」のリストなので、欠点について言及するのに適しています。レイジーで純粋に関数型のプログラミングにはあるかもしれません。良い場所は、次の(技術的には真実ですが、面白くないという点に偏っています)解任の場所にあったでしょう。
厳密な関数が厳密な言語でO(f(n))の複雑さを持つ場合、遅延言語でも複雑さO(f(n))になります。なぜ心配ですか?:)
メモリ使用量の上限が固定されているため、違いはありません。
証明のスケッチ:メモリ使用量の上限が固定されている場合、あたかも実際にそのマシンで実行しているかのように同じ漸近的な複雑さで命令命令セットを実行する仮想マシンを作成できるはずです。これは、可変メモリを永続的なデータ構造として管理し、O(log(n))に読み取りと書き込みを与えることができるためですが、メモリ使用量の上限が固定されているため、メモリ量を固定して、 O(1)への崩壊。したがって、機能の実装は、VMの機能の実装で実行される命令バージョンになる可能性があるため、どちらも同じ漸近的な複雑さを持つ必要があります。
Haskellのパフォーマンスについて読んでから、関数型言語と手続き型/ OO言語のベンチマークゲームのパフォーマンスを比較することをお勧めします。