Using statements with zipWithN

Say we can write something like this:

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

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

We can also use zipWith4 (,,,) zipWith5(,,,,) , etc.

Now I want to do the same, but by adding a comma operator instead. Is there a way to define it in the same way without using lambdas, as in

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

Thanks in advance for any response.

+4
source share
4 answers

It looks like you need a dot-free style code for \abc -> a + b + c . Let us know that in the general case \abc -> a + b + c often preferable to specify a free code, because it is easier to read four weeks later when you find an error.

There is a wiki article on programming without reservation ( source ).

You can also install the pointfree package, which solves these problems on the command line. For instance,

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

So ((+) .) . (+) ((+) .) . (+) is a point free version (x, y and z are “points”, in case you are interested, and no, this has nothing to do with geometry). You can use this definition if you want, but most people will look at your code and will not know what this funny piece of ASCII art should do. Half of them will work with pencil and paper, but is it not so original \xyz -> x + y + z in front of our eyes?

Hint: if you ever need to find out what some free code does, look at the type:

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

Or you can install the pointful package, which is roughly equal to the inverse of the pointfree value.

Summary: Welcome to the world of free programming programs, be careful that your code is unreadable.

+12
source

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

 import Control.Applicative getZipList $ (,,) <$> ZipList [1,2,3] <*> ZipList [4,5,6] <*> ZipList [7,8,9] 

or the like (for a pair (+)):

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

Although it probably doesn't make sense to use applicative functors for this particular problem, they nevertheless provide a very powerful abstraction / mechanism for solving such problems, so they certainly deserve to be studied (for example, we can get rid of zipWith3, zipWith4 ... etc.).

+7
source

Bypassing zipWith3 you can do:

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

When using zipWith3, it cuts the output to the shortest list, this is not so, that is, for [[1,2], [3]] it gives [4,2].

+4
source

I think you can’t write it without llamas. In fact, zipWith3 requires as a first parameter a function that takes 3 parameters, and (+) only takes two. So you need to define a “plus function with three parameters”, this is exactly what your lambda does.

Alternative is

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

I don't know if this is higher than

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

All Articles