<div dir="ltr">Even simpler, Freezer could just be a Monad denoting arbitrary "cleanup" actions, as long as they don't involve writes.<br><div><br></div><div><br></div><div>-- | A computation that is guaranteed to run after all modifications are complete.<br></div><div>newtype Freeze s a = {- private constructor and accessor -} Freeze { getFreeze :: ST s a } deriving (Functor, Applicative, Monad)</div><div><br></div><div>freezeArray :: (Ix i, MArray a e (ST s), IArray b e) => a i e -> Freeze s (b i e)</div><div>freezeArray arr = Freeze (unsafeFreeze arr)</div><div><br></div><div>-- Reads are fine too, just not writes<br></div><div>freezeRef :: STRef s a -> Freeze s a<br></div><div>freezeRef ref = Freeze (readSTRef ref)<br></div><div><br></div><div>runSTFreeze :: (forall s . ST s (Freeze s a)) -> a</div><div>runSTFreeze act = runST (act >>= getFreeze)</div><div><br></div><div><br></div><div><br></div><div>The proposed -Trav and -With functions can be implemented straightforwardly from that if desired:<br>runSTArrayTrav m = runSTFreeze (m >>= traverse freezeArray)<br>runSTUArrayTrav m = runSTFreeze (m >>= traverse freezeArray)<br>runSTArrayWith tr m = runSTFreeze (m >>= tr freezeArray freezeArray)</div></div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Aug 21, 2019 at 11:46 PM Henning Thielemann <<a href="mailto:lemming@henning-thielemann.de">lemming@henning-thielemann.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
On Wed, 21 Aug 2019, Zemyla wrote:<br>
<br>
> The "runSTArray" and "runSTUArray" functions allow efficiently working <br>
> with Arrays in the ST monad before turning them immutable<br>
<br>
I think instead of some new functions we should have a Kleisli Arrow data <br>
type that hides unsafeFreeze for us.<br>
<br>
newtype Freezer s a b =<br>
    -- private constructor and accessor<br>
    Freezer {getFreezer :: a -> ST s b}<br>
<br>
instance Category Freezer where<br>
instance Arrow Freezer where<br>
<br>
quickFreeze :: Freezer s (STArray s i e) (Array i e)<br>
quickFreeze = Freezer unsafeFreeze<br>
<br>
runFrozen :: (forall s. Freezer s a b) -> (forall s. ST s a) -> b<br>
runFrozen freezer st = runST (getFreezer (freezer st))<br>
<br>
<br>
For moving two arrays and an additional value out, you would do<br>
<br>
runFrozen ((quickFreeze *** quickFreeze) *** id) st<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>