Reference 允许函数的副作用

Reference 允许函数的副作用,reference,ocaml,record,mutable,Reference,Ocaml,Record,Mutable,我定义了一个模块Comp,它的操作非常昂贵。在大多数情况下,对于类型为Comp.t的值,可以计算类型为int的值,该值可用于加速许多操作。因此,我定义了一个类型x,如下所示,它代表了两种情况:1)整数已被计算2)否则 type x = A of (Comp.t, int) | B of Comp.t 编写了一个函数convert:x->x,试图计算Comp.t的整数,该整数可能不存在,该函数的成本也很高: let convert (v: x): x = match v with | A

我定义了一个模块
Comp
,它的操作非常昂贵。在大多数情况下,对于类型为
Comp.t
的值,可以计算类型为
int
的值,该值可用于加速许多操作。因此,我定义了一个类型
x
,如下所示,它代表了两种情况:1)整数已被计算2)否则

type x = A of (Comp.t, int) | B of Comp.t
编写了一个函数
convert:x->x
,试图计算
Comp.t
的整数,该整数可能不存在,该函数的成本也很高:

let convert (v: x): x =
  match v with
  | A _ -> v
  | B c -> 
    try to calculate the integer "i" from "c", 
    return "A (c, i)" if the integer is found; otherwise, return "B c". 
最初,小于的comparison函数
可以这样编写:

open Comp

let lt (x0: x) (x1: x): bool =
  let x0, x1 = Comp.convert x0, Comp.convert x1 in
  match x0, x1 with
    | A (c0, i0), A (c1, i1) -> 
      i0 < i1 (* which is very fast *)
    | A (c0, _), B c1 | B c0, A (c1, _) | B c0, B c1 -> 
      Comp.lt c0 c1 (* which is quite slow *)

...
let b0 = lt x0_o x1_o in
let b1 = le x0_o x1_o in (* "le" call "convert" too *) 
let b2 = ge x0_o x1_o in (* "ge" call "convert" too *)
...
opencomp
设lt(x0:x)(x1:x):bool=
设x0,x1=Comp.convert x0,Comp.convert x1 in
将x0,x1与
|A(c0,i0),A(c1,i1)->
i0
组件lt c0 c1(*相当慢*)
...
设b0=lt x0\u o x1\u o in
设b1=le x0_o x1_o in(*“le”调用“convert”too*)
设b2=ge x0_o x1_o in(*“ge”调用“convert”too*)
...
由于
convert
的成本很高,而且除了
lt
之外,还有许多其他功能可能会不时调用它(例如
le
ge
),因此我想让转换影响外部的值。例如,我希望
lt
更改
x0_o
x1_o
的值,以便以后的函数(例如
le
ge
)接收可能已转换的参数,从而加快整个块的计算速度


所以我想应该使用可变记录之类的东西,有人能给我举个例子吗?另外,一般来说,这样做(允许副作用)以优化计算是否是一个好主意?

我认为您要做的是记忆()函数Comp.convert(如果它是纯函数):

此备忘代码使用哈希表存储结果,而不是重新计算结果(将Comp.convert函数替换为一个非常简单的函数来测试代码):


非常感谢。
Comp.t
的结构很复杂,所以我担心
Hashtbl.mem
Hashtbl.find
的复杂度很高?没关系,Hashtbl是通用的,你可以使用“复杂”结构。为什么“找不到整数”?整数是我自己定义的。。。在某些情况下,我认为有一个整数是没有意义的。的确,在这些情况下,一个特殊的值可以关联。。。
let convert x = x +  3

let convert_m' () = 
  let tbl = Hashtbl.create 100 in
  (fun x -> if Hashtbl.mem tbl x then Hashtbl.find tbl x else 
      begin 
        let n = convert x in
        Hashtbl.add tbl x n;
        n 
      end
  )

let convert_m = convert_m' ()
let b = convert_m 6