あなたが引用したブログ投稿は、その主張を少し誇張しています。FPはデザインパターンの必要性を排除しません。「デザインパターン」という用語は、FP言語で同じことを説明するために広く使用されているわけではありません。しかし、それらは存在します。関数型言語には、「問題Xに遭遇したときに、Yのようなコードを使用する」という形式のベストプラクティスルールがたくさんあります。これは、基本的にデザインパターンです。
ただし、ほとんどのOOP固有のデザインパターンは、関数型言語ではほとんど無関係です。
一般に、デザインパターンは言語の欠点を修正するためだけに存在していると言っても、特に論争の的にはならないと思います。そして、別の言語が同じ問題を簡単に解決できる場合、その他の言語はそのための設計パターンを必要としません。その言語のユーザーは、問題が存在することにさえ気付かないかもしれません。なぜなら、それはその言語では問題ではないからです。
ギャングオブフォーがこの問題について述べていることは次のとおりです。
プログラミング言語の選択は、自分の視点に影響を与えるため、重要です。私たちのパターンは、Smalltalk / C ++レベルの言語機能を想定しており、その選択により、簡単に実装できるものと実装できないものが決まります。手続き型言語を想定した場合、「継承」、「カプセル化」、「ポリモーフィズム」と呼ばれる設計パターンが含まれている可能性があります。同様に、パターンの一部は、あまり一般的ではないオブジェクト指向言語によって直接サポートされています。CLOSには、たとえば、Visitorなどのパターンの必要性を減らすマルチメソッドがあります。実際、SmalltalkとC ++の間には十分な違いがあり、一部のパターンは1つの言語で他の言語よりも簡単に表現できます。(たとえば、イテレーターを参照してください。)
(上記は、Introduction to the Design Patternsブックの4ページ、パラグラフ3からの引用です)
関数型プログラミングの主な機能には、ファーストクラスの値、カリー化、不変値などの関数が含まれます。OOデザインパターンがこれらの機能のいずれかに近似していることは明らかではありません。
ファーストクラスの関数の近似でない場合、コマンドパターンは何ですか?:) FP言語では、関数を引数として別の関数に渡すだけです。OOP言語では、関数をクラスにラップする必要があります。これをインスタンス化して、そのオブジェクトを他の関数に渡すことができます。効果は同じですが、OOPではデザインパターンと呼ばれ、かなり多くのコードが必要です。そして、カレー化されていない場合、抽象的なファクトリパターンは何ですか?関数にパラメーターを少しずつ渡して、最後に呼び出したときにどのような値が関数から出力されるかを構成します。
したがって、はい。FPF言語ではいくつかのGoFデザインパターンが冗長になっています。これは、より強力で使いやすい代替手段が存在するためです。
しかしもちろん、FP言語では解決されないデザインパターンがまだあります。シングルトンに相当するFPとは何ですか?(シングルトンは一般にひどいパターンであることを少しの間無視します。)
そして、それは両方の方法でも機能します。先ほど言ったように、FPにもデザインパターンがあります。人々は通常それらをそのように考えていないだけです。
しかし、あなたはモナドに出くわしたかもしれません。「グローバルな状態に対処する」ための設計パターンではないにしても、それらは何ですか?これはOOP言語では非常に単純な問題であり、同等のデザインパターンは存在しません。
「静的変数をインクリメントする」、または「そのソケットから読み取る」ためのデザインパターンは必要ありません。これは、あなたがすることだけなのでです。
モナドが設計パターンであると言うことは、通常の演算で整数を表し、ゼロ要素が設計パターンであると言うのと同じくらいばかげています。いいえ、モナドは数学的なパターンであり、デザインパターンではありません。
(純粋な)関数型言語では、モナドの「デザインパターン」や、同じことを可能にする他の方法で回避しない限り、副作用や変更可能な状態は不可能です。
さらに、OOPをサポートする関数型言語(F#やOCamlなど)では、これらの言語を使用するプログラマーが、他のすべてのOOP言語で利用可能な同じデザインパターンを使用することは明らかです。実際、現在私はF#とOCamlを毎日使用しており、これらの言語で使用するパターンとJavaで書くときに使用するパターンとの間に顕著な違いはありません。
おそらくあなたはまだ命令的に考えているからですか?多くの人は、生涯にわたって命令型言語を扱った後、関数型言語を試すときにその習慣をあきらめるのに苦労しています。(私はF#でかなり面白い試みをいくつか見ました。文字通りすべての関数は、基本的にはCプログラムを取得し、すべてのセミコロンを 'let'で置き換えたかのように、単に 'let'ステートメントの文字列でした。:))
しかし、別の可能性としては、OOP言語での設計パターンを必要とする問題を簡単に解決していることに気付いていない可能性があります。
カレーを使用するとき、または関数を引数として別の関数に渡すときは、停止して、OOP言語でそれを行う方法を考えてください。
関数型プログラミングによってOOP設計パターンが不要になるという主張に真実はありますか?
うん。:) FP言語で作業する場合、OOP固有のデザインパターンは必要ありません。ただし、MVCやその他の非OOP固有のものなど、いくつかの一般的なデザインパターンが必要です。代わりに、FP固有の新しい「デザインパターン」がいくつか必要です。すべての言語には欠点があり、通常、デザインパターンはそれらを回避する方法です。
とにかく、ML(少なくとも学習目的では私の個人的なお気に入り)やHaskellなどの「よりクリーンな」FP言語で手を試すのは興味深いかもしれません。新しい何かに直面しています。
予想通り、何人かの人が私のデザインパターンの定義に「言語の欠点を修正する」と異議を唱えたので、これが私の正当化です。
すでに述べたように、ほとんどの設計パターンは1つのプログラミングパラダイムに固有であり、場合によっては1つの特定の言語にも固有です。多くの場合、それらはそのパラダイムにのみ存在する問題を解決します(FPのモナド、またはOOPの抽象ファクトリーを参照)。
抽象ファクトリパターンがFPに存在しないのはなぜですか?解決しようとする問題はそこには存在しないからです。
したがって、FP言語にはない問題がOOP言語に存在する場合、それは明らかにOOP言語の欠点です。問題は解決できますが、あなたの言語では解決できませんが、問題を回避するには、あなたからの一連の定型コードが必要です。理想的には、私たちのプログラミング言語がすべての問題を魔法のように解消することを望んでいます。依然として存在する問題は、原則として言語の欠点です。;)