コンビネーターとは何ですか?
を探しています:
私は探していません:
実用的な観点から見ると、コンビネータは一種のプログラミング構造であり、ロジックの断片を興味深い、しばしば高度な方法でまとめることができます。通常、これらの使用は、実行可能コードをオブジェクトにパックできる可能性に依存します。これは、(歴史的な理由から)ラムダ関数またはラムダ式と呼ばれることが多いですが、距離はさまざまです。
(便利な)コンビネーターの簡単な例は、パラメーターなしで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がなくても、現代の言語で簡単に作成できます。
Y-combinatorを「作業を完了するのに役立つ」ものとしてブランド化するのは間違っています。私はそれが多くの場面で非常に役立つとわかりました。最も明白なケースは、すぐにbootstrapいくつかの組み込みインタープリタ言語を使用する必要がある場合です。プリミティブの最小セット、つまりsequence
、select
、call
、const
およびclosure allocation
、完全で恣意的な複雑な言語を構築するにはすでに十分です。再帰の特別なサポートは必要ありません-固定小数点コンビネーターを介して追加できます。それ以外の場合は、はるかに複雑なプリミティブが必要になります。
コンビネータのもう1つの明らかなケースは難読化です。 SKI微積分に変換されたコードは、実際には読み取ることができません。アルゴリズムの実装を本当に難読化する必要がある場合は、コンビネータの使用を検討してください これは例です 。
そしてもちろん、コンビネータは関数型言語を実装するための重要なツールです。 (上記の例のように)最も簡単なアプローチは、SKIまたは同等の計算によるものです。 Supercombinators は、他のいくつかの実装で使用されています。 この本 はそれについて深く話します。
これは冗談です ですが、多くの難解なプログラミング技術と理論がカバーされているため、非常に注意深く読む価値のある冗談です。
少し掘り下げて、StackOverflowの質問を見つけました 「コンビネーター」の適切な説明(非数学者向け) これは、この質問の非常に従兄弟です。 回答の1つReginald Braithwaite's blog、Homoiconic をポイントしました。これは、コード内のコンビネーターのいくつかの有用な例にリンクしています(例 K Combinator 、実装済み) RubyのObject#tap
メソッド-このページが役立つ理由の例をご覧ください)。
Combinatory LogicのWikipediaページ は、combinatorをよりグローバルに説明しています。