Filipe Nóbrega
Filipe Nóbrega

Reputation: 667

Haskell - My own zip3 function

Is there a better way to re-create this function? It compiles fine.

This is what I have:

zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3' [] _ _ = []
zip3' _ [] _ = []
zip3' _ _ [] = []
zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs

I'm just wondering if there is a better way to summarize this:

zip3' [] _ _ = []
zip3' _ [] _ = []
zip3' _ _ [] = []

Upvotes: 9

Views: 1270

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476719

It works fine. If you want to make the program shorter, you can write:

zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs
zip3' _      _      _ = []

Since the first line will only fail to fire if there is at least one of the three lists that is not (_:_) (so []). But this is sometimes seen as an anti-pattern, since in a very unlike event that one adds a constructor to the list data type, this might end up with an empty list (whereas in that case, we perhaps better get an error). I agree that for lists this is close to impossible: a lot of libraries and programs would no longer work. But in general it is not uncommon that you for instance design a data type, and later change your mind and add an extra constructor.

If we inspect the source code of zip3 :: [a] -> [b] -> [c] -> [(a,b,c)], then we see it is implemented that way [source]:

zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
-- Specification
-- zip3 =  zipWith3 (,,)
zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs
zip3 _      _      _      = []

For some reason zip itself is implemented in the "question" style [source]:

zip :: [a] -> [b] -> [(a,b)]
zip []     _bs    = []
zip _as    []     = []
zip (a:as) (b:bs) = (a,b) : zip as bs

Upvotes: 16

Silvio Mayolo
Silvio Mayolo

Reputation: 70287

There's nothing inherently wrong with your approach, but you can collapse the first three cases into a catch-all at the end.

zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs
zip3' _ _ _ = []

In fact, this is how GHC does it.

Upvotes: 6

Related Questions