我试图更深入地了解 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
或者如果我从不引用它,运行时是否会留下未评估的 thunk?
如果图像确实是延迟读取的,那么 I/O 操作是否可能发生乱序?例如,如果在调用后立即image
删除文件怎么办?现在 putStrLn 调用在尝试读取时将一无所获。