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
ますが、シールを優先するため非推奨と見なされます。)