phantom-state 0.1.0.0 → 0.2.0.0
raw patch · 4 files changed
+173/−79 lines, 4 filesdep +criteriondep +phantom-statedep +vectordep ~transformersPVP ok
version bump matches the API change (PVP)
Dependencies added: criterion, phantom-state, vector
Dependency ranges changed: transformers
API changes (from Hackage documentation)
- Control.Monad.PhantomState: PhantomStateT :: (s -> m s) -> PhantomStateT s m a
- Control.Monad.PhantomState: changeState :: Applicative m => (s -> s) -> PhantomStateT s m ()
- Control.Monad.PhantomState: instance Functor (PhantomStateT s m)
- Control.Monad.PhantomState: instance Monad m => Applicative (PhantomStateT s m)
- Control.Monad.PhantomState: instance Monad m => Monad (PhantomStateT s m)
- Control.Monad.PhantomState: instance MonadTrans (PhantomStateT s)
- Control.Monad.PhantomState: newtype PhantomStateT s m a
- Control.Monad.PhantomState: runPhantomState :: PhantomState s a -> s -> s
- Control.Monad.PhantomState: runPhantomStateT :: PhantomStateT s m a -> s -> m s
- Control.Monad.PhantomState: type PhantomState s a = PhantomStateT s Identity a
- Control.Monad.PhantomState: useState :: Applicative m => (s -> m a) -> PhantomStateT s m ()
+ Control.Applicative.PhantomState: changeState :: Applicative m => (s -> s) -> PhantomStateT s m ()
+ Control.Applicative.PhantomState: data PhantomStateT s m a
+ Control.Applicative.PhantomState: instance Functor (PhantomStateT s m)
+ Control.Applicative.PhantomState: instance Monad m => Applicative (PhantomStateT s m)
+ Control.Applicative.PhantomState: runPhantomState :: PhantomState s a -> s -> s
+ Control.Applicative.PhantomState: runPhantomStateT :: PhantomStateT s m a -> s -> m s
+ Control.Applicative.PhantomState: type PhantomState s = PhantomStateT s Identity
+ Control.Applicative.PhantomState: useAndChangeState :: (s -> m s) -> PhantomStateT s m ()
+ Control.Applicative.PhantomState: useState :: Applicative m => (s -> m a) -> PhantomStateT s m ()
Files
- Control/Applicative/PhantomState.hs +100/−0
- Control/Monad/PhantomState.hs +0/−77
- bench/Main.hs +54/−0
- phantom-state.cabal +19/−2
+ Control/Applicative/PhantomState.hs view
@@ -0,0 +1,100 @@++-- | Phantom State Transformer type and functions.+module Control.Applicative.PhantomState (+ PhantomStateT+ , PhantomState+ , useState+ , changeState+ , useAndChangeState+ , runPhantomStateT+ , runPhantomState+ ) where++import Control.Applicative+import Data.Functor.Identity++-- | The Phantom State Transformer is like the+-- State Monad Transformer, but it does not hold+-- any value. Therefore, it automatically discards+-- the result of any computation. Only changes in+-- the state and effects will remain. This transformer+-- produces a new 'Applicative' functor from any 'Monad'.+-- The primitive operations in this functor are:+--+-- * 'useState': Performs effects. State is unchanged.+-- * 'changeState': Changes state. No effect is performed.+-- * 'useAndChangeState': Changes state and performs effects.+--+-- Although 'useState' and 'changeState' are defined in+-- terms of 'useAndChangeState':+--+-- > useState f = useAndChangeState (\s -> f s *> pure s)+-- > changeState f = useAndChangeState (pure . f)+--+-- So 'useAndChangeState' is the only actual primitive.+--+-- Use 'runPhantomStateT' (or 'runPhantomState') to get+-- the result of a phantom state computation.+--+newtype PhantomStateT s m a = PhantomStateT (s -> m s)++-- | Type synonym of 'PhantomStateT' where the underlying 'Monad' is the 'Identity' monad.+type PhantomState s = PhantomStateT s Identity++-- | Perform an applicative action using the current state, leaving+-- the state unchanged. The result will be discarded, so only the+-- effect will remain.+useState :: Applicative m => (s -> m a) -> PhantomStateT s m ()+{-# INLINE useState #-}+useState f = useAndChangeState $ \s -> f s *> pure s++-- | Modify the state using a pure function. No effect will be produced,+-- only the state will be modified.+changeState :: Applicative m => (s -> s) -> PhantomStateT s m ()+{-# INLINE changeState #-}+changeState f = useAndChangeState $ \s -> pure (f s)++-- | Combination of 'useState' and 'changeState'. It allows you to change the state while+-- performing any effects. The new state will be the result of applying the argument+-- function to the old state. The following equations hold:+--+-- > useState f *> changeState g }+-- > } = useAndChangeState (\s -> f s *> g s)+-- > changeState g *> useState f }+--+useAndChangeState :: (s -> m s) -> PhantomStateT s m ()+{-# INLINE useAndChangeState #-}+useAndChangeState = PhantomStateT++-- | Perform a phantom state computation by setting an initial state+-- and running all the actions from there.+runPhantomStateT :: PhantomStateT s m a -- ^ Phantom state computation+ -> s -- ^ Initial state+ -> m s -- ^ Final result+{-# INLINE runPhantomStateT #-}+runPhantomStateT (PhantomStateT f) x = f x++-- | Specialized version of 'runPhantomStateT' where the underlying+-- 'Monad' is the 'Identity' monad.+runPhantomState :: PhantomState s a -- ^ Phantom state computation+ -> s -- ^ Initial state+ -> s -- ^ Final result+{-# INLINE runPhantomState #-}+runPhantomState f = runIdentity . runPhantomStateT f++-- Instances++instance Functor (PhantomStateT s m) where+ {-# INLINE fmap #-}+ fmap _ (PhantomStateT f) = PhantomStateT f++instance Monad m => Applicative (PhantomStateT s m) where+ {-# INLINE pure #-}+ pure _ = PhantomStateT return+ {-# INLINE (<*>) #-}+ PhantomStateT f <*> PhantomStateT g = PhantomStateT (\x -> f x >>= g)+ {-# INLINE (*>) #-}+ PhantomStateT f *> PhantomStateT g = PhantomStateT (\x -> f x >>= g)+ {-# INLINE (<*) #-}+ PhantomStateT f <* PhantomStateT g = PhantomStateT (\x -> f x >>= g)+
− Control/Monad/PhantomState.hs
@@ -1,77 +0,0 @@---- | Phantom Monad State Transformer constructor and functions.-module Control.Monad.PhantomState (- PhantomStateT (..)- , PhantomState- , useState- , changeState- , runPhantomStateT- , runPhantomState- ) where--import Control.Applicative-import Control.Monad.Trans.Class-import Data.Functor.Identity---- | The Phantom State Monad Transformer is like the--- State Monad Transformer, but it does not hold--- any value.-newtype PhantomStateT s m a = PhantomStateT (s -> m s)---- | Type synonym of 'PhantomStateT' where the underlying 'Monad' is the 'Identity' monad.-type PhantomState s a = PhantomStateT s Identity a---- | Perform an applicative action using the current state, leaving--- the state unchanged.-useState :: Applicative m => (s -> m a) -> PhantomStateT s m ()-{-# INLINE useState #-}-useState f = PhantomStateT $ \x -> f x *> pure x---- | Modify the state using a pure function.-changeState :: Applicative m => (s -> s) -> PhantomStateT s m ()-{-# INLINE changeState #-}-changeState f = PhantomStateT $ pure . f---- | Perform a phantom state computation by setting an initial state--- and running all the actions from there.-runPhantomStateT :: PhantomStateT s m a -- ^ Phantom state computation- -> s -- ^ Initial state- -> m s -- ^ Final result-{-# INLINE runPhantomStateT #-}-runPhantomStateT (PhantomStateT f) x = f x---- | Specialized version of 'runPhantomStateT' where the underlying--- 'Monad' is the 'Identity' monad.-runPhantomState :: PhantomState s a -- ^ Phantom state computation- -> s -- ^ Initial state- -> s -- ^ Final result-{-# INLINE runPhantomState #-}-runPhantomState f = runIdentity . runPhantomStateT f---- Instances--instance Functor (PhantomStateT s m) where- {-# INLINE fmap #-}- fmap _ (PhantomStateT f) = PhantomStateT f--instance Monad m => Applicative (PhantomStateT s m) where- {-# INLINE pure #-}- pure _ = PhantomStateT return- {-# INLINE (<*>) #-}- PhantomStateT f <*> PhantomStateT g = PhantomStateT (\x -> f x >>= g)- {-# INLINE (*>) #-}- PhantomStateT f *> PhantomStateT g = PhantomStateT (\x -> f x >>= g)- {-# INLINE (<*) #-}- PhantomStateT f <* PhantomStateT g = PhantomStateT (\x -> f x >>= g)--instance Monad m => Monad (PhantomStateT s m) where- {-# INLINE return #-}- return = pure- {-# INLINE (>>=) #-}- x >>= f = x *> f undefined- {-# INLINE (>>) #-}- (>>) = (*>)--instance MonadTrans (PhantomStateT s) where- {-# INLINE lift #-}- lift m = PhantomStateT (\x -> m >> return x)
+ bench/Main.hs view
@@ -0,0 +1,54 @@++import Criterion.Main++-- vectors+import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.Unboxed.Mutable as MV++-- functors+import Control.Applicative+import Control.Monad (mapM_,replicateM)+import Data.Foldable (sequenceA_)+import Control.Monad.Trans.Class+-- state+import Control.Monad.Trans.State++-- phantom-state+import Control.Applicative.PhantomState++createVector1 :: Int -> V.Vector Int+createVector1 n = V.create $ do+ v <- MV.unsafeNew n+ let step = do + i <- get+ lift $ MV.write v i i+ put (i+1)+ execStateT (replicateM n step) 0+ return v++replicateA_ :: Applicative f => Int -> f a -> f ()+replicateA_ n f = sequenceA_ (replicate n f)++createVector2 :: Int -> V.Vector Int+createVector2 n = V.create $ do+ v <- MV.unsafeNew n+ let step = useState (\i -> MV.write v i i)+ *> changeState (+1)+ runPhantomStateT (replicateA_ n step) 0+ return v++createVector3 :: Int -> V.Vector Int+createVector3 n = V.create $ do+ v <- MV.unsafeNew n+ mapM_ (\i -> MV.write v i i) [0..n-1]+ return v++main :: IO ()+main = defaultMain+ [ bgroup "vector"+ [ bench "generate" $ nf (\i -> V.generate i id) 10000+ , bench "state" $ nf createVector1 10000+ , bench "phantom-state" $ nf createVector2 10000+ , bench "mapM_" $ nf createVector3 10000+ ]+ ]
phantom-state.cabal view
@@ -1,5 +1,5 @@ name: phantom-state-version: 0.1.0.0+version: 0.2.0.0 synopsis: Phantom State Monad Transformer. Like State Monad, but without values. description: A monad transformer that mimics the State Monad Transformer from the <http://hackage.haskell.org/package/transformers transformers> package,@@ -10,13 +10,30 @@ license-file: LICENSE author: Daniel Díaz maintainer: dhelta.diaz@gmail.com+bug-reports: https://github.com/Daniel-Diaz/phantom-state/issues category: Control build-type: Simple cabal-version: >=1.10 +Source-repository head+ type: git+ location: git://github.com/Daniel-Diaz/phantom-state.git+ library- exposed-modules: Control.Monad.PhantomState+ exposed-modules: Control.Applicative.PhantomState build-depends: base == 4.* , transformers >= 0.3 && < 0.5 default-language: Haskell2010 ghc-options: -O2 -Wall++benchmark phantom-state-bench+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: bench+ main-is: Main.hs+ build-depends: base == 4.*+ , criterion+ , vector+ , phantom-state+ , transformers+ ghc-options: -O2