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


52

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

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


回答:


24

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

人々はどのように機能的なプログラムを書くのですか?どうやって始めますか?

関数を書くことにより。関数型プログラミングを行うときは、を書いているかmain、ヘルパー関数を書いています。時には、主な目標は、データ型を操作するさまざまな関連関数を含むデータ型を作成することです。

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

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

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

関数型言語の設計パターンはありますか?

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

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

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

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

tl; dr高階関数とモナドのグロッキングは、Haskellのデザインパターンのグロッキングと同等です。これらのHaskellの概念を学ぶと、Haskellの力をシミュレートするための「デザインパターン」はほとんど安価な回避策であると考えるようになります。

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

これらの管理戦略を、あるプログラミングパラダイムに結びつけるものは見当たりません。phynfoが述べたように、関数型プログラミングは事実上強制的にそうミニマイルストーンは、ケーキの一部である必要があり、あなたは部分問題に大きな問題を壊し、機能分解を行うこと。QuickCheckやZenoのようなツールを使用して、作成する関数に関するプロパティをテストしたり、証明することさえできます。


「詳しく説明することはできましたが、世界はもう1つのモナドの類推を本当に必要としません。」-モナドには常により多くの類推が必要であり、あなたのものは私が見た中で最高のものの一つです。
アダム・ゲント

1
すばらしい答えですが、デザインパターンの議論は少し誤解を招くと思います。Haskellではオブジェクト指向/ GOFスタイルのデザインパターンは必要ありませんが(実際、それらを試すのはばかげています)、パターン自体は、コミュニティが繰り返し発生する種類の問題の解決策を伝える方法です。Haskellコミュニティはまだ非常に若いため、語るべきパターンはまだ多くありませんが、Haskellのパターンの例について質問された場合は、GADTやArrowized FRPのようなものに言及します。
rtperson
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.