Search code examples
haskellschemelazy-evaluationhigher-order-functionspartial-application

laziness in action? (Haskell)


In chapter 6 of Learn You a Haskell, the following function is introduced:

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

The author gives a couple examples of its use which I found easy enough to follow. Then this one:

ghci> zipWith' (zipWith' (*)) [[1,2,3],[3,5,6],[2,3,4]] [[3,2,2],[3,4,5],[5,4,3]]

Which outputs [[3,4,6],[9,20,30],[10,12,12]]

Is this an example of lazy evaluation? I tried to translate zipWith' into Scheme (see below). I got it working with the "easy" examples, but not the last one, which makes me think that Haskell's laziness might be making the difference.

(define zipWith
  (lambda (f listA listB)
    (cond
      ((null? listA) (quote ()))
      ((null? listB) (quote ()))
      (else (cons (f (car listA) (car listB)) (zipWith f (cdr listA) (cdr listB)))))))

Solution

  • jberryman's link in a comment to my original post provides the most comprehensive answer. Thanks to all who replied.

    (edit-in: as @newacct mentions in the comments, partial application is trivially achieved with explicit lambda construction, (lambda (x y) (zipWith * x y)). Lambdas are very basic in Scheme, we don't need macros for that.)