Я пытаюсь получить более глубокое понимание лени в Haskell.
Сегодня я представил себе следующий фрагмент:
data Image = Image { name :: String, pixels :: String }
image :: String -> IO Image
image path = Image path <$> readFile path
Апелляция здесь заключается в том, что я могу просто создать экземпляр Image и передать его; если мне нужны данные изображения, он будет читаться лениво - если нет, можно избежать затрат времени и памяти на чтение файла:
main = do
image <- image "file"
putStrLn $ length $ pixels image
Но как это работает? Как лень совместима с IO? Будет ли readFile вызываться независимо от того, получаю ли я доступ к pixels image
или не удастся ли выполнить runtime, если он никогда не ссылается на него?
Если изображение действительно читается лениво, то не возможно ли, что действия ввода-вывода могут не совпадать с порядком? Например, что, если сразу после вызова image
я удаляю файл? Теперь вызов putStrLn ничего не найдет, когда он попытается прочитать.