Traversing versions of runSTArray and runSTUArray
A lot of the time, I find myself wanting to calculate an array in the ST monad and either return a different value to show that the calculated array is invalid or return extra information with the array. However, the interfaces in Data.Array.ST
make it difficult to impossible to do the first (if the array has a specific structure, then you can make "sentinel" values that don't share that structure, and outright impossible to do the second.
Something like the following would be ideal:
runSTArrayMany :: Traversable t => (forall s. ST s (t (STArray s i e))) -> t (Array i e)
runSTArrayMany st = runST (st >>= traverse unsafeFreezeSTArray)
runSTUArrayMany :: Traversable t => (forall s. ST s (t (STUArray s i e))) -> t (UArray i e)
runSTUArrayMany st = runST (st >>= traverse unsafeFreezeSTUArray)
And, while this wouldn't be necessary, it would be nice to have for data structures that can potentially return multiple arrays of different types. The first argument is pretty much a lens
-style traversal.
runSTArrayMulti :: (forall f s. Applicative f => (forall i e. STArray s i e -> f (Array i e)) -> (forall i e. STUArray s i e -> f (UArray i e)) -> u s -> f v) -> (forall s. ST s (u s)) -> v
runSTArrayMulti tr st = runST (st >>= tr unsafeFreezeSTArray unsafeFreezeSTUArray)
One possible problem is if the same array is in, for instance, a list several times, and freezing an array isn't idempotent. I honestly can't think of any reason in the underlying code why it wouldn't be, though.