从unsafePerformIO
开始到RTS,libc或OS API结束,GHC如何实现IO?
我试图了解当标准前奏不可用时IO在Haskell中如何工作(例如,如果我们出于任何原因自己实现标准前奏)。
我本来希望在GHC的Haskell代码中找到对C函数的包装调用,但事实并非如此。 unsafePerformIO
建立在runRW#
之上,这是重型魔法开始的地方,我们开始崩溃到Haskell中没有实现的函数和类型,而是内置到编译器中。 runRW#
似乎能够对现实世界的状态(即State# RealWorld
)进行IO动作。
试图从另一个方向走,我还没有在RTS找到立足点。它似乎不包含我期望的功能,如fread()
和fwrite()
或read()
和write()
。
从哪里继续关注IO实现?从这里开始的基本路线图是什么?
据我所知,IO x
类型的值实际上是从RealWorld#
到RealWorld#
和x
的[严格]元组的函数。换句话说,一个简单的状态monad。
你不会在RTS本身找到read()
等;我相信通常的Prelude接口通过FFI调用它们。也就是说,执行它的代码是在base
包中,而不是在RTS本身中。 (但是,RTS确实拥有自己的线程调度程序,可能会调用pthread
或其他任何内容。还有垃圾收集器和内存管理器,可能会调用mmap
。)
至少,我相信它是如何运作的,尽我所能记住。毋庸置疑,这些都是GHC特定实现的高度特异性,而不是任何官方Haskell语言规范的一部分。