如何通过隐藏"状态"更改来编写sig类型中没有IO的haskell函数
题
我在haskell中编写了一个函数,它需要一些参数,如Word32,String(忽略currying)并输出Io Word32。现在,这是一个 功能 真正意义上的: 对于相同的输入,输出将始终相同.没有副作用。该函数返回IO Word32而不是Word32的原因是该函数在循环中多次更新许多32位线性反馈移位寄存器(lfsr)和其他寄存器,以便计算最终的Word32输出。
我的问题是这样的:鉴于此功能 有效无副作用, ,是否有可能隐藏函数实现内部的那些寄存器更新,以便函数返回Word32而不是IO Word32?如果是这样,如何?
解决方案
是的!Haskell可以做到这一点。
圣莫纳德
如果你实际上使用可变状态(寄存器),这是完全隐藏的观察者在函数之外,那么你在 圣莫纳德, ,仅用于记忆效果的monad。你通过 runST
, ,并且当您退出函数时,所有效果都保证不可见。
它正是处理本地可变状态的正确计算环境。
纯功能状态:国家莫纳德
但是,如果您实际上并没有改变寄存器或单元格,而是多次更新纯函数值,则可以使用更简单的环境: 国家莫纳德.这不允许可变状态,但给出了局部状态的错觉。
IO,和unsafePerformIO
最后,如果你有本地的,可变的效果,比如在 ST
monad,但是由于某种原因,您将需要对该状态进行IO操作(例如通过FFI调用),您可以模拟 ST
monad,具有几乎一样多的安全性,通过使用 unsafePerformIO
, ,而不是 runST
, ,来引入本地IO环境。由于IO monad没有很好的类型来强制抽象,因此您需要手动确保副作用是不可观察的。
其他提示
如果您使用FFI导入该函数,只需删除 IO
从返回类型。否则,使用 unsafePerformIO :: IO a -> a
从 System.IO.Unsafe
.请注意,此功能是Haskell中最危险的功能之一。不要使用它,如果你不是真的shure关于后果。但为了你的目的,这似乎没问题。
是的,这将是unsaceperformio的合法使用。 但如果你真的确定没有明显的效果,那就是好的。