94

コンビネータとは??

「自由変数のない関数または定義」ですか(SOで定義されています)?

または、これはどうですか: John Hughesによる、Arrows に関する有名な論文によると、「コンビネータは、プログラムのフラグメントからプログラムのフラグメントを構築する関数です」。すべての詳細を手で書くのではなく、自動的にプログラムします。」彼は続けて、 とはそのようなコンビネータの 2 つの一般的な例だmapと言います。filter

最初の定義に一致するいくつかのコンビネータ:

  • S
  • K
  • To Mock a Mockingbird のその他(私は間違っているかもしれません -- 私はこの本を読んでいません)

2 番目の定義に一致するいくつかのコンビネータ:

  • 地図
  • フィルター
  • 折りたたむ/減らす(おそらく)
  • >>=、compose、fmap のいずれか ?????

私は最初の定義には興味がありません-それらは実際のプログラムを書くのに役立ちません(私が間違っていると確信したら+1)。 2 番目の定義を理解するのを手伝ってください。map、filter、reduce は便利だと思います。これらを使用すると、より高いレベルでプログラミングを行うことができます。つまり、間違いが少なくなり、コードがより短く、より明確になります。コンビネータに関する私の具体的な質問のいくつかを次に示します。

  1. マップ、フィルターなどのコンビネーターの例は何ですか?
  2. プログラミング言語がよく実装するコンビネータは何ですか?
  3. コンビネータは、より優れた API を設計するのにどのように役立ちますか?
  4. 効果的なコンビネータを設計するにはどうすればよいですか?
  5. 非関数型言語 (Java など) のコンビネーターと似ているものは何ですか? または、これらの言語はコンビネーターの代わりに何を使用していますか?

アップデート

@CA McCann のおかげで、コンビネータの理解が少し深まりました。しかし、1 つの質問がまだ私にとっての障害となっています。

コンビネータを多用して書かれた関数型プログラムとそうでない関数型プログラムの違いは何ですか?

答えは、コンビネータを多用したバージョンの方が短く、明確で、より一般的であるということだと思いますが、可能であれば、より詳細な議論をいただければ幸いです。

foldまた、一般的なプログラミング言語での複雑なコンビネータ (つまり より複雑) の例と説明も探しています。

4

1 に答える 1

95

私は最初の定義には興味がありません-それらは実際のプログラムを書くのに役立ちません(私が間違っていると確信したら+1)。2番目の定義を理解するのを手伝ってください。map、filter、reduce は便利だと思います。これらを使用すると、より高いレベルでプログラミングを行うことができます。つまり、間違いが少なくなり、コードがより短く、より明確になります。

2 つの定義は基本的に同じものです。1つ目は正式な定義に基づいており、提供する例はプリミティブコンビネーターであり、可能な限り最小のビルディングブロックです。それらを使用すると、より洗練されたコンビネータを作成できる限り、実際のプログラムを作成するのに役立ちます。S や K のようなコンビネータを、仮想の「組み合わせコンピュータ」の機械語と考えてください。もちろん、実際のコンピューターはそのようには機能しないため、実際には通常、高レベルの操作を別の方法で舞台裏で実装することになりますが、概念的な基盤は、これらの高レベルの操作の意味を理解するための有用なツールです。オペレーション。

あなたが与える2番目の定義は、より非公式で、さまざまな方法で他の関数を組み合わせる高階関数の形で、より洗練されたコンビネーターを使用することに関するものです。基本的なビルディング ブロックが上記のプリミティブ コンビネータである場合、それらから構築されたものはすべて高階関数であり、コンビネータでもあることに注意してください。ただし、他のプリミティブが存在する言語では、関数であるか関数ではないかが区別されます。この場合、コンビネータは通常、非関数を操作するのではなく、一般的な方法で他の関数を操作する関数として定義されます。物事を直接機能させます。

マップ、フィルターなどのコンビネーターの例は何ですか?

リストするには多すぎます!どちらも、単一の値に対する動作を記述する関数を、コレクション全体に対する動作を記述する関数に変換します。エンドツーエンドで合成したり、引数を分割して再結合したりするなど、他の関数のみを変換する関数を使用することもできます。シングルステップ操作を、コレクションを生成または消費する再帰操作に変換するコンビネータを使用できます。または、他のあらゆる種類のことです。

プログラミング言語がよく実装するコンビネータは何ですか?

それによってだいぶ変わってきます。完全にジェネリックなコンビネータは比較的少なく、ほとんどは上記のプリミティブ コンビネータです。そのため、ほとんどの場合、コンビネータは使用されているデータ構造をある程度認識します (それらのデータ構造が他のコンビネータから構築されている場合でも)。通常、少数の「完全に汎用的な」コンビネータと、誰かが提供することを決定したさまざまな特殊なフォームがあります。(適切に一般化されたバージョンの) map、fold、および unfold で、必要なほとんどすべてを実行するのに十分な場合が、非常に多くあります。

コンビネータは、より優れた API を設計するのにどのように役立ちますか?

低レベルの詳細ではなく、高レベルの操作とそれらが相互作用する方法の観点から考えると、まさにあなたが言ったように.

コレクションに対する「for each」スタイルのループの人気について考えてみてください。これにより、コレクションの列挙の詳細を抽象化できます。ほとんどの場合、これらは単なる map/fold 操作であり、(組み込み構文ではなく) コンビネーターを作成することで、2 つの既存のループを複数の方法で直接組み合わせて、一方を他方の内側に入れ子にするなどのことができます。一連のコード全体をジャグリングするのではなく、コンビネータを適用するだけで、次々と実行します。

効果的なコンビネータを設計するにはどうすればよいですか?

まず、プログラムが使用するデータが何であれ、どのような操作が意味を持つかを考えてください。次に、これらの操作を一般的な方法で有意義に組み合わせる方法と、操作をより小さな断片に分割して結合する方法について考えます。主なことは、直接的なアクションではなく、変換操作で作業することです。不透明な方法で複雑な機能を実行し、事前に消化された結果を吐き出すだけの関数がある場合、それでできることはあまりありません。最終結果は、コンビネータを使用するコードに任せてください。プロセスの開始または終了を期待するものではなく、ポイント A からポイント B に移動するものが必要です。

非関数型言語 (Java など) のコンビネーターと似ているものは何ですか? または、これらの言語はコンビネーターの代わりに何を使用していますか?

あははは。そもそもオブジェクトは本当に高次のものなので、おかしなことに、オブジェクトにはデータがありますが、多くの操作も実行されます。優れた OOP 設計を構成する要素の多くは、「オブジェクトは通常、データ構造ではなく、コンビネーターのように振る舞います。」

したがって、おそらくここでの最良の答えは、コンビネーターのようなものの代わりに、多くの getter および setter メソッドまたは public フィールドを持つクラスと、不透明で事前定義されたアクションを実行することで主に構成されるロジックを使用することです。

于 2011-09-23T20:40:11.313 に答える