STRef与IORef的区别究竟是什么?我何时使用它们?据我所知,他们两个都是可变的状态,所以两者都存在吗?
答案 0 :(得分:25)
您可以在IO
monad中执行比ST
monad更多的操作。后者提供了可变引用,前者提供了可变引用,异常捕获,线程,当然还有IO。
使用可以解决问题的“最弱”或“更受限制”的工具通常是很好的Haskell实践,因为“较弱”的工具往往更容易理解和分析(这个原则在Haskell中出现的另一个地方)在Applicative
与Monad
区别中。
因此,如果仅需要可变引用,请使用ST
。通过查看类型,未来的维护者将能够推断出更多关于你的函数做什么(而不做)的事情。
您必须在两个不同的执行线程之间共享可变引用时,您被迫使用IORef
s(或它们的堂兄MVar
)的示例情况。
另请注意,您可以转义ST
(这意味着您可以在纯函数中运行ST
次计算),但无法转义IO
。
答案 1 :(得分:9)
它们各自提供相同的功能,但适用于不同的monad。如果您需要IORef
中的托管参考,请使用IO
;如果STRef
中需要托管参考,请使用ST s
。
编辑:一个简短的例子:
import Control.Monad.ST
import Data.IORef
import Data.STRef
exampleSTRef :: ST s Int
exampleSTRef = do
counter <- newSTRef 0
modifySTRef counter (+ 1)
readSTRef counter
exampleIORef :: IO Int
exampleIORef = do
counter <- newIORef 0
modifyIORef counter (+ 1)
putStrLn "im in ur IO monad so i can do I/O"
readIORef counter