When I try to compile this:
module Main where
import qualified Data.Vector.Unboxed.Mutable as MV
import Control.Monad.ST
myRead mv = runST $ MV.read mv 0
I get the following error message:
Could not deduce (t ~ U.MVector s a)
from the context (U.Unbox a)
bound by the inferred type of myRead :: U.Unbox a => t -> a
at src/Main.hs:53:1-32
`t' is a rigid type variable bound by
the inferred type of myRead :: U.Unbox a => t -> a
at src/Main.hs:53:1
Expected type: U.MVector (PrimState (ST s)) a
Actual type: t
In the first argument of `MV.read', namely `mv'
In the second argument of `($)', namely `MV.read mv 0'
In the expression: runST $ MV.read mv 0
Can I make a read from a mutable vector pure with runST? If so, how? I assume it entails a type signature for myRead, but everything I’ve tried has just lead to more and more incomprehensible error messages.
EDIT: Highlighting some context I just put in a comment below: The context here is that I have a function that takes in a mutable vector, does some computations using the mutable vector as a temporary scratch space, then needs to return a float value. Because I don’t care about the changes to the mutable vector, I was wondering if there was a way to ignore its “state change” and simply return one of the values from inside it.
The other answers are good, but I think there is one basic thing about ST that you are missing. Each call to runST is effectively making a new “ST universe” in which some imperative code runs. So if you have one call to runST to make the array and a separate call to runST to get a value out of that array, things can’t possibly work. The two runST calls want their own unique universes, whereas you want them to share one.
What the answers explained in some detail is how these unique universes are created by some type-system trickery.