懒惰在行动? (Haskell的)

时间:2012-06-26 18:40:19

标签: haskell scheme lazy-evaluation higher-order-functions partial-application

了解你的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)))))))

3 个答案:

答案 0 :(得分:5)

不,虽然这个例子将被懒惰地评估(就像Haskell中的任何其他函数一样),但行为并不依赖于此。在有限列表上,它会以热切的评估方式表现出相同的行为。当然,在无限列表中,它永远不会以急切的评估结束,但是懒惰的评估允许您只根据需要评估列表元素。

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

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

编辑: ,因为@newacct在评论中提及,部分应用程序通过明确的lambda构造(lambda (x y) (zipWith * x y))轻松实现。 Lambdas在Scheme中非常基本,我们不需要需要宏。)