这是展平二叉查找树的一种方法。它的问题是当它构建的大函数最终应用于[]时,堆栈溢出。我想知道是否有合理的方法修复这段代码片段而不完全改变它的工作方式。例如,如果构建一个自定义作曲家来构建一个函数树,然后使用一个显式堆栈来评估它们(因为问题已经是将一棵树展平了),那么这将无济于事。将多个函数组合在一起时溢出堆栈
let flatten_k t =
let rec f t (k:(list<'a>->list<'a>)->list<'a>) =
match t with
| Leaf ->
k (fun xs -> xs)
| Bin (l,x,r) ->
f l (fun fl -> f r (fun fr -> k (fl << (fun xs -> x::xs) << fr)))
f t (fun g -> g [])
这可能是因为它是更好地思考一个简单的例子,虽然它可能是难以令人信服地证明就可以了修复(因为它几乎为零,但至少它表明函数组合做溢出堆栈):
let test_composition() =
let mutable f = id
for i=0 to 1000000 do
f <- id << f // >> works fine for me
printf "Functions return %d" (f 123)
此外,这个问题不是关于如何扁化一棵树。我可以很容易地做到这一点,或以任何数量的纯粹必要的方式。我想知道基于积累大功能的方法是否可以用于解决这个特定问题。非常感谢。
let flatten t =
let rec f t acc cont =
match t with
| Leaf ->
cont acc
| Bin (l, x, r) ->
f r acc (fun rs -> f l (x::rs) cont)
f t [] id
你正在编译优化吗?什么是你的运行时间?操作系统? –
我没有使用优化功能,因为我不想要一个有时能够运行,有时不能运行的解决方案。然而,我正在生成尾巴呼叫。我在Windows下使用.net。我知道在Mono下,tail-calls没有正确实现,但这不是问题。 – jeremiah