IORefとSTRefの使い分け
#WIP
どうすればいい?
HaskellでReplを作るときにどちらを使えばよいのかわからないでいる
48時間でSchemeを書こう/変数と代入 - Wikibooksを見ると、理由は全く理解できないが、IORefを使ったほうが良いとある
この心を理解していきたい
STRefとは
STモナドを使う
「状態の書き換え」をするだけで、IOには関わらない
code: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とは
code:hs
newIORef :: a -> IO (IORef a)
writeIORef :: IORef a -> a -> IO ()
readIORef :: IORef a -> IO a
modifyIORef :: IORef a -> (a -> a) -> IO ()
IOモナドを使う
STRefよりもだいぶできることが多いのかな
具体的にはよくわからないが
「計算」以外の状態も保持することができる
つまり?
最小の例を比較してみる
code: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の中での扱いも異なってくる
参考
Haskell 状態系モナド 超入門 - Qiita
https://sharpknock.com/posts/programming/mutable-variables-in-haskell.html
StateVarとかいうモジュールがあるらしい
どういったときに IORef を使うべきか - みどりねこ日記
https://qiita.com/mod_poppo/items/03fc14f693b601e0a00f
https://qiita.com/7shi/items/2e9bff5d88302de1a9e9
https://stackoverflow.com/questions/20439316/when-to-use-stref-or-ioref
https://osa1.net/posts/2016-07-25-IORef-STRef-exposed.html
https://xtech.nikkei.com/it/article/COLUMN/20080603/305833/
https://xtech.nikkei.com/it/article/COLUMN/20070206/260872/?P=2
https://stackoverflow.com/questions/52467957/ioref-in-haskell
http://hiratara.hatenadiary.jp/entry/20121211/1355241685