# Mutable variable

### From HaskellWiki

(Difference between revisions)

(initialized from mailing list) |
(data-ref) |
||

(4 intermediate revisions by 2 users not shown) | |||

Line 4: | Line 4: | ||

There are several packages that provide a single interface to these different implementations of mutable variables (in alphabetical order): | There are several packages that provide a single interface to these different implementations of mutable variables (in alphabetical order): | ||

− | * {{HackagePackage|id=ArrayRef | + | * {{HackagePackage|id=ArrayRef}}, module <hask>Data.Ref.Universal</hask> |

* {{HackagePackage|id=binding-core}}, module <hask>Data.Variable</hask> | * {{HackagePackage|id=binding-core}}, module <hask>Data.Variable</hask> | ||

+ | * {{HackagePackage|id=data-ref}} | ||

* {{HackagePackage|id=monad-statevar}} | * {{HackagePackage|id=monad-statevar}} | ||

* {{HackagePackage|id=ref-fd}} | * {{HackagePackage|id=ref-fd}} | ||

Line 12: | Line 13: | ||

* {{HackagePackage|id=reference}} | * {{HackagePackage|id=reference}} | ||

* {{HackagePackage|id=stateref}} | * {{HackagePackage|id=stateref}} | ||

+ | * {{HackagePackage|id=StateVar}} | ||

+ | |||

+ | == Haskell 98 solution == | ||

+ | |||

+ | If the type of the reference depends only on the monad then there is an elegant Haskell 98 solution, | ||

+ | as implemented in the {{HackagePackage|id=data-ref}} package: | ||

+ | |||

+ | <haskell> | ||

+ | module Data.Ref where | ||

+ | |||

+ | import Data.IORef (newIORef, readIORef, writeIORef, ) | ||

+ | import Data.STRef (newSTRef, readSTRef, writeSTRef, ) | ||

+ | import Control.Concurrent.STM.TVar (newTVar, readTVar, writeTVar, ) | ||

+ | import Control.Concurrent.STM (STM, ) | ||

+ | import Control.Monad.ST (ST) | ||

+ | import Prelude hiding (read) | ||

+ | |||

+ | |||

+ | data T m a = Cons { write :: a -> m (), read :: m a } | ||

+ | |||

+ | modify :: Monad m => T m a -> (a -> a) -> m () | ||

+ | modify ref f = write ref . f =<< read ref | ||

+ | |||

+ | |||

+ | class C m where | ||

+ | new :: a -> m (T m a) | ||

+ | |||

+ | instance C IO where | ||

+ | new = fmap (\r -> Cons (writeIORef r) (readIORef r)) . newIORef | ||

+ | |||

+ | instance C (ST s) where | ||

+ | new = fmap (\r -> Cons (writeSTRef r) (readSTRef r)) . newSTRef | ||

+ | |||

+ | instance C STM where | ||

+ | new = fmap (\r -> Cons (writeTVar r) (readTVar r)) . newTVar | ||

+ | </haskell> | ||

+ | |||

== See also == | == See also == | ||

Line 17: | Line 55: | ||

* Haskell Libraries mailing list on "suggestion: A common type class for mutable variables" in [http://www.haskell.org/pipermail/libraries/2013-May/020131.html May] and [http://www.haskell.org/pipermail/libraries/2013-June/020152.html June], 2013 | * Haskell Libraries mailing list on "suggestion: A common type class for mutable variables" in [http://www.haskell.org/pipermail/libraries/2013-May/020131.html May] and [http://www.haskell.org/pipermail/libraries/2013-June/020152.html June], 2013 | ||

* [[Library/ArrayRef]] | * [[Library/ArrayRef]] | ||

+ | * A unified interface to mutable variables as an example for [[Multi-parameter type class]]es | ||

[[Category:Packages]] | [[Category:Packages]] |

## Latest revision as of 16:48, 15 July 2013

Although the functional programming paradigm emphasises the virtues of immutable variables, sometimes you need mutable variables nonetheless.

You can either simulate mutable variables using the state monad provided for instance byControl.Monad.Trans.State

Data.IORef

Data.STRef

Control.Concurrent.STM.TVar

There are several packages that provide a single interface to these different implementations of mutable variables (in alphabetical order):

- ArrayRef, module Data.Ref.Universal
- binding-core, module Data.Variable
- data-ref
- monad-statevar
- ref-fd
- ref-tf
- ref-mtl
- reference
- stateref
- StateVar

## [edit] 1 Haskell 98 solution

If the type of the reference depends only on the monad then there is an elegant Haskell 98 solution, as implemented in the data-ref package:

module Data.Ref where import Data.IORef (newIORef, readIORef, writeIORef, ) import Data.STRef (newSTRef, readSTRef, writeSTRef, ) import Control.Concurrent.STM.TVar (newTVar, readTVar, writeTVar, ) import Control.Concurrent.STM (STM, ) import Control.Monad.ST (ST) import Prelude hiding (read) data T m a = Cons { write :: a -> m (), read :: m a } modify :: Monad m => T m a -> (a -> a) -> m () modify ref f = write ref . f =<< read ref class C m where new :: a -> m (T m a) instance C IO where new = fmap (\r -> Cons (writeIORef r) (readIORef r)) . newIORef instance C (ST s) where new = fmap (\r -> Cons (writeSTRef r) (readSTRef r)) . newSTRef instance C STM where new = fmap (\r -> Cons (writeTVar r) (readTVar r)) . newTVar

## [edit] 2 See also

- Haskell Libraries mailing list on "suggestion: A common type class for mutable variables" in May and June, 2013
- Library/ArrayRef
- A unified interface to mutable variables as an example for Multi-parameter type classes