私はOCamlのファンクターを見ています。C++
//のいわゆる汎用オブジェクトとまったく同じように見えC#
ますJava
。今のところJavaの型の消去を無視し、C ++テンプレートの実装の詳細を無視すると(言語機能に興味があります)、ファンクターはジェネリックスとまったく同じです。私がそれを正しく理解していれば、ファンクターはあなたが提供するタイプからの新しい関数のセットをあなたに与えるので、例えば
List<MyClass>.GetType() != List<MyOtherClass>.GetType()
しかし、OCamlを大まかに書き直すことができます
#module Set =
functor (Elt: ORDERED_TYPE) ->
struct
type element = Elt.t
type set = element list
let empty = []
let rec add x s =
match s with
[] -> [x]
| hd::tl ->
match Elt.compare x hd with
Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: add x tl
let rec member x s =
match s with
[] -> false
| hd::tl ->
match Elt.compare x hd with
Equal -> true (* x belongs to s *)
| Less -> false (* x is smaller than all elements of s *)
| Greater -> member x tl
end;;
の中へC#
class Set<T> where T : ISortable
{
private List<T> l = new List<T>();
static public Set<T> empty = new Set<T>();
public bool IsMember(T x) {return l.IndexOf(x) > -1;}
public void Add(T x) {l.Add(x);}
}
確かに、ファンクターはに影響を与えるため、わずかな違いがあります(これは、の名前空間Module
と同様に、関数と値の定義の集まりにすぎません)。C#
しかし、それだけですか?ファンクターは単に名前空間に適用されるジェネリックですか?または、私が見逃しているファンクターとジェネリックの間に重要な違いはありますか?
ファンクターが単なる名前空間のジェネリックであるとしても、そのアプローチの重要な利点は何ですか?クラスは、ネストされたクラスを使用してアドホック名前空間として使用することもできます。