私はいつも、これらの両方の定義は、他の関数を引数として取る関数だと思っていました。それぞれのドメインが異なることは理解していますが、それらの特徴は何ですか?
1 に答える
さて、それらの異なるドメインからそれらの定義的な特徴を導き出してみましょう ;)
まず第一に、通常のコンテキストでは、コンビネータは高階関数です。しかし、結局のところ、これら 2 つの用語の違いについて話すときは、コンテキストを念頭に置いておくことが重要です。
高階関数
高階関数について考えるとき、通常最初に言及されるのは、「ああ、それらは (また) 少なくとも 1 つの関数を引数として取る」(fold
などを考える) ということです...あたかもそれが特別なものであるかのように。コンテキストに応じて、どれがそうです。
典型的な文脈: 関数型プログラミング、haskell、その他の (通常は型付けされた) 関数が第一級市民である言語 (LINQ が C# をさらに素晴らしいものにしたときのように)
Focus : 呼び出し元にこの関数の一部の機能を指定/カスタマイズさせます
コンビネーター
コンビネータはいくぶん特別な関数であり、プリミティブな関数は、引数として何を指定してもかまいません (引数の型はほとんど問題にならないため、関数を引数として渡すことはまったく問題になりません)。恒等コンビネータは「高階関数」とも呼べるのだろうか?正式には:いいえ、引数として関数は必要ありません! しかし、待ってください...必要な機能を「直接」実装する代わりに、どのコンテキストでコンビネータ(I、Kなど)に遭遇/使用しますか?回答: まあ、純粋に機能的なコンテキストで!
これは法律などではありませんが、ポインターやハッシュテーブルなどをコンビネーターに突然渡すコンテキストで実際のコンビネーターが表示される状況は本当に考えられません...繰り返しますが、それを行うことができます、しかし、そのようなシナリオでは、コンビネーターを使用するよりも良い方法があるはずです.
したがって、この「弱い」常識の法則 (純粋に機能的なコンテキストでのみコンビネーターを使用する) に基づいて、コンビネーターは本質的に高階関数です。引数として渡すために他に何が利用できますか? ;)
コンビネータを組み合わせると (もちろん、アプリケーションのみで - 真剣に考えれば) 、常に新しいコンビネータが得られるため、これも高階関数になります。プリミティブ コンビネータは、通常、抽象化を使用せずに何かに適用する基本的な動作または操作 (S、K、I、Y コンビネータを考えてください) を表すだけです。しかしもちろん、コンビネータの定義はそれらをその目的に限定しません!
典型的な文脈: (型なし) ラムダ計算、組み合わせ論理 (驚き)
フォーカス: (構造的に) 既存のコンビネータ/「ビルディング ブロック」を新しいものに結合します (たとえば、Y コンビネータを使用して、まだ再帰的でないものに「再帰を追加」します)。
概要
はい、ご覧のとおり、それは文脈的/哲学的なもの、または表現したいものに関するものかもしれません: 私はK コンビネーター (定義: ) を「高次関数」とは決して呼びません。関数以外で呼び出されるK = \a -> \b -> a
ことは決してないため、それを高階関数に「作成」します。K
この種の答えがあなたの質問に答えてくれることを願っています-正式にはそれらは確かに同じではありませんが、それらの定義特性はかなり似ています-個人的には、コンビネーターを典型的なコンテキストで高階関数として使用される関数と考えています(通常、特別なものと奇妙なものの間のどこかです) )。
編集:個人的な経験/印象によってわずかに「偏っていた」ことが判明したため、回答を少し調整しました。:) コンビネータと HOF を正しく区別するためのより良いアイデアを得るには、以下のコメントをお読みください!
EDIT2 : HaskellWikiを見ると、 HOFからかなり離れたコンビネータの技術的な定義も得られます!