Haskell 行动中的懒惰?(哈斯克尔)

Haskell 行动中的懒惰?(哈斯克尔),haskell,scheme,lazy-evaluation,higher-order-functions,partial-application,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],[

在学习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(见下文)。我用“简单”的例子来解释,但不是最后一个,这让我觉得哈斯克尔的懒惰可能会起作用

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

不,尽管这个例子将被惰性地计算(就像Haskell中的任何其他函数一样),但行为并不依赖于此。在有限的列表上,它的行为方式与热切的求值相同。当然,在无限列表上,它永远不会以急切求值结束,但惰性求值允许您只计算所需数量的列表元素

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

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

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


edit in:正如@newacct在评论中提到的,部分应用程序通过显式的
lambda
构造实现,
(lambda(xy)(zipWith*xy))
。lambda在Scheme中非常基本,我们不需要宏。)

不,这不是懒惰。它使用部分应用程序,这在Scheme中可能有点不寻常(或者不是,我对Scheme了解不多)。我认为Daniel Fischer是对的。显然,可以用宏@jberryman来模拟咖喱:我认为这个链接正是我所需要的。如果你能把这个作为一个答案,我很高兴给你信用@你不需要任何宏。手动执行部分应用程序并不难
(lambda(x y)(zipWith*x y))