【问题标题】:Why Map.make.fold more like List.fold_right (which is non-tail-recursive)?为什么 Map.make.fold 更像 List.fold_right (非尾递归)?
【发布时间】:2011-07-13 08:40:51
【问题描述】:

关于 Ocaml 折叠的问题:您能解释一下为什么 Map.make.fold 的设计更像 List.fold_right 而不是 List.fold_left,请注意那个 List。 fold_right 不是tail_recursive?应该有 Map.make.fold_left 和 Map.make.fold_right 吧?

type of Map.make.fold 
val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b

type of List.fold_left    
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

type of List.fold_right
val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b

【问题讨论】:

    标签: map ocaml tail-recursion fold


    【解决方案1】:

    如果您查看 Map 的折叠操作的 documentation(f kN dN ... (f k1 d1 a)...),您会发现它实际上执行了左折叠(其中 left 是最小的键,而 right 是最大的关键)。

    对于 Map 或 Set,它是一棵二叉搜索树,它很容易双向遍历,不像(单链)列表,只能在一个方向遍历;所以在两个方向上进行尾递归折叠同样容易。

    至于参数的顺序,我想这只是一个设计决定。 Haskell 的列表折叠(foldlfoldr)以及 Haskell's Map's fold 在列表参数之前始终具有初始值参数。我认为一致性很好。 OCaml 的列表从不同方向折叠有不同的参数顺序(我想这可能是因为对于左折叠,您将初始参数放在左侧,并逐渐将其“折叠”到列表右侧;而对于右折叠,您将右侧的初始元素并逐渐将其折叠到列表的左侧;因此参数的位置与视觉上的动作一致。)显然 OCaml 的 Map 的折叠参数顺序与其右侧折叠相同。我认为这并不重要。

    至于有两个 Map 折叠,这可能有一些价值。 Haskell's Map 在 GHC 6.12 中引入了折叠的两个方向。以前,只有一个正确的折叠。不过,地图上大多数折叠的使用可能并不关心顺序。

    【讨论】:

      【解决方案2】:

      您的问题暗示函数中参数的顺序与它是否是尾递归有关,但事实并非如此。 List.fold_right 也可以与 List.fold_right 具有相同的签名,但这不会改变其实现。

      【讨论】:

        猜你喜欢
        • 2013-02-28
        • 1970-01-01
        • 2018-03-17
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多