一般に、存在型を使用して、いくつかの型パラメーターを忘れることができます。型の代わりに、型の値を含む型'a foo
を使用します。知らないものもあります。OCaml で存在型を構築する方法はいくつかあります (ポリモーフィック レコードまたはファーストクラス モジュール)。exists_foo
'a foo
'a
ファントム型の場合、インターフェースを介して、ソケットを以前の機能を忘れた「型なしソケット」に変換する方法を提供できます。
type untyped
module Socket : sig
type 'a t
val ro : string -> [ `Read ] t
val rw : string -> [ `Read | `Write ] t
val untyped : 'a t -> untyped t
end = struct
type 'a t = string
let ro s = s
let rw s = s
let untyped s = s
end
type t = { owner : string; socket : untyped Socket.t }
let test = {
owner = "foo";
socket = Socket.(untyped (ro "bar"))
}
もちろん、ソケットがどのように開かれたかがわからない、型指定されていないソケットに対して可能なことを選択する必要があります。多分それはあなたが考えていたものではありませんか?
ソケットを合計型に保持して、その機能の知識を保持することもできます。
module Socket : sig
type 'a t
val ro : string -> [ `Read ] t
val rw : string -> [ `Read | `Write ] t
val read : [> `Read ] t -> unit
val write : [> `Write ] t -> unit
end = struct
type 'a t = string
let ro s = s
let rw s = s
let read _ = ()
let write _ = ()
end
type some_socket =
| Ro of [ `Read ] Socket.t
| Rw of [ `Read | `Write ] Socket.t
type t = { owner : string; socket : some_socket }
let test = {
owner = "foo";
socket = Ro (Socket.ro "bar")
}
let write container = match container.socket with
| Ro _ -> failwith "write not allowed"
| Rw s -> Socket.write s
最後に、最初の解決策を実装する別の方法があります。トップuntyped
型を使用する代わりに、型 Socket で値のサブタイプを許可することができます。このためには、インターフェイスでSocket.t
型の分散を指定する必要があります。それは不変 ( 'a t
)、共変 ( +'a t
)、または反変 ( -'a t
) ですか?
あなたのメンタルモデルが、より多くのケースを持つファントムバリアントタイプが「より有能」である場合、サブタイプは、いくつかのケースを持つバリアントから、より小さなタイプであるケースの少ないバリアントに移行する必要があります: to have a t
≤ b t
one should have a
≥ b
(a
より多くのケースがあります):t
反変でなければなりません。
module Socket : sig
type -'a t
val ro : string -> [ `Read ] t
val rw : string -> [ `Read | `Write ] t
val read : [> `Read ] t -> unit
val write : [> `Write ] t -> unit
end = struct
type 'a t = string
let ro s = s
let rw s = s
let read _ = ()
let write _ = ()
end
type t = { owner : string; socket : [ `Read ] Socket.t }
let test = {
owner = "foo";
socket = (Socket.rw "bar" :> [ `Read ] Socket.t)
}
(socket :> [ `Read ]) Socket.t
小さいソケット型への明示的なキャストに注意してください。