简单玫瑰树上的尾递归映射
tail recursive map over simple rosetree
我正在努力将非平凡函数映射为尾递归。
即使是简单的玫瑰树
type Tree<'a> =
| Leaf of 'a
| Branch of List<Tree<'a>>
有地图
let rec map : ('a -> 'b) -> Tree<'a> -> Tree<'b> =
fun f ->
function
| Leaf a ->
f a
|> Leaf
| Branch xs ->
xs
|> List.map (map f)
|> Branch
(更不用说绑定了)
使这个尾递归看起来很痛苦,我看过 FSharpx 之类的例子,但它们不是尾递归的。
我找到了这个
https://www.gresearch.co.uk/article/advanced-recursion-techniques-in-f/
但是基于连续性的最终示例的飞跃似乎完全针对他们的示例(最大),我似乎无法理解它。
是否有这个非常规范的示例的示例实现?
所以简单的一点就是这样
let map2 : ('a -> 'b) -> Tree<'a> -> Tree<'b> =
fun f ta ->
let rec innerMap : Tree<'a> -> (Tree<'b> -> Tree<'b>) -> Tree<'b> =
fun ta cont ->
match ta with
| Leaf a ->
f a |> Leaf |> cont
innerMap ta id
但我错过了分支的难点
如果您使用 link 中的建议,实施如下:
let rec mapB : ('a -> 'b) -> Tree<'a> -> (Tree<'b>-> Tree<'b>) -> Tree<'b> =
fun f ta k ->
match ta with
| Leaf a -> k (Leaf (f a))
| Branch ys ->
let continuations = ys |> List.map (mapB f)
let final (list:List<Tree<'b>>) = k (Branch list)
Continuation.sequence continuations final
如您所见,叶子的情况很简单:应用 F,将其包装回叶子并应用延续。
对于Branch,我们生成了一些偏函数来映射分支中的children。我们利用 Continuation.sequence 为我们执行这些部分功能。然后我们获取结果,将其包装在一个分支中并应用(最终)延续。
基本测试:
let t = Branch ([Leaf 3; Leaf 4;Leaf 5;Branch([Leaf 6])])
let t4 = mapB (fun x->x+1) t id
printfn "%A" t4
产量
Branch [Leaf 4; Leaf 5; Leaf 6; Branch [Leaf 7]]
顺便说一句,你想做什么? 运行 具有数千种场景的蒙特卡洛模拟?我还没有 运行 进入堆栈溢出错误,即使你的原始实现也是如此。
我正在努力将非平凡函数映射为尾递归。
即使是简单的玫瑰树
type Tree<'a> =
| Leaf of 'a
| Branch of List<Tree<'a>>
有地图
let rec map : ('a -> 'b) -> Tree<'a> -> Tree<'b> =
fun f ->
function
| Leaf a ->
f a
|> Leaf
| Branch xs ->
xs
|> List.map (map f)
|> Branch
(更不用说绑定了)
使这个尾递归看起来很痛苦,我看过 FSharpx 之类的例子,但它们不是尾递归的。 我找到了这个
https://www.gresearch.co.uk/article/advanced-recursion-techniques-in-f/
但是基于连续性的最终示例的飞跃似乎完全针对他们的示例(最大),我似乎无法理解它。
是否有这个非常规范的示例的示例实现?
所以简单的一点就是这样
let map2 : ('a -> 'b) -> Tree<'a> -> Tree<'b> =
fun f ta ->
let rec innerMap : Tree<'a> -> (Tree<'b> -> Tree<'b>) -> Tree<'b> =
fun ta cont ->
match ta with
| Leaf a ->
f a |> Leaf |> cont
innerMap ta id
但我错过了分支的难点
如果您使用 link 中的建议,实施如下:
let rec mapB : ('a -> 'b) -> Tree<'a> -> (Tree<'b>-> Tree<'b>) -> Tree<'b> =
fun f ta k ->
match ta with
| Leaf a -> k (Leaf (f a))
| Branch ys ->
let continuations = ys |> List.map (mapB f)
let final (list:List<Tree<'b>>) = k (Branch list)
Continuation.sequence continuations final
如您所见,叶子的情况很简单:应用 F,将其包装回叶子并应用延续。
对于Branch,我们生成了一些偏函数来映射分支中的children。我们利用 Continuation.sequence 为我们执行这些部分功能。然后我们获取结果,将其包装在一个分支中并应用(最终)延续。
基本测试:
let t = Branch ([Leaf 3; Leaf 4;Leaf 5;Branch([Leaf 6])])
let t4 = mapB (fun x->x+1) t id
printfn "%A" t4
产量
Branch [Leaf 4; Leaf 5; Leaf 6; Branch [Leaf 7]]
顺便说一句,你想做什么? 运行 具有数千种场景的蒙特卡洛模拟?我还没有 运行 进入堆栈溢出错误,即使你的原始实现也是如此。