如何将第二个参数传递给带有 3 个参数的 Haskell 函数?

Pen*_*gHX 4 haskell currying

我现在正在学习 Haskell,我对此非常好奇。例如:

minus :: Int -> Int -> Int -> Int
minus x y z = x - y - z
Run Code Online (Sandbox Code Playgroud)

如果我想先将 y 而不是 x 传递给函数 [minus] 怎么办?我想要一个函数 [minus x 5 z] 我不想要这个

minusy10 x z = minus x 10 z
Run Code Online (Sandbox Code Playgroud)

如果我必须定义一个新函数来实现这一点,我觉得它失去了一些“Haskell 优雅”。

Dan*_*ner 12

你的minus10做法非常惯用;通常它被绑定在一个where子句中,这样它就不会扰乱顶级 API。flip minus 10也是(`minus` 10)常见的选择。这两个选择仅适用于填写第二个参数;更一般地,为了填充第n个参数,lambda 可以更好地泛化,如 中所示\x -> minus x 10


Enr*_*lis 5

从根本上来说,您是在问如何minusy10在不明确命名其参数的情况下进行编写。而且,显然,您也不希望通过将它们移至 lambda 来进行作弊:

minusy10 = \x z -> minus x 10 z
Run Code Online (Sandbox Code Playgroud)

你想做的是以minusy10“无点风格”写作。

在这种情况下,这很容易完成,正如其他答案中所建议的那样,但在更一般的情况下,您可能需要参考pointfree.io,这将为您提供一种编写函数的可能方法(但可能存在更多方法)以无点风格。

在这种特定情况下,它提出了解决方案flip minus 10(这可能不是最具可读性的解决方案;相反,我称之为(`minus` 10)更具可读性)。

另一方面,并​​参考你的感觉

如果我必须定义一个新函数来实现这一点,我觉得它失去了一些“Haskell 优雅”

值得考虑的是,如果过度使用,无点样式可能会降低可读性。事实上,即使是非常简单的函数,您可以在眨眼之间阅读和理解,例如这个,

f x y = x + y*y
Run Code Online (Sandbox Code Playgroud)

无点风格可能会导致与可读相反的结果(实际上甚至更长!):

f = (. join (*)) . (+)
Run Code Online (Sandbox Code Playgroud)

所以我想说,无点风格和“全点”(?)风格之间存在平衡。这个平衡在哪里?在我看来,应该以最大可读性为目标,这与“可解析性”不同。

我的意思是

subtract2 x = x - 2
Run Code Online (Sandbox Code Playgroud)

很容易解析,也很容易阅读,但是

subtract2 = (-2)
Run Code Online (Sandbox Code Playgroud)

甚至更容易阅读。

在你原来的例子中,无点形式(`minus` 10)是相当可读的(但我实际上会质疑你给的名字minus,这让我想到一个类似二进制(-)的函数,而它是三元的)。