-- | This is an approximate re-implementation of "Control.Monad.ST" and "Data.STRef" using open witnesses. module Data.OpenWitness.ST ( -- * The @ST@ Monad ST,runST,fixST, -- * Converting @ST@ to @OW@ and @IO@ stToOW,RealWorld,stToIO, -- * STRefs STRef,newSTRef,readSTRef,writeSTRef,modifySTRef ) where { import Data.OpenWitness; import Data.Witness.WitnessDict; import Control.Monad.State; type ST s = StateT (WitnessDict (OpenWitness s)) (OW s); stToOW :: ST s a -> OW s a; stToOW st = evalStateT st emptyWitnessDict; runST :: (forall s . ST s a) -> a; runST st = runOW (stToOW st); fixST :: (a -> ST s a) -> ST s a; fixST = mfix; type STRef = OpenWitness; newSTRef :: a -> ST s (STRef s a); newSTRef a = do { wit <- lift newOpenWitnessOW; dict <- get; put (witnessDictAdd wit a dict); return wit; }; readSTRef :: STRef s a -> ST s a; readSTRef key = do { dict <- get; case witnessDictLookup key dict of { Just a -> return a; _ -> fail "ref not found"; }; }; writeSTRef :: forall s a. STRef s a -> a -> ST s (); writeSTRef key newa = modify (witnessDictReplace key newa); modifySTRef :: forall s a. STRef s a -> (a -> a) -> ST s (); modifySTRef key amap = modify (witnessDictModify key amap); stToIO :: ST RealWorld a -> IO a; stToIO = owToIO . stToOW; }