Bab*_*san 7 monads haskell functional-programming referential-transparency unsafe-perform-io
我在haskell中编写了一个函数,它接受一些参数,如Word32,String(忽略currying)并输出IO Word32.现在,这是一个真正意义上的函数:对于相同的输入,输出将始终相同.没有副作用.函数返回IO Word32而不是Word32的原因是该函数在循环中多次更新许多32位线性反馈移位寄存器(lfsr)和其他寄存器,以便计算最终的Word32输出.
我的问题是:鉴于此函数实际上没有副作用,是否可以在函数实现中隐藏这些寄存器更新,以便该函数返回Word32而不是IO Word32?如果是这样,怎么样?
Don*_*art 13
是! Haskell可以做到这一点.
ST monad
如果你实际上使用了可变状态(寄存器),那些完全隐藏在函数外部的观察者,那么你就是ST monad,一个仅用于记忆效应的monad.您通过runST退出ST世界,当退出该功能时,所有效果都保证不可见.
正是处理本地可变状态的正确计算环境.
纯粹的功能状态:国家monad
但是,如果您实际上没有改变寄存器或单元格,而是多次更新纯函数值,则可以使用更简单的环境:State monad.这不允许可变状态,但给出了局部状态的错觉.
IO和unsafePerformIO
最后,如果你有本地的,可变的效果,比如在STmonad中,但由于某种原因,你将需要在该状态下进行IO操作(例如通过FFI调用),你可以模拟STmonad,几乎与通过使用unsafePerformIO而不是runST引入本地IO环境来提高安全性.由于IO monad没有很好的类型来强制执行抽象,因此您需要手动确保自己无法观察到副作用.
如果使用FFI导入该功能,只需IO从返回类型中删除.否则,使用unsafePerformIO :: IO a -> a从System.IO.Unsafe.请注意,此函数是Haskell中最危险的函数之一.不要使用它,如果你不是真的不知道后果.但为了你的目的,似乎没关系.