Haskell/Mutable objects

From Wikibooks, the open-content textbooks collection

< Haskell
Jump to: navigation, search



Mutable objects (Solutions)

Contents

Advanced Haskell

ArrowsImage:50%.png
Understanding arrows
Continuation passing style (CPS) Image:50%.png
Mutable objects Image:00%.png
Zippers Image:75%.png
Applicative Functors Image:50%.png
Monoids Image:00%.png
Concurrency Image:00%.png

As one of the key strengths of Haskell is its purity: all side-effects are encapsulated in a monad. This makes reasoning about programs much easier, but many practical programming tasks require manipulating state and using imperative structures. This chapter will discuss advanced programming techniques for using imperative constructs, such as references and mutable arrays, without compromising (too much) purity.

[edit] The ST and IO monads

Recall the The State Monad and The IO monad from the chapter on Monads. These are two methods of structuring imperative effects. Both references and arrays can live in state monads or the IO monad, so which one is more appropriate for what, and how does one use them?

[edit] State references: STRef and IORef

[edit] Mutable arrays

[edit] Examples

import Data.IORef
import Data.Map(Map)
import qualified Data.Map as M
import Data.Monoid(Monoid(..))
import System.IO.Unsafe(unsafePerformIO)

memo :: (Ord a) => (a -> b) -> (a -> b)
memo f = m `seq` withMemo m f
  where m = unsafePerformIO newMemo

newtype Memo a b = Memo (IORef(Map a b))

newMemo :: (Ord a) => IO (Memo a b)
newMemo = Memo `fmap` newIORef mempty

withMemo :: (Ord a) => Memo a b -> (a -> b) -> (a -> b)
withMemo (Memo r) f a = unsafePerformIO $
                         do m <- readIORef r
                            case M.lookup a m of
                              Just b -> return b
                              Nothing -> let b = f a
                               in writeIORef r
                                    (M.insert a b m)
                                      >> return b
Personal tools
Create a book