Question

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)))))))
Était-ce utile?

La solution 3

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.)

Autres conseils

No, although this example will be evaluated lazily (like any other function in Haskell), the behaviour doesn't depend on that. On finite lists it would behave the same way with eager evaluation. On infinite lists, of course, it would never terminate with eager evaluation, but lazy evaluation allows you to evaluate only as many list elements as you need.

If you post the code you're using to call the Scheme zipWith for the last example, maybe we can help see why that's behaving differently.

zipWith' (*) [1,2,3] [1..] would (have use of) evaluate lazily

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top