Search code examples
haskellzipwith

Using zip in conjunction with zipWith in Haskell


I'm currently learning Haskell, and I am stuck with the following conundrum. What is wrong with the following construction?:

zip [1,2,3] [4,5,6]
Result: [(1,4),(2,5),(3,6)]

zipWith (+) [1,2,3] [4,5,6]
Result: [5,7,9]

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

Result: <interactive>:22:1: error:
    • No instance for (Num [()]) arising from a use of ‘it’
    • In the first argument of ‘print’, namely ‘it’
      In a stmt of an interactive GHCi command: print it

Expected Result: [(1,4),(2,5),(3,6)]

What am I missing?


Solution

  • in short: zip is applied to the elements of the lists, not the entire lists.

    zip is not a sensical function to combine two elements that are not lists. Indeed, zip has type zip :: [a] -> [b] -> [(a, b)] [Hackage]. It thus takes two lists and creates 2-tuples with these lists.

    This means that zipWith will work with zip as function if we have a list of lists:

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

    here the outer zipWith thus zips the outer structures, and zip will be called on zip [1] [4] and zip [2, 3] [5, 6] to produce [(1, 4)] and [(2, 5), (3, 6)] respectively.

    zip is a shortcut for:

    zip = zipWith (,)
    

    indeed, (,) :: a -> b -> (a, b) is a data constructor, and therefore also a function that takes two elements, and produces a 2-tuple of these two elements, so:

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

    will zip the two lists together.