【问题标题】:tail recursive map over simple rosetree简单玫瑰树上的尾递归映射
【发布时间】:2021-08-18 11:05:28
【问题描述】:

我正在努力将非平凡函数映射为尾递归。

即使是简单的玫瑰树

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

但我错过了分支的难点

【问题讨论】:

    标签: f# tail-recursion


    【解决方案1】:

    如果您使用链接中的建议,则实现如下:

    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,将其包装回 Leaf 并应用延续。

    对于分支,我们生成了许多映射分支中子级的部分函数。我们利用 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]]
    

    顺便说一句,你想做什么?用数千个场景运行蒙特卡罗模拟?即使使用您的原始实现,我还没有遇到堆栈溢出错误。

    【讨论】:

    • 问题是 2 倍,a) 我不喜欢编写如果溢出的代码,我没有修复的技能,并且 b) 我可能正在建模可能非常大的树...但更紧迫的事情是能够在晚上睡觉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2011-07-24
    相关资源
    最近更新 更多