Difference between revisions of "Mutable variable"
(add StateVar) 
Tomjaguarpaw (talk  contribs) (Remove references to packages that seem unmaintained (no uploads in last five years)) 

(3 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): 

−  * {{HackagePackageid=ArrayRef}}, module <hask>Data.Ref.Universal</hask> 

* {{HackagePackageid=bindingcore}}, module <hask>Data.Variable</hask> 
* {{HackagePackageid=bindingcore}}, module <hask>Data.Variable</hask> 

−  * {{HackagePackageid= 
+  * {{HackagePackageid=dataref}} 
−  * {{HackagePackageid=monadstatevar}} 

* {{HackagePackageid=reffd}} 
* {{HackagePackageid=reffd}} 

* {{HackagePackageid=reftf}} 
* {{HackagePackageid=reftf}} 

−  * {{HackagePackageid= 
+  * {{HackagePackageid=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 {{HackagePackageid=dataref}} 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 == 
Latest revision as of 20:04, 13 May 2020
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 by Control.Monad.Trans.State
in the transformers package or you can use really mutable variables as provided by Data.IORef
or Data.STRef
or Control.Concurrent.STM.TVar
from the stm package. In either case you need a monad in order to cope with mutability, while staying purely functional.
There are several packages that provide a single interface to these different implementations of mutable variables (in alphabetical order):
 bindingcore, module
Data.Variable
 dataref
 reffd
 reftf
 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 dataref 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
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 Multiparameter type classes