Я пытаюсь получить более глубокое понимание лени в Haskell.Как лень и ввод-вывод работают вместе в Haskell?
я представлял себе следующий фрагмент сегодня:
data Image = Image { name :: String, pixels :: String }
image :: String -> IO Image
image path = Image path <$> readFile path
Привлекательность в том, что я мог бы просто создать экземпляр изображения и передать его вокруг; если мне нужны данные изображения было бы прочитать лениво - если нет, то время и память стоимость чтения файла можно было бы избежать:
main = do
image <- image "file"
putStrLn $ length $ pixels image
Но это то, как он на самом деле работает? Как лень совместима с IO? Будет ли readFile вызываться независимо от того, получаю ли я доступ к pixels image
или будет ли время выполнения оставить этот файл неоцененным, если я не буду ссылаться на него?
Если изображение действительно прочитано лениво, то не возможно ли, что действия ввода-вывода могут произойти не в порядке? Например, что, если сразу после вызова image
я удаляю файл? Теперь вызов putStrLn ничего не найдет, когда он попытается прочитать.
Спасибо за этот ответ! На самом деле, это было описание RWH hGetContents, которое смутило меня в этом вопросе. Я не понимал, что это особый случай, и использовал небезопасные вызовы ввода-вывода внизу. Итак, в основном, мой пример читает файл, как только действие readFile обрабатывается? Это кажется намного более последовательным, если так. – Bill
@Bill: Вот реализация для readFile, прямо из стандартных библиотек GHC: 'readFile name = openFile name ReadMode >> = hGetContents' Таким образом, нет, ваш пример попадает под категорию« cheating cheater ». Тем не менее, ленивые функции ввода-вывода, как правило, достаточно безопасны для повседневного практического использования, поэтому не переживайте слишком много, если чистота для вас очень важна. –
Я знаю, что Олег говорит, что 'unsafeInterleaveIO' нарушает ссылочную прозрачность, но я не согласен. Я бы сказал, что это просто недетерминированно, как и многие вещи в монаде IO. «GetCurrentTime» нарушает ссылочную прозрачность, потому что я могу использовать его для определения того, какая из двух экзистенциально равных функций реализована более эффективно? –