I am confused about using the STArray in Haskell with polymorphism.
Suppose I have the following setup
data SomeData a = Something a
thawData :: MArray u a m => SomeData a -> m (u Int a)
thawData = {- doesn't matter -}
doSomething :: SomeData a -> ()
doSomething x = runST $ do
xArr <- thawData x
return ()
now, I believe the type of thawData specializes in this case to
thawData :: SomeData a -> ST s (STArray Int a)
However, this does not compile unless I change the type of thawData to explicitly use the STArray, even if I try to explicitly type it in the body of the do expression.
So what on earth is going on? Why can't the type specialize?
Can I somehow change the body of doSomething rather than the type of thawData?
Thanks!
Not quite,
STArray
s are parametrized by the state type, so it would beST s (STArray s Int a)
. But that cannot be inferred, as the error message tells you:there are several possible instances of the
MArray
class withST s
as the monad to choose from (and even if only one instance was in scope, the compiler operates on an open world assumption, other instances could be defined somewhere else). So the compiler doesn't know which instance to use, hence it refuses to compile the code.Now, the possible fix suggested isn't the right one here, what you need is to fix the array type by another means. One possibility is to specialise the type signature of
thawData
at the top level, as you did.Another is to specialise it in
doSomething
instead,which tells the compiler at which type
thawData
is to be used here, and the third is to move the expression type signature to the end of that linebut that requires the
ScopedTypeVariables
extension since now you need to refer to the type that instantiates the type variablea
from the signature ofdoSomething
. I find it more readable than the expression type signature in the middle of the line, though.