为什么Map.make.fold更像List.fold_right(非尾递归)?

时间:2011-07-13 08:40:51

标签: map ocaml tail-recursion fold

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

2 个答案:

答案 0 :(得分:4)

如果您查看地图折叠所做的documentation (f kN dN ... (f k1 d1 a)...),您会看到它实际上执行了左折(左边是最小的键)而权利是最大的关键。)

对于一个二元搜索树的地图或集合,很容易在两个方向上遍历它,不像一个(单链接)列表,它只能在一个方向上遍历;因此,在两个方向上进行尾递归折叠也同样容易。

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

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

答案 1 :(得分:1)

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