statethread (empty) → 0.1
raw patch · 9 files changed
+310/−0 lines, 9 filesdep +applicativedep +basedep +transformerssetup-changed
Dependencies added: applicative, base, transformers
Files
- LICENSE +31/−0
- Setup.lhs +3/−0
- src/Control/Monad/ST.hs +3/−0
- src/Control/Monad/ST/Lazy.hs +113/−0
- src/Control/Monad/ST/Strict.hs +64/−0
- src/Data/STRef.hs +3/−0
- src/Data/STRef/Lazy.hs +22/−0
- src/Data/STRef/Strict.hs +31/−0
- statethread.cabal +40/−0
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2009, Henning Thielemann++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * The names of contributors may not be used to endorse or promote+ products derived from this software without specific prior+ written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#! /usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ src/Control/Monad/ST.hs view
@@ -0,0 +1,3 @@+module Control.Monad.ST (module Control.Monad.ST.Strict) where++import Control.Monad.ST.Strict
+ src/Control/Monad/ST/Lazy.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE Rank2Types #-}+module Control.Monad.ST.Lazy (+ ST, runST, fixST,++ RealWorld, stToIO,++ strictToLazyST, lazyToStrictST,++ unsafeInterleaveST,+ unsafeIOToST+ ) where+++import qualified Control.Monad.ST.Strict as Strict+import Control.Monad.Trans.State (StateT(StateT), mapStateT, evalStateT, )+import Control.Monad.Trans (lift, )+import Control.Monad.Fix (MonadFix, mfix, )+import Control.Applicative (Applicative(pure, (<*>)), )+import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )++++-- * The 'ST' Monad++{- |+The lazy state thread monad provides a weak form of sequencing:+If action A is written before B, then A will be run before B.+Generally an action is run whenever its result is needed+or when a subsequent action must be run.++This sequencing is necessary,+in order to run 'writeSTRef' actions at all+and run them in the right order and interleaving with 'readSTRef'.++I used the same idea in the @lazyio@ package.+-}+newtype ST s a = ST {unST :: StateT (State s) IO a}++data State s = State+++instance Functor (ST s) where+ fmap f (ST st) = ST (fmap f st)++instance Applicative (ST s) where+ pure f = ST (pure f)+ ST f <*> ST x = ST $+ mapStateT unsafeInterleaveIO f <*>+ mapStateT unsafeInterleaveIO x++instance Monad (ST s) where+ return f = ST (return f)+ fail str = ST (fail str)+ ST x >> ST y = ST $+ mapStateT unsafeInterleaveIO x >>+ mapStateT unsafeInterleaveIO y+ ST x >>= k = ST $+ mapStateT unsafeInterleaveIO . unST . k =<<+ mapStateT unsafeInterleaveIO x+++runST :: (forall s. ST s a) -> a+runST st = unsafePerformIO (evalStateT (unST st) State)++fixST :: (a -> ST s a) -> ST s a+fixST f = ST (mfix (unST . f))++instance MonadFix (ST s) where+ mfix = fixST+++-- * Converting 'ST' to 'IO'++data RealWorld = RealWorld++stToIO :: ST RealWorld a -> IO a+stToIO = flip evalStateT State . unST+++-- * Converting between strict and lazy 'ST'++strictToLazyST :: Strict.ST s a -> ST s a+strictToLazyST =+ unsafeIOToST . Strict.unsafeSTToIO++{-+ToDo:+Do we also have to bring the monadic result into some evaluated form?+Shall we also trigger all ST actions by a 'seq'ing on the final 'State'?+-}+lazyToStrictST :: ST s a -> Strict.ST s a+lazyToStrictST =+ Strict.unsafeIOToST . flip evalStateT State . unST+++-- * Unsafe operations++unsafeInterleaveST :: ST s a -> ST s a+unsafeInterleaveST (ST st) =+ ST $ StateT $ \_ -> fmap (\x->(x,State)) (evalStateT st State)++{-+Explicitly matching the @State@ constructor+forces former actions to be run.+-}+unsafeIOToST :: IO a -> ST s a+unsafeIOToST m =+ ST $ StateT $ \State -> fmap (\x->(x,State)) m++{-+unsafeSTToIO :: ST s a -> IO a+unsafeSTToIO = unST+-}
+ src/Control/Monad/ST/Strict.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE Rank2Types #-}+module Control.Monad.ST.Strict (+ ST, runST, fixST,++ RealWorld, stToIO,++ unsafeInterleaveST,+ unsafeIOToST,+ unsafeSTToIO,+ ) where++import Control.Monad.Fix (MonadFix, mfix, )+import Control.Applicative (Applicative(pure, (<*>)), )+import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )+import System.IO (fixIO, )+++-- * The 'ST' Monad++newtype ST s a = ST {unST :: IO a}++instance Functor (ST s) where+ fmap f (ST st) = ST (fmap f st)++instance Applicative (ST s) where+ pure f = ST (pure f)+ ST f <*> ST x = ST (f <*> x)++instance Monad (ST s) where+ return f = ST (return f)+ fail str = ST (fail str)+ ST x >> ST y = ST (x >> y)+ ST x >>= k = ST (unST . k =<< x)+++runST :: (forall s. ST s a) -> a+runST st = unsafePerformIO (unST st)++fixST :: (a -> ST s a) -> ST s a+fixST f = ST (fixIO (unST . f))++instance MonadFix (ST s) where+ mfix = fixST+++-- * Converting 'ST' to 'IO'++data RealWorld = RealWorld++stToIO :: ST RealWorld a -> IO a+stToIO = unST+++-- * Unsafe operations++unsafeInterleaveST :: ST s a -> ST s a+unsafeInterleaveST (ST st) =+ ST (unsafeInterleaveIO st)++unsafeIOToST :: IO a -> ST s a+unsafeIOToST = ST++unsafeSTToIO :: ST s a -> IO a+unsafeSTToIO = unST
+ src/Data/STRef.hs view
@@ -0,0 +1,3 @@+module Data.STRef (module Data.STRef.Strict) where++import Data.STRef.Strict
+ src/Data/STRef/Lazy.hs view
@@ -0,0 +1,22 @@+module Data.STRef.Lazy (+ STRef,+ newSTRef,+ readSTRef,+ writeSTRef,+ modifySTRef,+ ) where++import Control.Monad.ST.Lazy (ST, strictToLazyST, )+import Data.STRef.Strict (STRef, )+import qualified Data.STRef.Strict as ST+++newSTRef :: a -> ST s (STRef s a)+readSTRef :: STRef s a -> ST s a+writeSTRef :: STRef s a -> a -> ST s ()+modifySTRef :: STRef s a -> (a -> a) -> ST s ()++newSTRef = strictToLazyST . ST.newSTRef+readSTRef = strictToLazyST . ST.readSTRef+writeSTRef r a = strictToLazyST (ST.writeSTRef r a)+modifySTRef r f = strictToLazyST (ST.modifySTRef r f)
+ src/Data/STRef/Strict.hs view
@@ -0,0 +1,31 @@+module Data.STRef.Strict (+ STRef,+ newSTRef,+ readSTRef,+ writeSTRef,+ modifySTRef,+ ) where++import Control.Monad.ST.Strict (ST, )+import qualified Control.Monad.ST.Strict as Strict+import qualified Data.IORef as IORef+++newtype STRef s a = STRef {unSTRef :: IORef.IORef a}+++newSTRef :: a -> ST s (STRef s a)+newSTRef a =+ Strict.unsafeIOToST (fmap STRef (IORef.newIORef a))++readSTRef :: STRef s a -> ST s a+readSTRef ref =+ Strict.unsafeIOToST (IORef.readIORef (unSTRef ref))++writeSTRef :: STRef s a -> a -> ST s ()+writeSTRef ref a =+ Strict.unsafeIOToST (IORef.writeIORef (unSTRef ref) a)++modifySTRef :: STRef s a -> (a -> a) -> ST s ()+modifySTRef ref f =+ Strict.unsafeIOToST (IORef.modifyIORef (unSTRef ref) f)
+ statethread.cabal view
@@ -0,0 +1,40 @@+Name: statethread+Version: 0.1+License: BSD3+License-File: LICENSE+Maintainer: haskell@henning-thielemann.de+Synopsis: The ST monad and STRefs+Category: Data Structures, Monads+Description:+ The ST monad and STRefs in a portable form.+ This package implements state threads as wrapper around IO and IORefs.+ Your compiler must support rank-2-types, IORefs,+ unsafePerformIO and unsafeInterleaveIO.+ The package can be used as drop-in replacement for the 'st' package.+Build-Type: Simple+Cabal-Version: >=1.6+Tested-With: JHC==0.7.3++Source-Repository this+ Tag: 0.1+ Type: darcs+ Location: http://darcs.haskell.org/packages/statethread/++Source-Repository head+ Type: darcs+ Location: http://darcs.haskell.org/packages/statethread/++Library+ Build-Depends:+ transformers >=0.0 && <0.2,+ applicative >=1.0 && <1.1,+ base >=1.0 && <2+ Extensions: Rank2Types+ Hs-Source-Dirs: src+ Exposed-Modules:+ Control.Monad.ST+ Control.Monad.ST.Lazy+ Control.Monad.ST.Strict+ Data.STRef+ Data.STRef.Lazy+ Data.STRef.Strict