Мне ленивая оценка полезна для многих вещей.
Во-первых, все существующие ленивые языки чисты, потому что очень сложно рассуждать о побочных эффектах в ленивом языке.
Чистые языки позволяют рассуждать об определениях функций с использованием эквациональных рассуждений.
foo x = x + 3
К сожалению, в не ленивых настройках больше операторов не могут быть возвращены, чем в ленивых, поэтому это менее полезно в таких языках, как ML. Но на ленивом языке вы можете смело рассуждать о равенстве.
Во-вторых, многие вещи, такие как «ограничение значения» в ML, не нужны в ленивых языках, таких как Haskell. Это приводит к значительному снижению синтаксиса. В языках, подобных ML, необходимо использовать такие ключевые слова, как var или fun. В Хаскеле эти вещи сводятся к одному понятию.
В-третьих, лень позволяет вам писать очень функциональный код, который можно понять по частям. В Haskell принято писать тело функции, например:
foo x y = if condition1
then some (complicated set of combinators) (involving bigscaryexpression)
else if condition2
then bigscaryexpression
else Nothing
where some x y = ...
bigscaryexpression = ...
condition1 = ...
condition2 = ...
Это позволяет вам работать «сверху вниз», понимая тело функции. ML-подобные языки вынуждают вас использовать let, которая оценивается строго. Следовательно, вы не осмеливаетесь «поднять» предложение let до основной части функции, потому что, если это дорого (или имеет побочные эффекты), вы не хотите, чтобы оно всегда оценивалось. Haskell может явно «вытолкнуть» детали к предложению where, поскольку он знает, что содержимое этого предложения будет оцениваться только при необходимости.
На практике мы, как правило, используем охранников и разрушаемся до:
foo x y
| condition1 = some (complicated set of combinators) (involving bigscaryexpression)
| condition2 = bigscaryexpression
| otherwise = Nothing
where some x y = ...
bigscaryexpression = ...
condition1 = ...
condition2 = ...
В-четвертых, лень иногда предлагает гораздо более элегантное выражение определенных алгоритмов. Ленивая «быстрая сортировка» в Haskell является однострочной и имеет то преимущество, что если вы смотрите только на первые несколько предметов, вы оплачиваете только расходы, пропорциональные стоимости выбора только этих предметов. Ничто не мешает вам делать это строго, но вам, вероятно, придется каждый раз перекодировать алгоритм для достижения той же асимптотической производительности.
В-пятых, лень позволяет вам определять новые управляющие структуры в языке. Вы не можете написать новую конструкцию типа «если .. тогда .. еще ..» на строгом языке. Если вы попытаетесь определить функцию, например:
if' True x y = x
if' False x y = y
на строгом языке, тогда обе ветви будут оцениваться независимо от значения условия. Это ухудшается, когда вы рассматриваете петли. Все строгие решения требуют, чтобы язык предоставил вам какую-то цитату или явную лямбда-конструкцию.
Наконец, в том же духе, некоторые из лучших механизмов борьбы с побочными эффектами в системе типов, таких как монады, действительно могут эффективно выражаться только в ленивых условиях. Это можно увидеть, сравнив сложность рабочих процессов F # с Haskell Monads. (Вы можете определить монаду на строгом языке, но, к сожалению, вы часто будете нарушать закон монады или два из-за отсутствия лени и рабочих процессов, для сравнения заберите тонну строгого багажа.)