Haskell 中的柯里化无序

发布于 2024-09-24 19:19:24 字数 335 浏览 0 评论 0原文

Haskell 中是否有一种优雅的符号来对函数的参数进行乱序柯里化?

例如,如果您希望用 2 除以列表的所有元素,您可以编写

map ((/) 2) [1,2,3,4,5]

但是,要除以列表的所有元素,您似乎需要定义一个匿名函数

map (\x -> x/2) [1,2,3,4,5]

在更复杂的情况下,匿名函数很快就会变得难以使用。我知道在这种情况下 map ((*) 0.5) [1,2,3,4,5] 可以正常工作,但我有兴趣知道 Haskell 是否有更优雅的方法来柯里化函数的参数出了故障?

Is there an elegant notation for Currying the arguments of a function out of order in Haskell?

For example, if you wish to divide 2 by all elements of a list, you can write

map ((/) 2) [1,2,3,4,5]

However to divide all elements of a list it seems you need to define an anonymous function

map (\x -> x/2) [1,2,3,4,5]

Anonymous functions quickly become unwieldy in more complex cases. I'm aware that in this case map ((*) 0.5) [1,2,3,4,5] would work fine, but I'm interested to know if Haskell has a more elegant way of currying arguments of a function out of order?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枕梦 2024-10-01 19:19:24

在这种特殊情况下:

Prelude> map (/2) [1..5]
[0.5,1.0,1.5,2.0,2.5]

您不仅可以将中缀运算符用作普通前缀函数,还可以部分以中缀形式应用它。同样,第一个示例最好写成 map (2/) [1..5]

另外,还有 flip ,虽然不太优雅,但仍然是最好的适用于普通函数的选项(当您不想通过反引号将它们变成中缀时):

Prelude> let div' = (/)
Prelude> div' 2 1
2.0
Prelude> flip div' 2 1
0.5

In this particular case:

Prelude> map (/2) [1..5]
[0.5,1.0,1.5,2.0,2.5]

Not only you can use an infix operator as ordinary prefix function, you can also partially apply it in infix form. Likewise, the first example would better be written as map (2/) [1..5]

Also, there's flip which is not quite as elegant, but still the best option available for ordinary functions (when you don't want to turn them into infix via backticks):

Prelude> let div' = (/)
Prelude> div' 2 1
2.0
Prelude> flip div' 2 1
0.5
巾帼英雄 2024-10-01 19:19:24

对于第二个参数,lambda 是不必要的,只需使用如下形式:

map (/2) [1..5]

(/2) 形式仅表示您想要访问运算符的第二个参数。也可以使用第一个参数(2/)。这称为部分,并且是一个非常有用的技巧,不仅在代码高尔夫中。您还可以在前缀函数中使用它,如果您在中缀中使用它们:

map (`div` 2) [1..5]

在更困难的情况下,例如 3 个或更多参数,您应该使用 lambda,因为它在大多数情况下变得更具可读性。

For your second one, the lambda is unnecessary, just use like:

map (/2) [1..5]

The form (/2) simply means, that you want to access the second param of an operator. It is also possible with the first argument (2/). This is called a section, and is a really useful hack, not only in code golf. You can also use it in prefix functions, if you use them infix:

map (`div` 2) [1..5]

In more difficult cases, like 3 or more arguments, you're supposed to use lambdas, as it becomes more readable most times.

耶耶耶 2024-10-01 19:19:24

我认为您正在寻找一种通用的解决方案,例如方案中的cut。正确的?

flip 函数可以反转函数的前 2 个参数。可能还有其他函数执行类似的任务(我还不太擅长 Haskell...)。

I think you are looking for a generalized solution, like the cut in scheme. Right?

There is the flip function that reverse the first 2 arguments of a function. There may be other functions doing a similar task (I'm not too good at Haskell... yet).

世界等同你 2024-10-01 19:19:24

我最近遇到了非常相似的问题 ,除了使用辅助函数来完成它之外,我无法找到一个优雅的解决方案:

dbfunc f b c = (\a -> liftIO $ f a b c)
deleteAllRows = do
  ask >>= dbfunc run "delete from t1" []

至少这种模式在 HDBC 中足够常见,以至于 dbfunc 是可重用的。

I encountered a very similar issue myself recently, and I wasn't able to find an elegant solution other than using a helper function to do it:

dbfunc f b c = (\a -> liftIO $ f a b c)
deleteAllRows = do
  ask >>= dbfunc run "delete from t1" []

At least this pattern is common enough in HDBC that dbfunc is reusable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文