关于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
答案 0 :(得分:4)
如果您查看地图折叠所做的documentation :(f kN dN ... (f k1 d1 a)...)
,您会看到它实际上执行了左折(左边是最小的键)而权利是最大的关键。)
对于一个二元搜索树的地图或集合,很容易在两个方向上遍历它,不像一个(单链接)列表,它只能在一个方向上遍历;因此,在两个方向上进行尾递归折叠也同样容易。
至于论证的顺序,我想这只是一个设计决定。 Haskell的列表折叠(foldl
和foldr
)以及Haskell's Map's fold
在list参数之前始终具有初始值参数。我认为一致性很好。 OCaml的列表折叠从不同的方向有不同的参数顺序(我想这可能是因为对于左侧折叠,您将初始参数放在左侧,渐进式“折叠”它在列表的右侧;而对于右侧折叠,您放置右侧的初始元素并逐渐将其折叠在列表上;因此参数的放置与视觉上的动作一致。)显然,OCaml的Map的fold的参数顺序与其右侧折叠相同。我认为这不重要。
至于有两个Map折叠,可能有一些价值。 Haskell的Map在GHC 6.12中介绍了两种折叠方向。以前,只有一个正确的折叠。大多数在地图上使用折叠可能并不关心顺序。
答案 1 :(得分:1)
你的问题暗示函数中参数的顺序与它是否是尾递归有关,但事实并非如此。 List.fold_right
也可以与List.fold_right
具有相同的签名,但这不会改变其实施。