2013-12-07 3 views
17

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

ответ

21

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

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

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

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

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

+10

Последнее, IMHO, самое важное: 'ST' позволяет вам безопасно использовать императивные функции, предоставляя чистый интерфейс. –

+0

Как точно выглядят вычисления ST внутри чистой функции? Можете ли вы привести пример побега? – user782220

+1

@ user782220 Вы избегаете 'ST', используя функцию' runST'. На странице Haskellwiki на 'ST' есть несколько примеров: http://www.haskell.org/haskellwiki/Monad/ST См. Также расширение' RankNTypes': https://www.fpcomplete.com/school/to-infinity- и-beyond/pick-of-the-week/guide-to-ghc-extensions/explicit-forall # use-case-the-st-monad – danidiaz

9

Каждый из них обеспечивает ту же функциональность, что и для разных монадов. Используйте IORef, если вам нужен управляемый рефлекс в 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 
+1

Что '' 'в' exampleSTRef'? – dimid

+2

@dimid Проверьте [этот ответ] (http://stackoverflow.com/a/12468757/1193741) для объяснения. – jtobin

Смежные вопросы