7

私はHaskellチュートリアル(Learn You a Haskell)を読んでいました。このチュートリアルでは、怠惰は参照透過性とうまく調和すると著者は述べています。さらに読んだり検索したりしても、その理由はまだわかりません。参照透過性と怠惰の優れている点は理解していますが、それらが一緒になって私を悩ませていることに注意してください。

2つの組み合わせの特別な利点はありますか?

それとも、作者は、彼らが持っていて良かったと言いたかっただけで、それを曖昧に表現したのでしょうか?

4

3 に答える 3

11

本当に簡単です。非厳密な(たとえば遅延)評価は、タスクを延期できることを意味します。しかし、何かを延期するためには、今と同じ結果が後で得られることを確認する必要があります。これは参照透過性です。この命令型Javaコードを考えてみましょう。

long start = System.currentTimeMillis(); //get the start time
runBenchmarkFunction();
System.out.println("Run took " + (System.currentTimeMillis() - start) + " ms"); 

開始が必要なのは3行目だけなので、怠惰な言語は1行目の評価を延期します。したがって、結果は0(またはそれに非常に近い)になります。おそらくそれはあなたが望むものではありません。その問題の理由は、System.currentTimeMillisが参照透過性ではないためです。その場合、参照透過性のあるsinやlnのような「数学的な意味」の関数であれば、問題はありません。

于 2010-10-05T14:37:53.063 に答える
5

参照透過性とは、同じ入力が与えられた場合、関数が常に同じ出力を返すことを意味します。したがって、関数が怠惰であるか厳密であるかは問題ではありません。レイジー関数は、将来の未知の時間にその出力を計算しますが、参照透過性により、指定された入力に対して出力が常に同じになることが保証されます。

したがって、ある意味で、参照透過性は怠惰な関数の正確さを保証します。

于 2010-10-05T14:34:31.023 に答える
4

ジェネレーターを使用して無限シーケンスを遅延計算するこのPythonコードについて考えてみます。グローバル状態を使用しているため、参照透過性がありません。したがって、ジェネレーターの呼び出し元は、取得している結果が他のイベントの影響を受けていないことを確認できません。

foo = 0

def foo_sequence():
    global foo
    while True:
        foo += 1
        yield foo

>>> generator = foo_sequence()
>>> generator.next()
1
>>> generator.next()
2
>>> foo = 5
>>> generator.next()
6

この場合、呼び出し元は、このようなイベントが発生しないように、シーケンス全体をアトミックに生成することを好みます。したがって、参照透過性の欠如(この不自然な例では)は怠惰を魅力的にしません。

于 2010-10-05T14:44:37.653 に答える