私はmemoizationでモジュールI
を作りたいと思っています。タイプI.t
には、実際の複合コンテンツc
といくつかの変更可能なプロパティ(たとえば、mutable is_cool
)が含まれています。モジュールは、変更可能なプロパティが使用されている理由です、高価なことができます特性(例えば、is_cool
)を、計算して取得する機能を外部の提供:メモ化の一貫性を保証することは可能ですか?
(*in i.ml *)
module Content = struct
type t = { i: int; mutable j: int }
let is_cool (x: t) : bool = ...
end
module I : sig
type t
val get_c: t -> Content.t
val is_cool: t -> bool
...
end = struct
type t = {
c : Content.t;
mutable is_cool : bool option;
mutable property_a : int option }
let get_c (x: t) -> Content.t = x.c
let is_cool (x: t) : bool =
match x.is_cool with
| Some r -> r
| None -> (* not yet calculated *)
let r = Content.is_cool x.c in
x.is_cool <- Some r;
r
end
...
私が持っている懸念を、モジュールをコーディングする方法ですI
のコードと、プログラムの実行中にタイプI.t
の任意の値に対して、その変更可能なプロパティは常にその内容と一致しますc
。一貫性があるということは、変更可能なプロパティはNone
であるか、またはSome v
である必要があります。ここで、v
はコンテンツの現在のプロパティを表します。例えば
は、直接性がよくモジュールI.t
の署名によって禁止されて変更したく以下のコード:ただし
(* in main.ml *)
open I
let test (x: I.t) =
x.is_cool <- Some false
は、変化し、このコードを、禁止することは容易ではないと思われます内容:これを改善する
(* in main.ml *)
let test (x: I.t) (i_new: int) =
let c = I.get_c x in
let c_new = { c with Content.i = i_new } in
let y = { x with c = c_new } in
(* now the content and the properties in y are likely to be inconsistent *)
一つの方法は、モジュールI
でset
を追加し、常に{ x with c = c_new }
の場所でset x c_new
を使用することです:
(*in i.ml *)
let set (x: t) (c: Content.t) : t =
{ c = c; is_cool = None; property_a = None }
は、しかし、まだ問題がある、例えば、
1)それは({ x with c = c_new }
2)Content.t
における可変要素の変更を書き込むことから人々を禁止することは不可能であるなど、 mutable j: int
)もI.t
が矛盾する可能性があります:
(* in main.ml *)
let test (x: I.t) (j_new: int) =
let c = I.get_c x in
c.Content.j <- j_new;
(* now the content and the properties in x are likely to be inconsistent *)
誰もが任意の既存のreflexiを知っていますこの問題を解決するにはどうすればよいでしょうか? 「レコード」の場所に常にset
を使用し、Content.t
に変更可能なコンポーネントを許可しない場合、コードシナリオの一貫性を100%保証できますか?