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)))))))
有帮助吗?

解决方案 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.)

其他提示

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top