批评IO monad被视为在世界上运作的州monad


46

IOHaskell中的单子通常被解释为州是世界的州单子。因此,将IO amonad 类型的值视为worldState -> (a, worldState)

前一段时间,我读了一篇文章(或博客/邮件列表帖子),该文章批评了这种观点,并提出了一些不正确的原因。但是我既不记得这篇文章,也不记得原因。有人知道吗

编辑:这篇文章似乎丢失了,所以让我们在这里开始收集各种参数。 我开始悬赏以使事情变得更有趣。

编辑:该文章中,我一直在寻找的应对尴尬的阵容:单子输入/输出,并发性,异常和外国语言的Haskell中调用由西蒙·佩顿-琼斯。(感谢TacTics的回答。)



@JoachimSauer谢谢,这也是一篇有趣的文章,但它不是我想要的。那个专注于世界现状范例。
彼得·普德拉克(PetrPudlák)2012年

在我脑海中,这里的评论是一个好的开始
Adam

1
在这种情况下,“世界”是什么意思?我认为这并不意味着“地球”。这是某种全球范围吗?提出这个建议的作者卖空了自己。如果他想同时混淆和粉碎读者的自负,则应将其称为“国家就是宇宙”或“神国”。世界。ah!如今,您的年轻人向往不高!
GlenPeterson 2012年

Answers:


33

问题IO a = worldState -> (a, worldState)在于,如果这是真的,那么我们可以证明forever (putStrLn "Hello") :: IO a并且undefined :: IO a相等。这是dolio(2010,irc)提供的证明:

forever m
 =
m >> forever m
 =
fix (\r -> m >> r)
 = {definition of >> for worldState -> (a, worldState)}
fix (\r -> \w -> r (snd $ m w))

引理: (\r w -> r (snd $ m w)) ⊥ = ⊥

(\r w -> r (snd $ m w)) ⊥
  =
\w -> ⊥ (snd $ m w))
  =
⊥ . snd . m
  =
⊥

因此 forever m = fix (\r -> \w -> r (snd $ m w)) = ⊥

特别地forever (putStrLn "Hello") = ⊥,因此forever (putStrLn "Hello")undefined是等效的程序。但是,无论从理论上还是在实践中,显然都不应将它们视为等效程序。

请注意,即使不调用并发,该模型也是错误的。


7
有人会惊讶于一个无终止的程序等同undefined于Haskell的纯粹语义吗?在Haskell的纯语义中,应该将不同的in区分开!但是,当我们从操作上考虑我们的程序时,即使IO没有参与,我们也要区分不同的类型。关心我的程序是引发异常还是进入无限循环,即使您可以通过证明它们都是prove来证明它们是相等的也是如此。但是,这实际上并不是矛盾。

3
⊥和[0,1 ..]的表示即使它们都是“不终止的”,也是不同的。区别在于⊥是表示非终止非生产性的计算,而[0,1 ..]是非终止但具有生产性的。我们期望(永远(putStrLn“ Hello”))具有类似的非终止但富有成效的表示。
罗素·奥康纳

1
但是肯定forever (putStrLn "Hello")不是[0,1..]。您的证明并不特定于worldState,因此它也适用于常规状态monad。因此forever (someModificationWith "Hello")在符号上也等同于⊥。我对这个结果完全不感到惊讶。它是不是在指称语义生产,什么电脑做业务上,而我们永远等待是无关紧要的。同样的事情forever (putStrLn "Hello"); 它不会也不产生一个新的世界状态,我们可以以某种方式懒惰地消费它。

像Mercury和Clean这样的编程语言使用显式的世界状态传递为IO提供声明性模型是否根本上是错误的?
2014年

@Ben您是指世界传递如何与并发一起工作吗?您是否看到过Mercury并发的Rosetta代码?我想知道这在语义上也意味着什么。
CMCDragonkai 2015年

12

这是一个简单的答案:状态monad状态的任何更改都是由于monad中执行的任何操作所致。如果确实有“ WorldState->(a,WorldState)”解释要求相同的属性,而WorldState是仅IO monad更改的纯值,那就错了。时间更改,文件内容,句柄状态等都可以更改,而与IO monad中发生的情况无关。这就是IO monad的意义所在。据我所知,GHC绕过真实世界值(或实际值)的底线是为了确保一切顺利进行(据我所知)(可能只是放入ST值中)。


8
这实际上不是问题。您可以将绑定操作建模为对源自某些固定但无法知道的规则存储的世界状态进行修改。
sclv 2012年

1
@sclv:是的,但是这个固定但不可知的规则存储是使IO 不再是状态monad 的差异因素,这种不一致在状态monad中找不到
Jimmy Hoffa 2012年

尽管我记不清确切的论点,但我听到的关于WorldState状态的论点与并发有关。但是即使如此,我仍然认为WorldState也可以对未来进行编码,因此我仍然没有真正看到问题所在。当然,我想我缺少了一些东西。
Thomas Eding 2012年

@JimmyHoffa:不过,您可以在状态下携带规则存储。
sclv 2012年

1
@JimmyHoffa:这是抽象的目的。另外,为了跟上我的最初评论,Clean使用唯一性类型来确保将IO明确且快乐地模拟为世界,并确保您不会欺骗和“复制”世界。这是强制抽象的一种方式。
sclv 2012年

12

我写了一篇关于如何将IO建模为与您的语言的运行时系统进行通信的不对称协程形式的博客文章。(诚​​然是系列的第三部分)

http://comonad.com/reader/2011/free-monads-for-less-3/

那篇文章涵盖了为什么对“世界通行”的语义推理不便的原因。


+1-特别有趣,因为我长期以来计划以与这种语言类似的方式实现我正在设计的语言的IO!:)
Jules

8

请参阅解决尴尬小队

主要原因是IO monad的RealWorld状态模型无法与并发一起很好地工作。在这个易读的经典中,SPJ支持使用操作语义来理解它。


我相信这是我一直在寻找的原始文章,主要是第3.1节。如果您是在我编辑问题之前发布它的,那么我会接受您的回答,但是现在,我认为等到最后看其他人将发表的所有想法会更公平。
PetrPudlák2012年

5

正如TacTics所说,有关RealWorld状态模型的主要抱怨是,世界传递不一定与并发一起工作。但是Wouter Swierstra和Thorsten Altenkirch在他们的论文《野兽之美:尴尬小队的功能语义学》:http://www.staff.science.uu.nl/~swier004/Publications/BeautyInTheBeast.pdf

与此对应的代码以IOSpec的形式在Hackage上:http ://hackage.haskell.org/package/IOSpec

我认为Wouter的论文会更详细:http//www.staff.science.uu.nl/~swier004/Publications/Thesis.pdf

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.