Почему лень хорошо сочетается с прозрачностью ссылок? - PullRequest
6 голосов
/ 05 октября 2010

Я читал учебник по Haskell (Learn You a Haskell), в котором автор сказал, что лень хорошо сочетается с прозрачностью ссылок. После дополнительного чтения и некоторых поисков я все еще не понимаю, почему. Обратите внимание, что я понимаю, что хорошего в ссылочной прозрачности и лени, но меня беспокоит их вместе.

Есть ли какая-то особая польза от комбинации двух?

Или, может быть, автор просто хотел сказать, что они оба хороши, и выразил это неоднозначно?

Ответы [ 3 ]

11 голосов
/ 05 октября 2010

Это действительно легко.Нестрогая (например, ленивая) оценка означает, что задачи могут быть отложены.Но для того, чтобы что-то отложить, вам лучше быть уверенным, что вы получите позже тот же результат, что и сейчас, и это прозрачность ссылок.Рассмотрим следующий императивный код Java:

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

Теперь ленивый язык откладывает оценку первой строки, потому что запуск необходим только в третьей строке.Таким образом, результат будет 0 (или очень близко к нему).Вероятно, это не то, что вы хотите.Причиной этой проблемы может быть то, что System.currentTimeMillis не ссылочно-прозрачный.В этом случае у вас не возникло бы никаких проблем, если бы это была функция в «математическом смысле», такая как sin или ln, которые являются ссылочно прозрачными.

5 голосов
/ 05 октября 2010

Ссылочная прозрачность означает, что функция всегда будет возвращать один и тот же вывод при одинаковом вводе.Так что если не имеет значения, если функция ленива или строгая.Ленивая функция вычислит свой вывод в какое-то неизвестное время в будущем, но из-за ссылочной прозрачности вам гарантировано, что выходные данные всегда будут одинаковыми для заданных входных данных.

Таким образом, ссылочная прозрачность в некотором смысле гарантирует правильностьленивые функции.

4 голосов
/ 05 октября 2010

Рассмотрим этот код 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

В этомВ этом случае вызывающая сторона предпочла бы генерировать всю последовательность атомарно, чтобы предотвратить такие события.Следовательно, отсутствие ссылочной прозрачности (в этом надуманном примере) делает лень непривлекательной.

...