1

次のようなデータ型があるとします

datatype IntLt = ltObj of int * int * (int * int -> bool)

つまり、このオブジェクトは、対応する操作を持つ int のペアです。ltObj の作成時に、2 つの引数を使用して関数を自動的に呼び出し、結果が false の場合に例外を発生させる方法はありますか?

つまり__init__、Python や C/C++/Java の通常のコンストラクターに類似した、データ型の構築に関するコンストラクター型の手順を探しています。これにはファンクタとシグネチャを使用しないことをお勧めします。

4

2 に答える 2

4

ML でこのような不変条件を強制する慣用的な方法は、モジュール システムを使用して抽象データ型 (ADT) を定義することです。簡単なスケッチを次に示します。

signature INT_LT =
sig
  type int_lt

  val int_lt : int * int * (int * int -> bool) -> int_lt
  val pair   : int_lt -> int * int
  ... (* other abstract operations you might want *)
end

structure IntLt :> INT_LT =
struct
  type int_lt = int * int * (int * int -> bool)

  fun int_lt(x, y, f) =
      if f(x, y) then (x, y, f) else raise Domain

  fun pair(x, y, f) = (x, y)

  ...
end

具体的には、ここでの不透明な署名帰属の使用に注意してください ( 封印:>とも呼ばれます)。型の値が与えられた場合、誰もその内部表現を知ることができないことを保証します。つまり、モジュール インターフェイスを経由せずにこの型の値を作成したり、アクセスしたりすることはできません。IntLt.int_lt

現在、これは署名を使用していますが、ファンクターは使用していません。:) (そうは言っても、コンストラクトを介して ADT を作成する方法もありabstypeますが、シールを優先するため非推奨と見なされます。)

于 2013-04-29T17:59:37.833 に答える
1

ありません — 後でコンストラクターでパターン マッチを実行できるようにしたい場合。

それに最も近いのは、必要なことを行う関数を作成し、それを使用してIntLt値を構築することです。

exception InvalidIntLt of int * int;

fun createIntLt (a, b, f) =
    if   f(a, b)
    then LtObj (a, b, f)
    else raise InvalidIntLt (a, b);

IntLtコンストラクターを使用して無効な * 値を指定することは引き続き有効であることに注意してください。

構造内にデータ型を作成する場合、これを防ぐオプションがあります。LtObjシグネチャを使用して、値コンストラクターを構造体の外に隠すことができます。ただし、これは、値コンストラクターを構造体外のパターン マッチングに使用できないことも意味することに注意してください。

*: それにf(a, b)は当てはまりません。

于 2013-04-29T15:39:29.817 に答える