4

interfaceOCamlでの仕組みがよくわかりません。

例を見てみましょう:

ここに画像の説明を入力


について

では、「a here」の意味は何ですか? 'aつまり、関数を説明するとき、 は を意味することを理解していますarbitrary type。では、ここでの意味は何ですか?ということarbitrary setですか?

また、なぜ 'a を の前に置くのsetですか?


概要

この例を説明するとき、Jason Hickey の Objective Caml の紹介は次のように述べています。

セットのポリモーフィック タイプを定義する必要があります。つまり、インターフェースでは、定義を与えずに型をセットとして宣言し、プログラムの他の部分が選択したセットの特定の表現を認識したり依存したりするのを防ぎます。

以上のことから、 という意味だと思いますin interface definition, we should hide the implementation details。しかし、どのような詳細が隠されていますか?


type 'a set = 'a list

実装ファイルには、type 'a set = 'a list.

これは何をしますか?

ということthis set only takes a listですか?これを意味する場合は、インターフェイス ファイルでこれを伝える必要がありますか? これのユーザーは、これsetがリストのみを取得することを知っているはずですよね?

4

1 に答える 1

9

では、ここでの'aの意味は何ですか?

これは、関数(Javaではジェネリックとして知られています)のパラメトリックポリモーフィズムに似ていますが、型の場合です。このコードセットでは、intを格納するタイプint set、文字列---string setなどがあります。'aは、一般的なOCaml構文であるため、前にあります。改訂された構文では、型変数は型名の後に記述されます:likelist intまたはset list int。さまざまな種類のポリモーフィズムの詳細については、本Types at programming languages、パートV:ポリモーフィズムをお勧めします。関数のパラメトリック多相を理解していれば、型の知識を高めることは難しくないと思います。

どのような詳細が隠されていますか?

MLファイルでは、タイプ'a setは要素のリストとして定義されています。リスト内のいくつかの要素を検索するには、リストを反復処理して(=)すべての要素を呼び出す必要があります(これが関数のList.mem動作方法です)。OCamlのAFAIRでは、stdlibセットはバランスの取れたツリーとして実装され、セットに格納されている値は、セットに格納されている要素のタイプであるcompare: t -> t -> int関数を持つ必要があります。tただし、セットは別の方法で定義でき、.mliの抽象型のみを見ると、.mlファイルでどのように実装されているかを推測することしかできません。

実際、この定義では、型は型'a listを実装するために使用されてい'a setますが、インターフェイスファイルからは、この情報は表示されません。隠された部分は、set型が実際にはであるという事実ですlist。モジュールの実装方法、および外部に提供されている情報の選択により、プログラムは、そのset作成方法を知らなくてもタイプを使用できます。

これは、開発者がモジュールを使用するコードを変更することなく、そのモジュールの実装を変更できるようにするため、ソフトウェア設計の重要な機能です。型を抽象化すると、その分離が強制されます。モジュールの外部listとしてを使用しようとすると、型エラーが発生します。set

タイプ'セット='リスト

AFAIR、この行は「タイプシノニム」(またはエイリアス)を導入しています。こことその下のタイプsetはと同じであり、期待する関数でlist使用でき、その逆も可能です。setlist

あなたが見るとき、あなたは'a setそれがただの何かのセットであることを理解するべきです、あなたがセットに置くとき、stringそれはになりますstring set'a set表示されている場合は、このセットに何が格納されているか、または格納されるかはわかりませんが、表示されている場合は表示されstring setます。タイプの同義語は、上記の本にも記載されています。

PS

つまり、タイプ'a set ='を意味します。リストは、セットがパラメーターとしてリストを期待していることを示しますか?

いいえ、そうではありません。この行に新しいタイプのエイリアスを追加するだけです。'型変数に置き換えることができる型の数を縮小しません。あなたが書くなら

# type 'a set = 'a list;;
type 'a set = 'a list
# let create x : _ set = [x];;
val create : 'a -> 'a set = <fun>

その後

List.map ((+)1) (create 2);;

コンパイラは、の型を(の型のパラメータに値が使用され、その関数の戻り型はであるため)create 2として推論し、型エイリアス(同義語)のテーブルを調べて、いつ理解するかを判断します。その型は型と同じであり、型推論のプロセスを続行します。int setint'acreate'a setsetlist

新しいシノニムを作成するときは、正しい数の型変数を記述する必要があることを理解する必要があります。つまりtype 'a new_t = ('a*'b) list、私とコンパイラの両方にとって意味がありません。少なくとも左側には右側と同じ数の型変数が必要 type ('a, 'b) new_t = ('a * 'b) listです。たとえば、動作します。

于 2013-01-09T12:34:52.680 に答える