コンビネーターとは何ですか?
を探しています:
- 実用的な説明
- それらの使用例
- コンビネーターがコードの品質/汎用性を改善する方法の例
私は探していません:
- 作業の完了に役立たないコンビネータの説明(Yコンビネータなど)
コンビネーターとは何ですか?
を探しています:
私は探していません:
回答:
実用的な観点から、コンビネーターは、興味深い高度な方法でロジックの断片をまとめることができるプログラミング構造の一種です。通常、それらを使用するのは、実行可能コードを(歴史的な理由から)ラムダ関数またはラムダ式と呼ばれることが多いオブジェクトにパックできるかどうかによって異なりますが、使用する距離は異なります。
(有用な)コンビネーターの簡単な例は、パラメーターなしで2つのラムダ関数を取り、それらを順番に実行する新しいラムダ関数を作成するものです。実際のコンビネータは、次のような一般的な擬似コードに見えます。
func in_sequence(first, second):
lambda ():
first()
second()
これをコンビネータにする重要なことは、2行目の匿名関数(ラムダ関数)です。あなたが電話するとき
a = in_sequence(f, g)
結果のオブジェクトaは、最初に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コンビネータは実際には必要ありません。これは、自己再帰関数を作成できるコンビネーターであり、Yコンビネーターを使用せずに現代言語で簡単に作成できます。
Y-combinatorを「作業の完了に役立つ」ものとしてブランド化するのは間違っています。多くの場合に非常に便利だと感じました。最も明らかなケースは、組み込みのインタープリター言語をすばやくブートストラップする必要がある場合です。あなたはプリミティブの最小限のセットを提供する場合、すなわちsequence
、select
、call
、const
そしてclosure allocation
、それはすでに完了し、任意の複雑な言語を構築するのに十分です。再帰の特別なサポートは必要ありません-固定小数点コンビネーターを介して追加できます。そうしないと、はるかに複雑なプリミティブが必要になります。
コンビネーターのもう1つの明らかなケースは難読化です。SKI計算に変換されたコードは、実際には判読できません。アルゴリズムの実装を本当に難読化する必要がある場合は、コンビネーターの使用を検討してください。以下に例を示します。
そして、もちろん、コンビネーターは関数型言語を実装するための重要なツールです。最も簡単なアプローチ(上記の例のように)は、SKIまたは同等の計算を介して行われます。スーパーコンビネータは、他のいくつかの実装で使用されます。この本はそれについて詳しく説明しています。
これは冗談ですが、多くの難解なプログラミング手法と理論がそこにカバーされているので、非常に注意深く読む価値のある冗談です。
少し掘り下げて、StackOverflowの質問を見つけました。「コンビネーター」(数学者ではない人)の良い説明です。これはこの質問と密接な関係があります。 回答の1つはReginald Braithwaiteのブログ、Homoiconicを指していました。これは、コード内のコンビネーターのいくつかの有用な例にリンクしています(たとえば、 RubyのObject#tap
メソッドによって実装されるKコンビネーター。
Combinatory LogicのWikipediaページには、コンビネーターがよりグローバルに説明されています。