我已经定义了一个模块Comp,其操作非常昂贵.在大多数情况下,对于Comp.t类型的值,可以计算int类型的值,该值可用于加速许多操作.所以我将类型x定义如下,表示2种情况:1)已经计算了整数2)否则
type x = A of (Comp.t, int) | B of Comp.t
函数转换: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".
最初,比较小的比较函数可以这样写:
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 *)
...
由于转换成本很高,并且还有许多其他函数可能不时调用它(例如le,ge),我想让转换影响外部的值.例如,我希望lt改变x0_o和x1_o的值,以便稍后的函数(例如le,ge)接收可能已经转换的参数,这导致整个块的计算速度更快.
所以我想应该使用类似可变记录的东西,有人能给我一个例子吗?另外,一般来说,这样做(允许副作用)优化计算是一个好主意吗?
最佳答案 我想你要做的是memoize(
https://en.wikipedia.org/wiki/Memoization)函数Comp.convert(如果它是纯的):
这个memoization代码使用一个哈希表来存储结果而不是重新计算它们(用一个非常简单的函数替换Comp.convert函数来测试代码):
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