monad-classes 0.3.1.1 → 0.3.2.0
raw patch · 6 files changed
+102/−5 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Monad.Classes.Proxied: instance Alternative m => Alternative (Proxied x m)
- Control.Monad.Classes.Proxied: instance Applicative m => Applicative (Proxied x m)
- Control.Monad.Classes.Proxied: instance Functor m => Functor (Proxied x m)
- Control.Monad.Classes.Proxied: instance Monad m => Monad (Proxied x m)
- Control.Monad.Classes.Proxied: instance MonadBase b m => MonadBase b (Proxied x m)
- Control.Monad.Classes.Proxied: instance MonadIO m => MonadIO (Proxied x m)
- Control.Monad.Classes.Proxied: instance MonadPlus m => MonadPlus (Proxied x m)
- Control.Monad.Classes.Proxied: instance MonadTrans (Proxied x)
- Control.Monad.Classes.Proxied: instance MonadTransControl (Proxied x)
+ Control.Monad.Classes: type family Down n m :: * -> *;
+ Control.Monad.Classes: }
+ Control.Monad.Classes.Proxied: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance Control.Monad.Trans.Class.MonadTrans (Control.Monad.Classes.Proxied.Proxied x)
+ Control.Monad.Classes.Proxied: instance Control.Monad.Trans.Control.MonadTransControl (Control.Monad.Classes.Proxied.Proxied x)
+ Control.Monad.Classes.Proxied: instance GHC.Base.Alternative m => GHC.Base.Alternative (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance GHC.Base.Applicative m => GHC.Base.Applicative (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Proxied: instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Control.Monad.Classes.Proxied.Proxied x m)
+ Control.Monad.Classes.Run: ReadStateT :: (IdentityT m a) -> ReadStateT s m a
+ Control.Monad.Classes.Run: newtype ReadStateT s m a
+ Control.Monad.Classes.Run: runReadState :: Proxy s -> ReadStateT s m a -> m a
- Control.Monad.Classes: ask :: MonadReader r m => m r
+ Control.Monad.Classes: ask :: forall m r. MonadReader r m => m r
- Control.Monad.Classes: class MonadLiftN (n :: Peano) m where type family Down n m :: * -> *
+ Control.Monad.Classes: class MonadLiftN (n :: Peano) m where type Down n m :: * -> * where {
- Control.Monad.Classes: exec :: MonadExec w m => w a -> m a
+ Control.Monad.Classes: exec :: forall w m a. MonadExec w m => w a -> m a
- Control.Monad.Classes: local :: MonadLocal r m => (r -> r) -> m a -> m a
+ Control.Monad.Classes: local :: forall a m r. MonadLocal r m => (r -> r) -> m a -> m a
- Control.Monad.Classes: state :: MonadState s m => (s -> (a, s)) -> m a
+ Control.Monad.Classes: state :: forall s m a. (MonadState s m) => (s -> (a, s)) -> m a
- Control.Monad.Classes: tell :: MonadWriter w m => w -> m ()
+ Control.Monad.Classes: tell :: forall w m. MonadWriter w m => w -> m ()
- Control.Monad.Classes: throw :: MonadExcept e m => e -> m a
+ Control.Monad.Classes: throw :: forall a e m. MonadExcept e m => e -> m a
- Control.Monad.Classes.Proxied: class Reifies (s :: k) a | s -> a
+ Control.Monad.Classes.Proxied: class Reifies k (s :: k) a | s -> a
- Control.Monad.Classes.Proxied: data Proxy# :: k -> (#)
+ Control.Monad.Classes.Proxied: data Proxy# :: forall k. k -> TYPE VoidRep
- Control.Monad.Classes.Run: evalWriterWith :: (w -> m ()) -> CustomWriterT w m a -> m a
+ Control.Monad.Classes.Run: evalWriterWith :: forall w m a. (w -> m ()) -> CustomWriterT w m a -> m a
- Control.Monad.Classes.Run: mapWriter :: MonadWriter w2 m => (w1 -> w2) -> CustomWriterT w1 m a -> m a
+ Control.Monad.Classes.Run: mapWriter :: forall w1 w2 m a. MonadWriter w2 m => (w1 -> w2) -> CustomWriterT w1 m a -> m a
- Control.Monad.Classes.Run: runZoom :: (forall f. Functor f => (small -> f small) -> big -> f big) -> ZoomT big small m a -> m a
+ Control.Monad.Classes.Run: runZoom :: forall big small m a. (forall f. Functor f => (small -> f small) -> big -> f big) -> ZoomT big small m a -> m a
- Control.Monad.Classes.Run: type CustomWriterT w m a = CustomWriterT' w m m a
+ Control.Monad.Classes.Run: type CustomWriterT w m = CustomWriterT' w m m
Files
- Control/Monad/Classes/ReadState.hs +49/−0
- Control/Monad/Classes/Reader.hs +8/−0
- Control/Monad/Classes/Run.hs +4/−0
- Control/Monad/Classes/Writer.hs +1/−1
- monad-classes.cabal +3/−2
- tests/test.hs +37/−2
+ Control/Monad/Classes/ReadState.hs view
@@ -0,0 +1,49 @@+module Control.Monad.Classes.ReadState where++import Control.Monad.Classes.Core+import Control.Monad.Classes.Effects+import Control.Monad.Classes.Reader+import Control.Monad.Classes.State+import Control.Monad.Trans.Identity+import Control.Monad.Trans.Class+import Control.Applicative+import Control.Monad.Base+import Control.Monad.Trans.Control+import Data.Peano+import Data.Proxy++-- | 'ReadState' is used to translate reader effects into state effects.+--+-- If you run a computation with 'StateT', this handler is not needed,+-- since 'StateT' already handles read requests.+--+-- This is useful in cases when you work in an abstract 'MonadState' monad+-- and thus have no guarantee that its handler will also accept reader+-- requests.+newtype ReadStateT s m a = ReadStateT (IdentityT m a)+ deriving (Functor, Applicative, Monad, MonadTrans)++runReadState :: Proxy s -> ReadStateT s m a -> m a+runReadState _ (ReadStateT (IdentityT a)) = a++type instance CanDo (ReadStateT s m) eff = ReadStateCanDo s eff++type family ReadStateCanDo s eff where+ ReadStateCanDo s (EffReader s) = True+ ReadStateCanDo s eff = False++instance MonadState s m => MonadReaderN Zero s (ReadStateT s m) where+ askN _ = ReadStateT (IdentityT get)++instance MonadBase b m => MonadBase b (ReadStateT x m) where+ liftBase = lift . liftBase++instance MonadTransControl (ReadStateT x) where+ type StT (ReadStateT s) a = StT IdentityT a+ liftWith = defaultLiftWith ReadStateT (\(ReadStateT a) -> a)+ restoreT = defaultRestoreT ReadStateT++instance MonadBaseControl b m => MonadBaseControl b (ReadStateT s m) where+ type StM (ReadStateT s m) a = StM m a+ liftBaseWith = defaultLiftBaseWith+ restoreM = defaultRestoreM
Control/Monad/Classes/Reader.hs view
@@ -11,6 +11,8 @@ type instance CanDo (R.ReaderT e m) eff = ReaderCanDo e eff +type instance CanDo ((->) e) eff = ReaderCanDo e eff+ type family ReaderCanDo e eff where ReaderCanDo e (EffReader e) = True ReaderCanDo e (EffLocal e) = True@@ -28,6 +30,9 @@ instance Monad m => MonadReaderN Zero r (SS.StateT r m) where askN _ = SS.get +instance MonadReaderN Zero r ((->) r) where+ askN _ = id+ instance (MonadTrans t, Monad (t m), MonadReaderN n r m, Monad m) => MonadReaderN (Succ n) r (t m) where@@ -52,6 +57,9 @@ instance (Monad m) => MonadLocalN Zero r (SS.StateT r m) where localN _ = stateLocal SS.put SS.get++instance MonadLocalN Zero r ((->) r) where+ localN _ = flip (.) instance (MonadTrans t, Monad (t m), MFunctor t, MonadLocalN n r m, Monad m) => MonadLocalN (Succ n) r (t m)
Control/Monad/Classes/Run.hs view
@@ -34,6 +34,9 @@ -- * Zoom , runZoom , ZoomT(..)+ -- * ReadState+ , ReadStateT(..)+ , runReadState ) where import Data.Functor.Identity@@ -42,6 +45,7 @@ import Control.Monad.Classes.Writer import Control.Monad.Classes.Reader import Control.Monad.Classes.Except+import Control.Monad.Classes.ReadState run :: Identity a -> a run = runIdentity
Control/Monad/Classes/Writer.hs view
@@ -80,7 +80,7 @@ -- the MonadTransControl instance newtype CustomWriterT' w n m a = CustomWriterT (Proxied (w -> n ()) m a) deriving (Functor, Applicative, Monad, Alternative, MonadPlus, MonadBase b, MonadIO)-type CustomWriterT w m a = CustomWriterT' w m m a+type CustomWriterT w m = CustomWriterT' w m m instance MonadTrans (CustomWriterT' w n) where lift a = CustomWriterT $ Proxied $ \_ -> a
monad-classes.cabal view
@@ -1,5 +1,5 @@ name: monad-classes-version: 0.3.1.1+version: 0.3.2.0 synopsis: more flexible mtl -- description: homepage: https://github.com/strake/monad-classes.hs@@ -27,7 +27,8 @@ Control.Monad.Classes.Exec, Control.Monad.Classes.Zoom, Control.Monad.Classes.Core,- Control.Monad.Classes.Effects+ Control.Monad.Classes.Effects,+ Control.Monad.Classes.ReadState build-depends: base >=4.7 && <5, peano >=0.1,
tests/test.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, NoMonomorphismRestriction, DataKinds, TypeFamilies, TemplateHaskell, ScopedTypeVariables,- MagicHash #-}+ MagicHash, FlexibleContexts #-} import Test.Tasty import Test.Tasty.HUnit import Control.Monad.Trans.Class@@ -12,6 +12,7 @@ import Control.Applicative import Control.Exception hiding (throw) import Data.Lens.Light+import Data.Proxy import GHC.Prim (Proxy#, proxy#) -- for IO tests@@ -35,7 +36,8 @@ tests :: TestTree tests = testGroup "Tests"- [ simpleStateTests+ [ readerTests+ , simpleStateTests , twoStatesTests , liftingTest , localState@@ -45,8 +47,31 @@ , liftNTests , liftConduitTest , mapWriterTest+ , readStateTest ] +readerTests = testGroup "Reader Tests"+ [ testCase "ask" $+ let base = 5 :: Integer+ power = 3 :: Int+ expected = 125 :: Integer+ in (runReader power action) base @?= expected+ , testCase "local ask" $+ let base = 5 :: Integer+ power = 2 :: Int+ altBase = 7 :: Integer+ altPower = 3 :: Int+ expected = 174 :: Integer+ action' = do+ x <- local (const altBase) action+ y <- local (const altPower) action+ pure (x + y)+ in (runReader power action') base @?= expected+ ]+ where+ f = (^) :: Integer -> Int -> Integer+ action = f <$> ask <*> ask+ simpleStateTests = testGroup "Simple State" [ testCase "get" $ (run $ runStateLazy (0 :: Int) get) @?= (0 :: Int, 0 :: Int)@@ -154,3 +179,13 @@ mapWriterTest = testCase "mapWriter" $ do run (execWriterStrict $ mapWriter (\(w :: Char) -> [w]) $ do { tell 'a'; tell 'b'; tell 'c' }) @?= "abc"++readStateTest = testCase "ReadState" $ do+ let+ a1 :: MonadReader Char m => m Char+ a1 = ask++ a2 :: MonadState Char m => m Char+ a2 = runReadState (Proxy :: Proxy Char) a1++ run (evalStateStrict 'w' a2) @?= 'w'