我知道事实上,我们不能独立实现 IO monad,但我不知道究竟是为什么。这段代码是尝试使用函数式语言实现命令式范式。你能解释一下这个例子和真正的 IO 之间的区别吗?看起来函数 main 实现了正确的操作顺序并且保持惰性。
import System.IO.Unsafe
data Io a = Io a
runIO :: Io a -> a
runIO (Io a) = a
instance Monad Io where
return x = Io x
Io a >>= f = f a
-- internal side effect function
output :: Show a => a -> Io ()
output s = return $! unsafePerformIO $ print s
----------------------------------------------------------------
mainIO :: Io ()
mainIO = do output "A"
b <- return "B"
output b
output b
x <- return (undefined :: String)
return undefined
output "C"
head [output "C", output "C"]
output x
output "D"
test = runIO mainIO
输出:
"A"
"B"
"B"
"C"
"C"
<interactive>: Prelude.undefined