2013-06-25 47 views
4

我已经定义了一个模块Comp,它的操作相当昂贵。在大多数情况下,对于Comp.t类型的值,可以计算出类型为int的值,该值可用于加速许多操作。所以,我定义类型x如下表示2情况: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". 

最初,comparaison功能less than可以写成如下:

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 *) 
... 

由于convert是昂贵的,并且还有许多其他功能可能会不时地调用它(例如, le,ge),我想使转换影响外部的价值。例如,我希望lt更改x0_ox1_o的值,以便后面的函数(例如le,ge)接收可能已经转换的参数,这会导致整个块的计算更快。

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

+0

为什么会“找不到整数”? – newacct

+0

整数是我自己定义的东西...在某些情况下,我认为它是没有意义的有一个整数...嗯,这是真的,一个特殊的值可以在这些情况下关联... – SoftTimur

回答

2

我想你想要做的是memoize的(https://en.wikipedia.org/wiki/Memoization)功能Comp.convert(如果是纯):

这memoization的代码使用哈希表来存储结果,而不是重新计算它们(替换函数comp用一个非常简单的代码来测试代码):

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 
+0

谢谢... Comp.t的结构很复杂,所以恐怕Hashtbl.mem和Hashtbl.find的复杂性很高? – SoftTimur

+0

没关系,Hashtbl是通用的,你可以使用它的“复杂”结构。 – snf