MVector
comes in two flavors, IOVector
and STVector
. I want to write some functions that use STVector
, so that they can be called from pure code despite using the fast mutable-vector algorithms in Data.Vector.Algorithms
.
With the help of a related thread, I've gotten partway there: I can stick an immutable Vector
into a mutable ST
context:
import Control.Monad.ST
import Data.Vector
import Data.Vector.Algorithms.Intro (sort)
x = fromList [1,4,2] :: Vector Int
verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x
freeze v
I just need to run sort
between the thaw and the freeze.
Perhaps surprisingly, I did not have to import Data.Vector.Mutable
, which is where STVector
is defined. Maybe I should use a type signature to specify that I want thaw
to produce an STVector
, but I don't know how: If I change the thaw
line to this:
v <- thaw x :: Data.Vector.Mutable.STVector s Int
I get this error:
• Couldn't match expected type ‘MVector
(primitive-0.6.3.0:Control.Monad.Primitive.PrimState (ST s))
Int’
with actual type ‘Int’
• In the first argument of ‘freeze’, namely ‘v’
You should be fine to write:
verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x
sort v
freeze v
giving:
> verboseCopy
[1,2,4]
>
The sort v
performs the sort as a side effect on the mutable vector v
, so there's no need to "save" or "capture" the sort result, if that's what you were worried about.
You don't need to explicitly type v
. Haskell will infer it to be a mutable vector and will treat it appropriately as an IOVector
or STVector
depending on whether you are using it within the IO or ST monad.
For your information, the reason you're getting the error is that the type you're supplying is for v
, but you've applied it to thaw x
which has a more complex type. If you write:
verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x :: ST s (STVector s Int)
sort v
freeze v
then it'll type check. However, again, this is unnecessary and won't change the behavior at all. Haskell has already figured out this type for you.