web-dev-qa-db-ja.com

Haskellまたは他の関数型プログラミング言語でプログラムをどのように設計しますか?

C#やRubyなどのオブジェクト指向プログラミング言語の経験があります。オブジェクト指向のスタイルでプログラムを設計する方法、クラスとオブジェクトを作成する方法、およびそれらの間の関係を定義する方法を知っています。いくつかのデザインパターンも知っています。

人々はどのように関数型プログラムを書いていますか?彼らはどうやって始めるのですか?関数型言語のデザインパターンはありますか?極端なプログラミングやアジャイル開発のような方法論は、関数型言語に適用できますか?

52
Luke

私は主にHaskellを念頭に置いて回答を書きますが、多くの概念はErlang、LISP、MLなどの他の関数型言語にも同様に適用されます。一部は、Ruby、Python、Perl、Javascriptに(ある程度)適用されます。

人々はどのように関数型プログラムを書いていますか?彼らはどのように始めますか?

関数を書くことによって。関数型プログラミングをしているときは、mainを書くか、ヘルパー関数を書いています。場合によっては、主な目的が、データ型を操作するさまざまな関連関数を含むデータ型を記述することです。

関数型プログラミングは、トップダウンとボトムアップの両方のアプローチに非常に適しています。 Haskellは、高水準言語でプログラムを作成し、高水準設計の詳細を定義することを強く推奨しています。 minimumを参照してください。例:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

リスト内の最小の要素を見つける関数は、単にリストをたどるように記述され、min関数を使用して各要素を「アキュムレータ」または現在の最小値と比較します。

関数型言語のデザインパターンはありますか?

「設計パターン」と同等と見なせるものは2つあります。imho、高次関数およびモナドです。前者について話しましょう。高階関数は、他の関数を入力として使用するか、関数を出力として生成する関数です。すべての関数型言語は一般にmapfilter、およびfoldを頻繁に使用します(フォールドはしばしば「リデュース」とも呼ばれます):を適用する3つの非常に基本的な高階関数さまざまな方法でリストに機能します。これらは美しい方法でループのボイラープレートを置き換えます。関数をパラメーターとして渡すことは、プログラミングにとって非常に強力な恩恵です。高次の関数を使用して独自のパターンを作成し、便利な関数が満載の強力な標準ライブラリを活用することで、多くの「設計パターン」をより簡単に実現できます。

モナドは「より怖い」トピックです。しかし、彼らはそれほど怖くない。モナドを考える私のお気に入りの方法は、それらをバブル内の関数を包み込み、その関数に超能力(バブル内でのみ機能する)を与えると考えることです。詳しく説明することはできますが、世界にはもう1つのモナドの例えは必要ありません。それでは、簡単な例に移ります。非決定論的な「設計パターン」を使用したいとします。さまざまな異なる入力に対して同じ計算を同時に実行したい。 1つの入力だけを選択するのではなく、すべてを選択する必要があります。それはリストモナドになります:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

さて、これを実行する慣用的な方法は実際にはmapですが、説明のために、リストモナドが1つの値で動作するように見える関数をどのように記述できるかを確認できますが、超強力な機能を備えていますリストのすべての要素で作業するには?その他の超大国には、障害、状態、「外界」との相互作用、並列実行などがあります。これらの超大国は非常に強力であり、ほとんどのプログラミング言語では、超大国を持つ関数があらゆる場所で暴れ回ることができます。ほとんどの人はHaskellがこれらの超大国をまったく許可しないと言いますが、実際、Haskellはそれらをモナドに格納するだけなので、その効果を制限して観察することができます。

tl; dr高階関数とモナドのGrokkingは、Haskellの設計パターンのGrokkingと同等です。これらのHaskellの概念を学習したら、「デザインパターン」はHaskellのパワーをシミュレートするためのほとんどの安価な回避策であると考え始めます。

極端なプログラミングやアジャイル開発のような方法論は、関数型言語に適用できますか?

これらの管理戦略を1つのプログラミングパラダイムに結び付けるものは何もありません。 phynfoが述べたように、関数型プログラミングは実質的にforces関数分解を実行し、大きな問題をサブ問題に分割するため、ミニマイルストーンは簡単なものです。作成した関数のプロパティをテストまたは証明するためのQuickCheckやZenoなどのツールがあります。

24
Dan Burton