[Haskell-cafe] Question about ST arrays

Ramin Honary ramin.honary at gmail.com
Fri Dec 29 15:36:27 UTC 2017

You should use "runSTArray" or "runSTUArray" instead of "runST" to convert
your STArray to an immutable array:  https://hackage.haskell.

Or another option is to use "stToIO"  to convert the "STArray" to an
but if you want to build an IOArray, it is better to just start with an
IOArray rather than converting an STArray to an IOArray.

The design of ST arrays is to allow you to construct them quickly and then
make them immutable once you are done constructing it.

An immutable array must have the whole array copied after every single
update, but ST arrays allow you to make many updates without copying, then
when you have completed constructing the ST array, you must freeze it to an
immutable array using the "runSTUArray" function. Freezing happens without
copying the array, after that it is immutable and may not be made into an
STArray again unless you unfreeze it using "thaw", which creates a copy of

Once you have constructed your immutable array, you can access it
arbitrarily using the immutable operator (!).

If you want to make multiple updates at multiple times, you must use an
IOArray or IOUArray. The ST monad is designed for you to construct pure,
referentially transparent, immutable values in an isolated and strictly
evaluated "environment" that lets you perform strict updates during
construction. Once evaluation of the "ST" monad is complete, the returned
value becomes pure, immutable, and referentially transparent. The for-all'd
"s" parameter of the "runST" function ensures you do not mix separate
"environments," and this is the reason you got your type error. Using
"runSTArray" or "runSTUArray" does not have this restriction.

I am not sure of the reason for this design decision, but I know it has
something to do with the compiler guaranteeing that pure immutable
referentially transparent types are constructed without effecting each
other, preventing race conditions. There is discussion of this on the
Haskell wiki:

On Fri, Dec 29, 2017 at 11:36 PM, Jean-Marc Alliot <jm at alliot.org> wrote:

> Hi,
> This is my first post to this list so I apologize in advance if I don't
> use it properly, or if my question is too simple or inapropriate.
> I come from the Caml world and I am quite new to Haskell (but not to
> functional programming). I am currently trying to get the hang of Haskell
> arrays. I have gone through regular arrays, IO Arrays and I am now working
> with ST Arrays.
> This is the problem I am currently stuck with. I write the following code:
> arr = newArray (-1, 1) 0 :: ST s (STArray s Int Int)
> get :: Int -> Int
> get i = runST (arr >>= (\b -> readArray b i))
> Here everything is perfectly OK.
> Now I want a more general version that could deal with any array like arr.
> So I write:
> get2 :: ST s (STArray s Int Int) -> Int -> Int
> get2 tab i = runST (tab >>= (\b -> readArray b i))
> And the compiler is clearly very upset by my code:
> Couldn't match type ‘s’ with ‘s1’
>       ‘s’ is a rigid type variable bound by
>         the type signature for:
>           get2 :: forall s. ST s (STArray s Int Int) -> Int -> Int
>         at testst.hs:17:9
>       ‘s1’ is a rigid type variable bound by
>         a type expected by the context:
>           forall s1. ST s1 Int
>         at testst.hs:18:14
>       Expected type: ST s1 Int
>         Actual type: ST s Int
> I am pretty sure that the compiler is right and I am wrong, but I don't
> get why... Anyone could help?
> Thanks
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20171230/d823542e/attachment.html>

More information about the Haskell-Cafe mailing list