-- * Boxed arrays
STArray, -- instance of: Eq, MArray
+ runSTArray,
-- * Unboxed arrays
STUArray, -- instance of: Eq, MArray
+ runSTUArray,
castSTUArray, -- :: STUArray s i a -> ST s (STUArray s i b)
-- * Overloaded mutable array interface
import Prelude
import Data.Array.MArray
-import Data.Array.Base ( STUArray, castSTUArray )
+import Data.Array.Base ( STUArray, castSTUArray, UArray, unsafeFreezeSTUArray )
+import Control.Monad.ST ( ST, runST )
#ifdef __HUGS__
import Hugs.ST ( STArray )
#endif
#ifdef __GLASGOW_HASKELL__
-import GHC.Arr ( STArray )
+import GHC.Arr ( STArray, Array )
#endif
+
+-- | A safe way to create and work with a mutable array before returning an
+-- immutable array for later perusal. This function avoids copying
+-- the array before returning it - it uses 'unsafeFreeze' internally, but
+-- this wrapper is a safe interface to that function.
+--
+runSTArray :: (Ix i)
+ => (forall s . ST s (STArray s i e))
+ -> Array i e
+runSTArray st = runST (st >>= unsafeFreeze)
+
+-- | A safe way to create and work with an unboxed mutable array before
+-- returning an immutable array for later perusal. This function
+-- avoids copying the array before returning it - it uses
+-- 'unsafeFreeze' internally, but this wrapper is a safe interface to
+-- that function.
+--
+runSTUArray :: (Ix i)
+ => (forall s . ST s (STUArray s i e))
+ -> UArray i e
+runSTUArray st = runST (st >>= unsafeFreezeSTUArray)
+
+
+-- INTERESTING... this is the type we'd like to give to runSTUArray:
+--
+-- runSTUArray :: (Ix i, IArray UArray e,
+-- forall s. MArray (STUArray s) e (ST s))
+-- => (forall s . ST s (STUArray s i e))
+-- -> UArray i e
+--
+-- Note the quantified constraint. We dodged the problem by using
+-- unsafeFreezeSTUArray directly in the defn of runSTUArray above, but
+-- this essentially constrains us to a single unsafeFreeze for all STUArrays
+-- (in theory we might have a different one for certain element types).