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の他の関数のように)怠惰に評価されますが、動作はそれに依存しません。有限リストでは、それは熱心な評価で同じように動作します。もちろん、無限リストでは、熱心な評価で終了することはありませんが、遅延評価では、必要な数のリスト要素のみを評価できます。

最後の例でSchemezipWithを呼び出すために使用しているコードを投稿すると、それが異なる動作をする理由を理解するのに役立つかもしれません。

于 2012-06-26T18:45:47.583 に答える
2

zipWith' (*) [1,2,3] [1..] 怠惰に評価する(使用する)

于 2012-06-27T09:48:05.227 に答える
2

私の元の投稿へのコメントにあるjberryman のリンク は、最も包括的な回答を提供します。返信してくれたすべての人に感謝します。

( edit-in: @newacct がコメントで言及しているように、部分適用は明示的なlambda構築で自明に達成され(lambda (x y) (zipWith * x y))ます。ラムダは Scheme では非常に基本的なものであり、そのためのマクロは必要ありません。)

于 2012-06-27T21:11:12.793 に答える