我知道事实上,我们不能独立实现 IO monad,但我不知道究竟是为什么。这段代码是尝试使用函数式语言实现命令式范式。你能解释一下这个例子和真正的 IO 之间的区别吗?看起来函数 main 实现了正确的 Action 顺序并且保持懒惰。
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
最佳答案
我不确定你想展示什么。您已经嵌入了 IO
的编码在 Haskell 中,使用 IO
的现有实现作为目标。
关键是你对unsafePerformIO
的使用和 print
--- 您从其他 IO 系统借用的原语。
考虑一下:如果您没有任何其他 IO 系统可以依赖会怎样。所以没有 print
或其他方式来调用原始 IO 函数。你将如何实现 IO?
因此,虽然您可以在 Haskell 中以多种方式实现 IO 抽象,但您总是不得不依赖新的运行时原语函数来实际调用操作系统来执行真正的 IO。这是 Haskell 本身无法实现的部分。
作为引用,见博士论文"A Functional Specification of Effects" , Wouter Swierstra,概述了在 Haskell 中对 IO 和其他效果进行编码的各种方式,并将 IO 规范定义为纯函数数据类型(您所做工作的一种扩展)。
关于haskell - Haskell 内部的 IO 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10447914/