web-dev-qa-db-ja.com

コンビネーターとは何ですか?それらはプログラミングプロジェクトにどのように適用されますか? (実用的な説明)

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

を探しています:

  • 実用的な説明
  • それらの使用例
  • コンビネーターがコードの品質/一般性を向上させる方法の例

私は探していません:

  • 仕事を終わらせるのに役立たないコンビネーターの説明(Yコンビネーターなど)
53
user39685

実用的な観点から見ると、コンビネータは一種のプログラミング構造であり、ロジックの断片を興味深い、しばしば高度な方法でまとめることができます。通常、これらの使用は、実行可能コードをオブジェクトにパックできる可能性に依存します。これは、(歴史的な理由から)ラムダ関数またはラムダ式と呼ばれることが多いですが、距離はさまざまです。

(便利な)コンビネーターの簡単な例は、パラメーターなしで2つのラムダ関数を取り、それらを順番に実行する新しいものを作成するものです。実際のコンビネーターは、次のような一般的な疑似コードに見えます。

func in_sequence(first, second):
  lambda ():
    first()
    second()

これを結合子にする重要なことは、2行目の無名関数(ラムダ関数)です。あなたが電話するとき

a = in_sequence(f, g)

結果のオブジェクトaはnot最初に実行した結果f()、次にg()ですが、後で呼び出してf()を実行できるオブジェクトですとg()を順番に:

a() // a is a callable object, i.e. a function without parameters

同様に、2つのコードブロックを並列に実行するコンビネーターを使用できます。

func in_parallel(first, second):
  lambda ():
    t1 = start_thread(first)
    t2 = start_thread(second)
    wait(t1)
    wait(t2)

そして再び、

a = in_parallel(f, g)
a()

クールなことは、「in_parallel」と「in_sequence」はどちらも同じタイプ/シグネチャを持つコンビネーターです。つまり、どちらも2つのパラメーターのない関数オブジェクトを取り、新しいものを返します。あなたは実際に次のようなものを書くことができます

a = in_sequence(in_parallel(f, g), in_parallel(h, i))

期待どおりに動作します。

基本的に、コンビネータを使用すると、プログラムの制御フローを(とりわけ)手続き的で柔軟な方法で構築できます。たとえば、プログラムで並列処理を実行するためにin_parallel(..)コンビネーターを使用する場合、それに関連するデバッグをin_parallelコンビネーター自体の実装に追加できます。その後、プログラムに並列処理関連のバグがあると思われる場合は、実際にはin_parallelを再実装するだけです。

in_parallel(first, second):
  in_sequence(first, second)

そして、1ストロークで、すべての平行断面が連続断面に変換されました!

コンビネータは、正しく使用すると非常に便利です。

ただし、Y Combinatorは実際には必要ありません。これは、自己再帰関数を作成できるコンビネーターであり、Y Combinatorがなくても、現代の言語で簡単に作成できます。

56
antti.huima

Y-combinatorを「作業を完了するのに役立つ」ものとしてブランド化するのは間違っています。私はそれが多くの場面で非常に役立つとわかりました。最も明白なケースは、すぐにbootstrapいくつかの組み込みインタープリタ言語を使用する必要がある場合です。プリミティブの最小セット、つまりsequenceselectcallconstおよびclosure allocation、完全で恣意的な複雑な言語を構築するにはすでに十分です。再帰の特別なサポートは必要ありません-固定小数点コンビネーターを介して追加できます。それ以外の場合は、はるかに複雑なプリミティブが必要になります。

コンビネータのもう1つの明らかなケースは難読化です。 SKI微積分に変換されたコードは、実際には読み取ることができません。アルゴリズムの実装を本当に難読化する必要がある場合は、コンビネータの使用を検討してください これは例です

そしてもちろん、コンビネータは関数型言語を実装するための重要なツールです。 (上記の例のように)最も簡単なアプローチは、SKIまたは同等の計算によるものです。 Supercombinators は、他のいくつかの実装で使用されています。 この本 はそれについて深く話します。

これは冗談です ですが、多くの難解なプログラミング技術と理論がカバーされているため、非常に注意深く読む価値のある冗談です。

10
SK-logic

少し掘り下げて、StackOverflowの質問を見つけました 「コンビネーター」の適切な説明(非数学者向け) これは、この質問の非常に従兄弟です。 回答の1つReginald Braithwaite's blog、Homoiconic をポイントしました。これは、コード内のコンビネーターのいくつかの有用な例にリンクしています(例 K Combinator 、実装済み) RubyのObject#tapメソッド-このページが役立つ理由の例をご覧ください)。

Combinatory LogicのWikipediaページ は、combinatorをよりグローバルに説明しています。

8
Aidan Cully