generated at
IORefとSTRefの使い分け












どうすればいい?
HaskellでReplを作るときにどちらを使えばよいのかわからないでいる
48時間でSchemeを書こう/変数と代入 - Wikibooksを見ると、理由は全く理解できないが、IORefを使ったほうが良いとある
この心を理解していきたい




STRefとは
STモナドを使う
「状態の書き換え」をするだけで、IOには関わらない
hs
newSTRef :: a -> GHC.ST.ST s (STRef s a) readSTRef :: STRef s a -> GHC.ST.ST s a writeSTRef :: STRef s a -> a -> GHC.ST.ST s () modifySTRef :: STRef s a -> (a -> a) -> ST s () runST :: (forall s. ST s a) -> a
この辺の関数は全てSTモナドを返すので、runSTを使って値を取り出す
Stateモナドと異なり、複数の状態を扱うことができると見なせる
「計算」を状態として保持する


IORefとは
hs
newIORef :: a -> IO (IORef a) writeIORef :: IORef a -> a -> IO () readIORef :: IORef a -> IO a modifyIORef :: IORef a -> (a -> a) -> IO ()
IOモナドを使う
STRefよりもだいぶできることが多いのかな
具体的にはよくわからないが
「計算」以外の状態も保持することができる
つまり?


最小の例を比較してみる
hs
import Data.IORef import Control.Monad.ST import Data.STRef io :: IO Integer io = do a <- newIORef 1 writeIORef a 2 return =<< readIORef a st :: ST s Integer st = do a <- newSTRef 1 writeSTRef a 2 return =<< readSTRef a main = do print =<< io -- 2 print $ runST st -- 2
io st はほぼ同じ見た目をしているが、返す型が異なるのでmainの中での扱いも異なってくる




参考
StateVarとかいうモジュールがあるらしい