Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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' _ _ [] = []
like image 988
Filipe Nóbrega Avatar asked Jan 04 '18 19:01

Filipe Nóbrega


1 Answers

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
like image 87
Willem Van Onsem Avatar answered Oct 30 '22 23:10

Willem Van Onsem