Brilliant. I think I've got it now. Thanks heaps, Tobias.

On Sat, May 26, 2012 at 4:01 AM, Tobias Brandt <tob.brandt@googlemail.com> wrote:
On 25 May 2012 19:43, Matthew Moppett <matthewmoppett@gmail.com> wrote:
> About the extra type info needed -- what part of the type "ST s (STArray s
> Int Int)" is the compiler unable to infer?

It doesn't know which array type to use, because 'newListArray' is polymorphic
in the type of array it returns. This type is not mentioned in
the signature of idST because the array is immediately consumed again by
'getElems'.

You can try it out in ghci (':t expr' gives you the type of an expression):

:m +Data.Array.ST
let xs = [1,2,3 :: Int]

:t xs
[Int]

:t newListArray (1, length xs) xs
MArray a Int m => m (a Int Int)

Applying getElems gets you this:
:t (newListArray (1, length xs) xs) >>= getElems
MArray a Int m => m [Int]

>From the 'runST' in your program, the compiler knows that m = ST s,
for some s, but there is nothing constraining 'a' further.
Any 'a' fulfilling the constraint 'MArray a Int (ST s)' will do.
Therefore we have to fix 'a' to some type, e.g. 'STArray s', but
'STUArray s' would work too, in this case.