I want something like
f :: [forall m. (Mutable v) (PrimState m) r -> m ()] -> v r -> v r -- illegal signature
f gs x = runST $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs -- you get the idea
unsafeFreeze y
I'm essentially in the same position I was in this question where Vitus commented:
[I]f you want keep polymorphic functions inside some structure, you need either specialized data type (e.g. newtype I = I (forall a. a -> a)) or ImpredicativeTypes.
Also, see this question. The problem is, these are both really ugly solutions. So I've come up with a third alternative, which is to avoid the polymorphism altogether by running what "should" be a ST
computation in IO
instead. Thus f
becomes:
f :: [(Mutable v) RealWorld r -> IO ()] -> v r -> v r
f gs x = unsafePerformIO $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs -- you get the idea
unsafeFreeze y
I feel slightly dirty for going the unsafe
IO
route compared the to the "safe" ST
route, but if my alternative is a wrapper or impredicative types... Apparently, I'm not alone.
Is there any reason I shouldn't use unsafePerformIO
here? In this case, is it really unsafe at all? Are there performance considerations or anything else I should be aware of?
--------------EDIT----------------
An answer below shows me how to get around this problem altogether, which is great. But I'm still interested in the original question (implicaitons of runST
vs unsafePerformIO
when using mutable vectors) for educational purposes.
PolyModifier
is easier to understand thanforall m. (Mutable v) (PrimState m) r -> m ()
. Other than that, you're giving up some assurances the type systems gives you. It's hard to say whether you have here since, you haven't shown us all the code. But now you're making assertions like "x will never be ever viewed again" since you're just clobbering a pure structure – Superimposedmap PM
onto the function list. I also didn't like wrapping something that has no reason to be wrapped from a abstraction perspective: it's just a function, nothing special about it. – Kauppiforall
outside the list, as in(forall m. [Mutable v (PrimState m) r -> m ()]) -> v r -> v r
? (In other words, are you sure you need to store something polymorphic in your structure, rather than just having a polymorphic structure?) – Lyssa-XImpredicativeTypes
. – Kauppi