为什么Map.make.fold更像List.fold\u right(这是非尾部递归的)?

为什么Map.make.fold更像List.fold\u right(这是非尾部递归的)?,map,ocaml,tail-recursion,fold,Map,Ocaml,Tail Recursion,Fold,关于Ocaml折叠的天真问题:你能解释一下为什么Map.make.fold设计得更像List.fold_right而不是List.fold_left,注意到了这个列表吗。右折不是尾部递归吗?应该有Map.make.fold\u左和Map.make.fold\u右 type of Map.make.fold val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b type of List.fold_lef

关于Ocaml折叠的天真问题:你能解释一下为什么Map.make.fold设计得更像List.fold_right而不是List.fold_left,注意到了这个列表吗。右折不是尾部递归吗?应该有Map.make.fold\u左和Map.make.fold\u右

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
如果您查看地图折叠的作用:
(f kN dN…(f k1 d1 a)…)
,您将看到它实际上执行左折叠(其中左键是最小的键,右键是最大的键)

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

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


至于有两个贴图折叠,可能有一些价值。Haskell的地图在GHC6.12中介绍了折叠的两个方向。以前,只有一个右褶皱。不过,大多数在映射上使用fold可能并不关心顺序。

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