为什么foldBack的签名与F#中的fold有如此大的不同?

为什么foldBack的签名与F#中的fold有如此大的不同?,f#,F#,至少有两件事我不明白: 从左侧折叠到右侧折叠的重构不仅需要在签名上进行大量更改,而且需要在每个地方进行大量更改,这取决于文件夹功能 如果不翻转参数,就无法根据列表链接它 List.foldBack:('T->'State->'State)->'T List->'State->'State List.fold:('State->'T->'State)->'State->'T List->'State 与折叠相比,为什么有人在折叠的签名中把所有参数都倒过来?这只是一个有用的助记符,可以帮助程序员

至少有两件事我不明白:

  • 从左侧折叠到右侧折叠的重构不仅需要在签名上进行大量更改,而且需要在每个地方进行大量更改,这取决于文件夹功能
  • 如果不翻转参数,就无法根据列表链接它
List.foldBack:('T->'State->'State)->'T List->'State->'State

List.fold:('State->'T->'State)->'State->'T List->'State


折叠
相比,为什么有人在
折叠
的签名中把所有参数都倒过来?

这只是一个有用的助记符,可以帮助程序员记住列表是如何迭代的。想象一下,你的清单是从左开始,右结束的<代码>折叠从左侧的初始状态开始,然后累积到右侧的状态<代码>折叠执行相反的操作,它从右侧的初始状态开始,然后返回到左侧的列表

这无疑显示了F#的OCaml遗产,因为其他一些函数式语言(Haskell、Scala、ML)将列表作为最后一个参数,以允许更常见的部分应用程序场景

如果我真的需要一个类似于折叠的
版本,我会定义自己的助手函数:

module List = 
  let foldBack' f acc lst =
    let flip f a b = f b a
    List.foldBack (flip f) lst acc

这是F#在OCaml的起源的遗迹。您可以看到,
List.fold
List.foldBack
的F#函数签名在中是相同的(分别称为
List.fold#left
List.fold#right
)。而且,如果不打破大量的代码,它是永远不会改变的。我认为,一旦你对每个人的行为有了正确的思维模式,签名就会自然而然地读出。同样在懒惰的语言中,也有很好的理由让这些人分开。但我认为这是一个有效的问题。保留列表作为最后一个参数,以考虑更常见的部分应用场景。当涉及到F#中的折叠时,情况并非如此。是的,他是这么说的。