2

关于 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
4

2 回答 2

4

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

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

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

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

于 2011-07-13T10:36:34.600 回答
1

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

于 2011-07-13T19:59:25.963 回答