働く男性のためのコンビネーターの説明


93

コンビネーターとは何ですか?

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

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

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

  • S
  • K
  • Y
  • To Mock a Mockingbirdの他の人(私は間違っているかもしれません-私はこの本を読んだことがありません)

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

  • 地図
  • フィルタ
  • フォールド/リデュース(おそらく)
  • >> =、作成、fmapのいずれか?????

私は最初の定義には興味がありません-それらは私が実際のプログラムを書くのを助けにはしません(あなたが私に間違っていると納得させれば+1)。 2番目の定義を理解してください。map、filter、reduceは便利だと思います。これらを使用すると、より高いレベルでプログラムを作成できます。ミスが少なく、コードが短くて明確になります。コンビネーターに関する私の特定の質問のいくつかはここにあります:

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

更新

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

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

答えは、combinator-heavyバージョンのほうが短く、明確で、より一般的だと思いますが、可能であれば、より詳細な議論をお願いします。

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


4
map / filter / foldの高次関数を検討し、常に使用しています。私はまだコンビネーターが何であるかを知りません。

1
@pst-私は5日前に合意したはずですが、今はジョンヒューズと議論することはできません
マットフェンウィック

回答:


93

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

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

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

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

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

プログラミング言語はどのコンビネーターによく実装されていますか?

それはかなり異なります。完全に汎用的なコンビネーターはほとんどなく(主に上記のプリミティブなもの)、そのため、ほとんどの場合、コンビネーターは、使用されているデータ構造を認識します(これらのデータ構造が他のコンビネーターから構築されている場合でも)。場合によっては、通常、「完全に汎用的な」コンビネータがいくつかあり、その後、誰かが提供しようと決めたさまざまな特殊な形式があります。(適切に一般化されたバージョンの)map、fold、unfoldで、必要なほぼすべてのことを実行できるケースがとんでもない数にあります。

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

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

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

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

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

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

あはははは。おもしろいことですが、オブジェクトはそもそも実際には高次のものです。オブジェクトにはいくつかのデータがありますが、それらには一連の操作が含まれており、優れたOOP設計を構成する多くのものが「オブジェクト通常、データ構造ではなく、コンビネータのように動作します。」

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


正解です。コンビネータは特別ではなく、保守可能なソフトウェアシステムの構築に不可欠な部分です。私はまだあなたの投稿の文脈で、ヒューズの「プログラムの断片」ステートメントを消化しようとしています。
Matt Fenwick、2011

@マットフェンウィック:彼が「プログラムフラグメント」を使用しているのは、私が話している変換や操作の種類を意味していると確信しています。また、メンテナンス可能なシステムを正確に構築することについては言いません。高度にモジュール化され、特定の方法で分離されたシステムを構築し、それに伴う利点をもたらすことについては言いません。
CAマッキャン2011

コンビネータの実際の使用法について読むための優れたリソースを知っていますか?本当にありがとう!
Matt Fenwick

@マット・フェンウィック:すみません、頭のてっぺんから特定のことは何もありません。ただし、これは非常に機能的なスタイルで記述されたプログラムにとって自然なアプローチである傾向があるため、それを強く奨励する言語(HaskellやClojureなど)に少し時間を費やし、その言語でクリーンで慣用的なコードがどのように記述されているかを調べます、スタイルの感触を得るためのかなり良い方法です。
CAマッキャン、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.