95

我最近两次重构代码以更改参数的顺序,因为有太多的代码喜欢flip\x -> foo bar x 42正在发生黑客攻击。

在设计函数签名时,哪些原则可以帮助我充分利用柯里化?

4

3 回答 3

112

对于容易支持柯里化和部分应用的语言,有一系列令人信服的论点,最初来自 Chris Okasaki:

  • 将数据结构作为最后一个参数

为什么?然后,您可以很好地对数据进行操作。例如insert 1 $ insert 2 $ insert 3 $ s。这也有助于state 上的功能

诸如“容器”之类的标准库遵循此约定

有时会给出替代参数以将数据结构放在首位,因此可以将其关闭,从而在静态结构(例如查找)上产生更简洁的函数。然而,广泛的共识似乎是这不是一个胜利,特别是因为它把你推向大量括号内的代码。

  • 把变化最大的论点放在最后

对于递归函数,通常将变化最大的参数(例如累加器)作为最后一个参数,而将变化最小的参数(例如函数参数)放在开头。这与数据结构最后一种风格很好地组合在一起。


在他的 Edison 库(同样是另一个数据结构库)中给出了 Okasaki 视图的摘要:

  • 部分应用:更可能是静态的参数通常出现在其他参数之前,以便于部分应用。
  • 集合出现在最后:在操作查询单个集合或修改现有集合的所有情况下,集合参数将最后出现。这是 Haskell 数据结构库的事实上的标准,并为 API 提供了一定程度的一致性。
  • Most usual order: where an operation represents a well-known mathematical function on more than one datastructure, the arguments are chosen to match the most usual argument order for the function.
于 2011-05-02T22:38:13.790 回答
11

首先放置您最有可能重用的参数。函数参数就是一个很好的例子。您更可能想要map f超过两个不同的列表,而不是想要在同一个列表上映射许多不同的功能。

于 2011-05-02T22:35:56.940 回答
3

I tend to do what you did, pick some order that seems good and then refactor if it turns out that another order is better. The order depends a lot on how you are going to use the function (naturally).

于 2011-05-03T11:56:43.850 回答