Я пытаюсь лучше понять 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..]?