Когда использовать STRef или IORef?

В чем же разница между STRef и IORef и когда я использую их? Насколько я могу сказать, они оба предназначены для изменяемого состояния, так что точка их обоих существует?

Ответы

Ответ 1

Вы можете делать больше вещей в монаде IO, чем в монаде ST. Последний предоставляет изменчивые ссылки, первый предоставляет изменяемые ссылки, исключение catch, потоки и, конечно, IO.

Обычно хорошая практика Haskell использует "самый слабый" или "более ограниченный" инструмент, который может решить вашу проблему, потому что "более слабые" инструменты, как правило, легче понять и проанализировать (в другом месте этот принцип возникает в Haskell находится в значении Applicative по сравнению с Monad).

Итак, если вам нужны только изменяемые ссылки, используйте ST. Будущие разработчики смогут больше рассказать о том, что делает ваша функция (и не делает), просто глядя на тип.

Пример ситуации, в которой вы вынуждены использовать IORef (или их двоюродных братьев MVar s), - это когда нужно разделить изменяемую ссылку между двумя различными потоками выполнения.

Также имейте в виду, что вы можете избежать ST (это означает, что вы можете запускать вычисления ST внутри чистых функций), но вы не можете избежать IO.

Ответ 2

Каждый из них обеспечивает ту же функциональность, но для разных монад. Используйте IORef, если вам нужен управляемый ref в IO и STRef, если вам нужен один из ST s.

EDIT: краткий пример:

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