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 it:
https://hackage.haskell.org/package/array-0.5.2.0/docs/Data-Array-MArray.html#v:thaw
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:
https://wiki.haskell.org/Monad/ST#An_explanation_in_Haskell-Cafe