【问题标题】:Is it possible to garantee the consistency of memoization?是否可以保证 memoization 的一致性?
【发布时间】:2016-04-09 05:10:43
【问题描述】:

我想构建一个带有记忆功能的模块II.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 一致。一致意味着“可变属性应该是NoneSome 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,并始终使用set x c_new 代替{ x with c = 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 *) 

有没有人知道任何现有的反思或解决方案面对这种由记忆引起的不一致?如果我们一直使用set来代替“记录于”,并且不允许Content.t中的可变组件,我们能保证任何代码场景100%的一致性吗?

【问题讨论】:

    标签: ocaml lazy-evaluation memoization mutable side-effects


    【解决方案1】:

    嗯,你可以使用 private

    您的代码如下所示:

    module type C = sig
      type t = private { i: int; mutable j: int }
      val new_c : int -> int -> t
      val is_cool : t -> bool
    end
    module Content : C = struct
      type t = { i: int; mutable j: int }
      let new_c = ...
      let is_cool (x: t) : bool = ...
    end
    
    module I : sig
      type t
      val new_i : int -> int -> 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 new_i = ...
    
      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
      ...
    

    如果你尝试写:

     let c = {i = 3; j = 3};;
    

    它会拒绝你回答:

     Error: Cannot create values of the private type Content.t
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-16
      • 2015-07-03
      • 2018-02-28
      • 2019-12-15
      • 1970-01-01
      • 2020-05-14
      • 2012-11-28
      • 2016-01-17
      相关资源
      最近更新 更多