我可能不太了解 IO 单子。
如果我编写了一个预计将运行数月的应用程序,同时记录其进度,IO monad 是否会将所有日志信息保存在 RAM 中直到最后?
在IO Inside上的博客中,Haskell 将世界建模为
main :: RealWorld -> ((), RealWorld)
这样 IO 不会在代码的 Haskell 部分执行期间发生,而只会在应用程序从main
.
我可能完全误解了这一点。有人可以解释Haskell 什么时候真正做 IO 吗?
IO monad 会将所有日志信息保存在 RAM 中直到最后吗?
不,您不应该将“IO monad”视为执行操作的东西。这只是表示命令式程序的一种数学方式。原始的命令式程序是这样的getChar
;>>=
用于将两个程序粘合到一个更大的命令式程序中。IO monad 是所有命令式程序的集合。
考虑一个程序,例如
main = putStr "Hello, " >> putStrLn "world!"
这意味着:main
是执行程序的程序putStr "Hello, "
,完成后,执行程序putStrLn "world!"
。Haskell 解释器或编译程序不需要在内存中保留任何状态,除了指令指针,即“我们在哪里,接下来我们要执行什么”。
这个RealWorld -> ((), RealWorld)
比喻可能让你感到困惑,因为它似乎暗示了将外部世界的状态转换为必须完整计算的新状态,之后可以更新世界以反映计算的状态。这根本不是发生的事情。Haskell wiki 对此提出警告:
以下关于 IO 的故事是不正确的,因为它实际上无法解释 IO 的一些重要方面(包括交互和并发)。
IO monad 会将所有日志信息保存在 RAM 中直到最后吗?
不。假设您使用的是合理的日志记录策略。
Haskell 在程序需要结果时执行 IO;对于大多数动作来说,这是立即的。(例外是惰性文件输入库,在程序使用数据之前不一定要读取文件)。