What exactly is the difference between STRef and IORef and when do I use each of them? As far as I can tell they both are for mutable state so whats the point of both of them existing?
问题:
回答1:
You can do more things in the IO
monad than in the ST
monad. The latter provides mutable references, the former provides mutable references, exception catching, threads, and of course IO.
It is usually good Haskell practice to use the "weakest" or "more restricted" tool available that can solve your problem, because "weaker" tools tend to be easier to understand and analyze (another place this principle crops up in Haskell is in the Applicative
versus Monad
distinction).
So, if you only need mutable references, use ST
. Future maintainers will be able to infer more about what your function does (and doesn't do) just by looking at the type.
An example situation in which you are forced to use IORef
s (or their cousins MVar
s) is when having to share a mutable reference between two different execution threads.
Also keep in mind that you can escape ST
(which means you can run ST
computations inside pure functions) but you can't escape IO
.
回答2:
They each provide the same functionality, but for different monads. Use IORef
if you need a managed ref in IO
, and STRef
if you need one in ST s
.
EDIT: a brief example:
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