将运算符与 zipWithN 一起使用

发布于 2024-11-25 03:33:58 字数 370 浏览 0 评论 0原文

比如说,我们可以这样写:

zipWith (,) [1,2,3] [4,5,6]

如果我们想要元组 3 列表,我们可以写: zipWith3 (,,) [1,2,3] [4,5,6] [7,8,9]

我们还可以使用 zipWith4 (,,,) zipWith5(,,,,)等等。

现在,我想做同样的事情,但使用添加而不是逗号运算符。 有没有办法以同样简洁的方式定义它,而不是像

zipWith3 (\a b c -> a + b + c) [1, 2, 3] [4, 5, 6] [7, 8, 9]

提前感谢任何答案那样使用 lambda。

Say, we can write something like this:

zipWith (,) [1,2,3] [4,5,6]

If we want to tuple 3 list, we can write:
zipWith3 (,,) [1,2,3] [4,5,6] [7,8,9]

We can also use zipWith4 (,,,) zipWith5(,,,,) and so on.

Now, I want to do the same thing, but using adding instead comma operator.
Is there any way to define it in the same terse way, not using lambdas like in

zipWith3 (\a b c -> a + b + c) [1, 2, 3] [4, 5, 6] [7, 8, 9]

Thanks in advance for any answer.

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

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

发布评论

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

评论(4

日暮斜阳 2024-12-02 03:33:58

听起来您想要 \abc -> 的“无点”样式代码a + b + c。众所周知,一般来说, \abc -> a + b + c 通常比指向自由代码更可取,因为四个星期后当您发现错误时阅读起来要容易得多。

有一篇关于无点编程的 wiki 文章(来源)。

您还可以安装 pointfree 软件包,它可以让您在命令行上解决这些问题。例如,

$ pointfree '\x y z -> x + y + z'
((+) .) . (+)

所以 ((+) .) 。 (+) 是无点版本(x、y 和 z 是“点”,以防您想知道,不,这与几何无关)。如果您愿意,可以使用该定义,但大多数人会查看您的代码,并且不知道那幅看起来很有趣的 ASCII 艺术作品应该做什么。其中一半人会用铅笔和纸算出来,但这不是原始的 \xyz -> x + y + z 这么舒服?

提示:如果您需要弄清楚某些 point free 代码的作用,请查看类型:

Prelude> :t ((+) .) . (+)
((+) .) . (+) :: (Num a) => a -> a -> a -> a

或者您可以安装 pointful 包,它大约与 pointfree 相反。

摘要:欢迎来到积分免费编程的世界,请谨慎操作,以免您的代码不可读。

It sounds like you want "point free" style code for \a b c -> a + b + c. Let it be known that, in general, \a b c -> a + b + c is often preferable to point free code because it is much easier to read four weeks later when you found a bug.

There is a wiki article on point free programming (source).

You can also install the pointfree package, which lets you solve these problems on the command line. For example,

$ pointfree '\x y z -> x + y + z'
((+) .) . (+)

So ((+) .) . (+) is the point free version (x, y, and z are the "points", in case you were wondering, and no, this has nothing to do with geometry). You can use that definition if you'd like, but most people will look at your code and will have no idea what that funny looking piece of ASCII art is supposed to do. Half of them will work it out with pencil and paper, but isn't the original \x y z -> x + y + z so much easier on the eyes?

Hint: If you ever need to figure out what some point free code does, look at the type:

Prelude> :t ((+) .) . (+)
((+) .) . (+) :: (Num a) => a -> a -> a -> a

Or you can install the pointful package, which is approximately the inverse of pointfree.

Summary: Welcome to the world of points free programming, proceed with caution lest your code be unreadable.

怕倦 2024-12-02 03:33:58

另一种选择:应用函子。事实上,Control.Applicative 包含新类型定义 ZipList (因为有几种可能的定义列表类型的 Applicative )可以像这样使用:

import Control.Applicative 

getZipList $ (,,) <
gt; ZipList [1,2,3] <*> ZipList [4,5,6] <*> ZipList [7,8,9]

或像这样(对于几个 (+) ):

getZipList $ (+) <
gt; ((+) <
gt; ZipList [1,2,3] <*> ZipList [4,5,6]) <*> ZipList [7,8,9]

尽管对于这个特定的情况使用 applicative 函子可能没有多大意义问题,但它们仍然提供了非常强大的抽象/机制来解决类似类型的任务,因此它们绝对值得学习(例如我们可以摆脱 zipWith3、zipWith4 ...等)。

Another option: applicative functors. In fact, Control.Applicative contains newtype definition ZipList (since there are several possible definitions of Applicative for list type) which can be used like that:

import Control.Applicative 

getZipList $ (,,) <
gt; ZipList [1,2,3] <*> ZipList [4,5,6] <*> ZipList [7,8,9]

or like that (for a couple of (+)'s):

getZipList $ (+) <
gt; ((+) <
gt; ZipList [1,2,3] <*> ZipList [4,5,6]) <*> ZipList [7,8,9]

Even though it probably doesn't make much sense to use applicative functors for this particular problem, they nevertheless provide very powerful abstraction/mechanism for solving similar kind of tasks, so they are definitely worth learning (e.g. we can get rid of zipWith3, zipWith4 ... etc).

潦草背影 2024-12-02 03:33:58

绕过 zipWith3,你可以这样做:

import Data.List (transpose)
map sum $ transpose [[1,2,3],[4,5,6],[7,8,9]]

虽然使用 zipWith3 将输出剪切到最短列表,但这不会,即对于 [[1,2],[3]] 它给出 [4,2]。

Bypassing zipWith3, you can do:

import Data.List (transpose)
map sum $ transpose [[1,2,3],[4,5,6],[7,8,9]]

While using zipWith3 cuts the output to shortest list, this doesn't, i.e. for [[1,2],[3]] it gives [4,2].

春庭雪 2024-12-02 03:33:58

我认为没有 lamda 你就无法写它。事实上,zipWith3 需要一个带有 3 个参数的函数作为第一个参数,而 (+) 仅需要两个参数。因此,您需要定义“一个带有 3 个参数的加函数”,这正是您的 lambda 所做的。

另一种选择是:

foldr1 (zipWith (+)) [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]

我不知道上面的内容是否比

zipWith3 (\a b c -> a + b + c) [1, 2, 3] [4, 5, 6] [7, 8, 9]

I think you cannot write it without lamda. In fact zipWith3 requires as first parameter a function that takes 3 parameters, and (+) takes only two. So, you need to define "a plus function taking 3 parameters", that is exactly what your lambda does.

An alternative is:

foldr1 (zipWith (+)) [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]

I don't know if the above is terser than

zipWith3 (\a b c -> a + b + c) [1, 2, 3] [4, 5, 6] [7, 8, 9]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文