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

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


person user782220    schedule 07.12.2013    source источник


Ответы (2)


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

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

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

Примером ситуации, в которой вы вынуждены использовать IORefs (или их двоюродных братьев MVars), является необходимость совместного использования изменяемой ссылки между двумя разными потоками выполнения.

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

person danidiaz    schedule 07.12.2013
comment
Последний пункт, ИМХО, самый важный: ST позволяет безопасно использовать императивные функции, предоставляя чистый интерфейс. - person Joachim Breitner; 07.12.2013
comment
Как именно выглядят вычисления ST внутри чистой функции? Можете ли вы привести пример побега? - person user782220; 07.12.2013
comment
@user782220 user782220 Вы экранируете 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
comment
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
person jtobin    schedule 07.12.2013
comment
Что s в exampleSTRef? - person dimid; 22.06.2016
comment
@dimid Проверьте этот ответ для объяснения. - person jtobin; 22.06.2016