[Haskell] help with IOArray

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Sun Aug 19 11:22:59 EDT 2007


robert bauer wrote:
> I have an IOArray, but it doesn't work the way I expected it to.
> 
> I defined
> 
> newMem s = newIOArray (0, size-1) 0
> 
> and then
> 
> x = newMem 30
> 
> then
> 
> do {
>    y <- x
>  ; v <- readIOArray y 2
>  ; print v
>  ; writeIOArray y 2 20
>  ; v <- readIOArray y 2
>  ; print v
> }
> 
> this resulted in 0, 2  as expected.
> 
> however, then
> 
> do {
>  y <- x
>  ; v <- readIOArray y 20
>  ; print v
> }
> 
> results in 0
> 
> I thought the IOArray was basically a static structure?

yes it is. However, 'x' is not an IOArray. Its type is (after
defaulting)

  x :: IO (IOArray Int Int)

It represents an IO action that constructs a *new* array.> do {

so
> do {
>  y <- x
>  ; v <- readIOArray y 20
>  ; print v
> }

constrcts a new array and finds its 20th element, which was
initialized to 0.

The problem you have is dealing with global variables in Haskell.
There are two major approaches.

a) Construct the variable once and pass it explicitely as an argument to
   all functions. (In other words, don't use global variables at all.)

   > main = do {
   >   mem <- newMem
   >   func1 mem
   >   func2 mem
   > }

   This is simple, easy to understand, but it doesn't scale well.

   To make it scale better you can define a data type for the
   global state.

   > data GlobalState = GS { mem :: IOArray Int Int }

   This record can then easily be extended with new fields as they
   come up.

   Finally you can get rid of the explicit 'mem' (or 'state') arguments
   by using a state monad transformer (StateT).

b) Use actual global variables. See

   http://haskell.org/haskellwiki/Top_level_mutable_state

   for further information.

http://haskell.org/haskellwiki/Global_variables  is also interesting.

HTH,

Bertram


More information about the Haskell mailing list