Я пытаюсь лучше понять Haskell лень, например, когда он оценивает аргумент функции.
Из этого source:
Но когда вычисляется вызов
const
(здесь нас интересует, здесь, в конце концов), его возвращаемое значение также оценивается... Это хороший общий принцип: функция, очевидно, является строгой в его возвращаемое значение, потому что, когда приложение функции нужно оценивать, ему необходимо оценить, в теле функции, что возвращается. Начиная с этого момента вы можете знать, что должно оцениваться, глядя на то, что возвращаемое значение зависит от неизменно. Ваша функция будет строгой в этих аргументах и ленив в других.
Итак, функция в Haskell всегда оценивает собственное возвращаемое значение? Если у меня есть:
foo :: Num a => [a] -> [a]
foo [] = []
foo (_:xs) = map (* 2) xs
head (foo [1..]) -- = 4
В соответствии с вышеприведенным абзацем map (* 2) xs
необходимо оценить. Интуитивно я думаю, что это означает применение map
ко всему списку, приводящее к бесконечному циклу.
Но я могу успешно занять голову результата. Я знаю, что :
ленив в Haskell, значит ли это, что оценка map (* 2) xs
просто означает создание чего-то еще, еще не полностью оцененного?
Что значит оценивать функцию, примененную к бесконечному списку? Если возвращаемое значение функции всегда оценивается, когда функция оценивается, может ли функция когда-либо фактически возвращать thunk?
Edit:
bar x y = x
var = bar (product [1..]) 1
Этот код не зависает. Когда я создаю var
, не оценивает ли его тело? Или он устанавливает bar
в product [1..]
и не оценивает это? Если последний, bar
не возвращает свое тело в WHNF, правильно, так это действительно "оценило" x? Как bar
быть строгим в x
, если он не зависает при вычислении product [1..]
?