我试图在IO行动中访问一个州Monad的状态。
更具体地说:我试图使用来自installHandler的System.Posix.Signals编写一个状态相关的信号处理程序,这需要IO,但是,我想做不同的操作,并在处理程序中更改状态。我看了一下不升,但我读到了“国家单子”是不应该被解除的。
这个是可能的吗?我更多的是寻找一个解释而不是一个“复制粘贴”的解决方案。如果取消IO内部的状态不起作用,那么当您想在IO中执行一些状态感知的处理时,解决方案会是什么样的呢?
发布于 2020-12-26 20:18:52
类型为State a b的值不包含状态。它只是一个封装的函数,如果您传递一个启动状态(使用runState函数),它可以提供结果状态和结果。无法从此函数的外部访问中间(或“当前”)状态。这就是使State Monad“纯净”的原因。
您似乎希望有一个处理程序,它的行为并不总是相同的(即使使用相同的参数调用),但取决于外部状态。这种行为是“不纯的”,不能用纯粹的手段来实现。因此,在这种情况下,您需要的是以一种可以从处理程序访问某个状态的“当前值”的方式封装不纯净的东西,而不需要将当前值本身传递给处理程序。
正如您已经从注释中了解到的那样,提供对IO操作的可变状态访问的转到工具是使用IORef。IORefs工作,因为Haskell运行时(传统上,至少在多线程之前)会序列化IO操作。因此,“当前价值”的概念总是有意义的。在每个IO操作之后,每个IORef所指向的值都是固定的。发生的订单IO操作也是固定的,因为它需要是您在do块中或使用>>=操作符中链接它们的顺序。信号的处理由Haskell运行时以确定性的方式执行,类似于每次您链接两个IO操作时,运行时检查挂起的信号,并调用相应的处理程序。
如果您想要编写以命令式方式操作数据的代码(其中可以有许多变量,甚至是更新sinlge元素的数组),您可以将代码编写为I/O操作,并为此使用IORef和IOArray,但是有一个特殊的IO“小”版本,它只以与I/O相同的方式支持可变状态,而不能与环境交互。共享状态需要从这个特殊IO元素的“胶囊”内部创建、读取和写入,这样运行整个操作就不会与外部状态交互,而只是与其内部状态交互--因此整个胶囊是纯净的,即使胶囊内的单个语句可以被认为是不纯的。这个低版本IO的名称称为ST,它是“状态线程”的缩写。
https://stackoverflow.com/questions/65447500
复制相似问题