3

Learn You a Haskell的第6章中,介绍了以下功能:

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

作者给出了几个我觉得很容易理解的例子。然后这个:

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

哪个输出[[3,4,6],[9,20,30],[10,12,12]]

这是懒惰评估的例子吗?我试图将 zipWith' 翻译成 Scheme(见下文)。我用“简单”的例子来工作,但不是最后一个,这让我认为 Haskell 的懒惰可能会有所作为。

(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)))))))
4

3 回答 3

5

不,虽然这个例子会被延迟评估(就像 Haskell 中的任何其他函数一样),但行为并不依赖于此。在有限列表上,它的行为与急切评估相同。当然,在无限列表上,它永远不会因急切求值而终止,但惰性求值允许您只求值所需数量的列表元素。

如果您发布用于调用最后一个示例的 Scheme zipWith 的代码,也许我们可以帮助您了解为什么它的行为不同。

于 2012-06-26T18:45:47.583 回答
2

zipWith' (*) [1,2,3] [1..] 会(使用)懒惰地评估

于 2012-06-27T09:48:05.227 回答
2

jberryman 对我的原始帖子的评论中的链接 提供了最全面的答案。感谢所有回复的人。

编辑:正如@newacct 在评论中提到的那样,通过显式lambda构造可以轻松实现部分应用,(lambda (x y) (zipWith * x y)). Lambda 在 Scheme 中是非常基本的,我们不需要宏。)

于 2012-06-27T21:11:12.793 回答