This is the textbook zip function:
zip :: [a] -> [a] -> [(a,a)] zip [] _ = [] zip _ [] = [] zip (x:xs) (y:ys) = (x,y) : zip xs ys I asked on #haskell earlier wether "zip" could be implemented using "foldr" alone, no recursion, no pattern matching. After some thinking, we noticed the recursion could be eliminated using continuations:
zip' :: [a] -> [a] -> [(a,a)] zip' = foldr cons nil where cons h t (y:ys) = (h,y) : (t ys) cons h t [] = [] nil = const [] We are still left with pattern matching. After some more neuron toasting I came up with an incomplete answer that I thought was logical:
zip :: [a] -> [a] -> [a] zip a b = (zipper a) (zipper b) where zipper = foldr (\ x xs cont -> x : cont xs) (const []) It returns a flat list, but does the zipping. I was certain it made sense, but Haskell complained about the type. I proceeded to test it on a untyped lambda calculator, and it worked. Why can't Haskell accept my function?
The error is:
zip.hs:17:19: Occurs check: cannot construct the infinite type: t0 ~ (t0 -> [a]) -> [a] Expected type: a -> ((t0 -> [a]) -> [a]) -> (t0 -> [a]) -> [a] Actual type: a -> ((t0 -> [a]) -> [a]) -> (((t0 -> [a]) -> [a]) -> [a]) -> [a] Relevant bindings include b ∷ [a] (bound at zip.hs:17:7) a ∷ [a] (bound at zip.hs:17:5) zip ∷ [a] -> [a] -> [a] (bound at zip.hs:17:1) In the first argument of ‘foldr’, namely ‘cons’ In the expression: ((foldr cons nil a) (foldr cons nil b)) zip.hs:17:38: Occurs check: cannot construct the infinite type: t0 ~ (t0 -> [a]) -> [a] Expected type: a -> (t0 -> [a]) -> t0 -> [a] Actual type: a -> (t0 -> [a]) -> ((t0 -> [a]) -> [a]) -> [a] Relevant bindings include b ∷ [a] (bound at zip.hs:17:7) a ∷ [a] (bound at zip.hs:17:5) zip ∷ [a] -> [a] -> [a] (bound at zip.hs:17:1) In the first argument of ‘foldr’, namely ‘cons’ In the fourth argument of ‘foldr’, namely ‘(foldr cons nil b)’
(,)as a function, andheadandtailinstead of (y:ys) and maybe an if/else?