Solution (source code)

= Solution

Use the usual left-to-right <pattern matching> order:

``
zip :: [a] -> [b] -> [(a,b)]
zip []     _      = []
zip _      []     = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
``

The result stops when either <list> ends, so its length on finite total inputs is the smaller input length. Elements remaining in the longer <list> are discarded.

Strictness is asymmetric. Writing the <bottom value> as $\bot$, \b[`zip` is strict in its first list but not uniformly strict in its second]: `zip undefined ys` is undefined, whereas `zip [] undefined = []`. With a nonempty first <list>, an undefined second <list> does make the result undefined. Neither pair component is forced merely to produce the outer result constructor: `zip [undefined] [undefined]` already has a defined outer cons and pair. This follows from ordered <pattern matching> and <lazy evaluation>, not from the behavior on total <lists> alone.<Haskell 2010 Language Report>[§3.17.2, ordered pattern matching; Chapter 9, zip in the Standard Prelude]{ref}