io-classes 1.4.0.0 → 1.4.1.0
raw patch · 3 files changed
+44/−10 lines, 3 filesdep +primitive
Dependencies added: primitive
Files
- CHANGELOG.md +8/−0
- io-classes.cabal +2/−1
- src/Control/Monad/Class/MonadST.hs +34/−9
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revsion history of io-classes +## 1.4.1.0++### Non-breaking changes++* New dependency on `primitive` package+* New `stToIO` in `MonadST`, which is simpler to use than the existing+ `withLiftST`, and depends on the `primitive` package's `PrimState` (#141).+ ## 1.4.0.0 ### Breaking changes
io-classes.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: io-classes-version: 1.4.0.0+version: 1.4.1.0 synopsis: Type classes for concurrency with STM, ST and timing description: IO Monad class hierarchy compatible with@@ -98,6 +98,7 @@ async >=2.1, bytestring, mtl >=2.2 && <2.4,+ primitive >= 0.7 && <0.10, stm >=2.5 && <2.6, time >=1.9.1 && <1.13
src/Control/Monad/Class/MonadST.hs view
@@ -1,35 +1,60 @@-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} module Control.Monad.Class.MonadST (MonadST (..)) where import Control.Monad.Reader -import Control.Monad.ST (ST, stToIO)+import Control.Monad.Primitive+import Control.Monad.ST as ST (ST, stToIO) -- | This class is for abstracting over 'stToIO' which allows running 'ST' -- actions in 'IO'. In this case it is to allow running 'ST' actions within -- another monad @m@. ----- The type of 'stToIO' is:+-- The normal type of 'stToIO' is: ----- > stToIO : ST RealWorld a -> IO a+-- > stToIO :: ST RealWorld a -> IO a ----- Abstracting over this is tricky because we need to not care about both--- the @IO@, and also the @RealWorld@.+-- We have two approaches to abstracting over this, a new and an older+-- (deprecated) method. The new method borrows the @primitive@ package's+-- 'PrimMonad' and 'PrimState' type family. This gives us: ----- A solution is to write an action that is given the @liftST@ as an argument+-- > stToIO :: ST (PrimState m) a -> m a+--+-- Which for 'IO' is exactly the same as above. For 'ST' it is identity, while+-- for @IOSim@ it is+--+-- > stToIO :: ST s a -> IOSim s a+--+-- The older (deprecated) method is tricky because we need to not care about+-- both the @IO@, and also the @RealWorld@, and it does so avoiding mentioning+-- any @s@ type (which is what the 'PrimState' type family gives access to).+-- The solution is to write an action that is given the @liftST@ as an argument -- and where that action itself is polymorphic in the @s@ parameter. This -- allows us to instantiate it with @RealWorld@ in the @IO@ case, and the local -- @s@ in a case where we are embedding into another @ST@ action. -- class Monad m => MonadST m where+ -- | @since 1.4.1.0+ stToIO :: ST (PrimState m) a -> m a++ -- | Deprecated. Use 'stToIO' instead. withLiftST :: (forall s. (forall a. ST s a -> m a) -> b) -> b +{-# DEPRECATED withLiftST "Use the simpler 'stToIO' instead." #-}+ instance MonadST IO where- withLiftST = \f -> f stToIO+ stToIO = stToPrim+ withLiftST = \f -> f ST.stToIO instance MonadST (ST s) where+ stToIO = stToPrim withLiftST = \f -> f id -instance MonadST m => MonadST (ReaderT r m) where+instance (MonadST m, PrimMonad m) => MonadST (ReaderT r m) where+ stToIO :: ST (PrimState m) a -> ReaderT r m a+ stToIO f = lift (stToPrim f)+ withLiftST f = withLiftST $ \g -> f (lift . g)