3

我知道事实上,我们不能独立实现 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
4

1 回答 1

11

我不确定你想展示什么。您已经IO在 Haskell 中嵌入了编码,使用现有的实现IO作为目标。

关键是您使用unsafePerformIO print--- 您从其他 IO 系统借用的原语。

考虑一下:如果您没有任何其他可依赖的 IO 系统会怎样。所以没有print或以其他方式调用原始 IO 函数。你将如何实现 IO?

因此,虽然您可以在 Haskell 中以多种方式实现 IO 抽象,但您总是不得不依靠新的运行时原语函数来实际调用操作系统来执行真正的 IO。那是不能在 Haskell 本机中实现的位。


作为参考,请参阅 Wouter Swierstra 的博士论文“效果的功能规范”,它概述了在 Haskell 中对 IO 和其他效果进行编码的各种方式,并将 IO 规范定义为纯功能数据类型(种类扩展你所做的事情)。

在此处输入图像描述

于 2012-05-04T11:47:16.920 回答