任何人都可以解释GHC对IO的定义吗?

Bar*_*icz 5 io haskell ghc

标题非常具有自我描述性,但有一部分引起了我的注意:

newtype IO a = IO ()
Run Code Online (Sandbox Code Playgroud)

剥离newtype,我们得到:

State# RealWorld -> (# State# RealWorld, a #)
Run Code Online (Sandbox Code Playgroud)

我不知道是什么意思State#.我们可以这样替换它State:

State RealWorld -> (State RealWorld, a)
Run Code Online (Sandbox Code Playgroud)

那可以这样表达吗?

State (State RealWorld) a
Run Code Online (Sandbox Code Playgroud)

这个特殊的结构引起了我的注意


我从概念上知道

type IO a  =  RealWorld -> (a, RealWorld)
Run Code Online (Sandbox Code Playgroud)

@ R.MartinhoFernandes告诉我,我实际上可以考虑实现ST RealWorld a,但我只是好奇为什么特定的GHC版本就像它一样.

dfe*_*uer 9

最好不要过于深入地考虑GHC的实现IO,因为这种实现很奇怪而且阴暗,并且大部分时间都是由编译器魔术和运气工作的.GHC使用的破碎模型是IO动作是从整个现实世界的状态到与整个现实世界的新状态配对的值的函数.对于幽默的证据,这是一个奇怪的模型,请参阅acme-realworld包.

这种"工作"的方式:除非你导入名称以其开头的奇怪模块,否则你GHC.无法触及任何这些State#东西.您只能访问处理的函数IOST确保State#不能复制或忽略的函数.这State#是通过程序进行的,它确保实际以正确的顺序调用I/O原语.因为这只是假装,所以State#它根本不是正常值 - 它的宽度为0,取0位.

为什么State#要采用类型参数?这是一个更漂亮的魔法.ST使用它来强制保持状态线程分离所需的多态性.因为IO,它与特殊的魔术RealWorld类型参数一起使用.

  • 我不会说世界传递模型从根本上被破坏了,因为如果您使用内部实现细节,它就不会健全;这同样适用于许多抽象,包括 Data.Map 之类的东西!其他语言*明确*使用世界传递*和*将“世界”暴露给用户代码;他们使用类型系统特性来确保线性,而 Haskell 通过不暴露任何可能以非线性方式使用世界的操作来确保线性。 (2认同)