В чем именно разница между STRef и IORef и когда я использую каждый из них? Насколько я могу судить, они оба предназначены для изменяемого состояния, так какой смысл в их существовании обоих?
Когда использовать STRef или IORef?
Ответы (2)
Вы можете делать больше вещей в монаде IO
, чем в монаде ST
. Последний предоставляет изменяемые ссылки, первый обеспечивает изменяемые ссылки, перехват исключений, потоки и, конечно же, ввод-вывод.
Обычно хорошей практикой в Haskell является использование «самого слабого» или «более ограниченного» из доступных инструментов, которые могут решить вашу проблему, потому что «более слабые» инструменты, как правило, легче понять и проанализировать (другое место, где этот принцип возникает в Haskell, находится в Applicative
против Monad
различия).
Итак, если вам нужны только изменяемые ссылки, используйте ST
. Будущие сопровождающие смогут сделать больше выводов о том, что делает (и не делает) ваша функция, просто взглянув на тип.
Примером ситуации, в которой вы вынуждены использовать IORef
s (или их двоюродных братьев MVar
s), является необходимость совместного использования изменяемой ссылки между двумя разными потоками выполнения.
Также имейте в виду, что вы можете избежать ST
(что означает, что вы можете выполнять ST
вычислений внутри чистых функций), но вы не можете избежать IO
.
ST
позволяет безопасно использовать императивные функции, предоставляя чистый интерфейс.
- person Joachim Breitner; 07.12.2013
ST
, используя функцию runST
. На странице Haskellwiki на ST
есть несколько примеров: haskell.org/haskellwiki/Monad/ST См. также расширение RankNTypes
: fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/
- person danidiaz; 07.12.2013
ST
имеет не только изменяемые ссылки, но и изменяемые массивы
- person newacct; 09.12.2013
Каждый из них обеспечивает одинаковую функциональность, но для разных монад. Используйте 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
s
в exampleSTRef
?
- person dimid; 22.06.2016