packages feed

simple-effects 0.1.0.1 → 0.1.0.2

raw patch · 6 files changed

+220/−165 lines, 6 files

Files

bench/Bench.hs view
@@ -1,23 +1,23 @@-{-# LANGUAGE FlexibleContexts #-}
-import Interlude
-
-import GHC.IO.Encoding (setLocaleEncoding, utf16)
-import Control.Effects
-import Control.Effects.State hiding (mtlSimple, effectsSimple)
-
-import Criterion.Main
-
-mtlSimple :: MonadState Int m => m ()
-mtlSimple = replicateM_ 1000000 mtlSimple'
-    where mtlSimple' = modify' (+ 1)
-
-effectsSimple :: (MonadEffect (GetState Int) m, MonadEffect (SetState Int) m) => m ()
-effectsSimple = replicateM_ 1000000 effectsSimple'
-    where effectsSimple' = setState . (+ (1 :: Int)) =<< getState
-
-main :: IO ()
-main =
-    defaultMain
-        [ bench "MTL state" $ nfIO (execStateT mtlSimple 0)
-        , bench "Effects state" $ nfIO (handleStateIO (0 :: Int) (effectsSimple >> getState) :: IO Int)
-        ]
+{-# LANGUAGE FlexibleContexts #-}+import Interlude++import GHC.IO.Encoding (setLocaleEncoding, utf16)+import Control.Effects+import Control.Effects.State hiding (mtlSimple, effectsSimple)++import Criterion.Main++mtlSimple :: MonadState Int m => m ()+mtlSimple = replicateM_ 1000000 mtlSimple'+    where mtlSimple' = modify' (+ 1)++effectsSimple :: (MonadEffect (GetState Int) m, MonadEffect (SetState Int) m) => m ()+effectsSimple = replicateM_ 1000000 effectsSimple'+    where effectsSimple' = setState . (+ (1 :: Int)) =<< getState++main :: IO ()+main =+    defaultMain+        [ bench "MTL state" $ nfIO (execStateT mtlSimple 0)+        , bench "Effects state" $ nfIO (handleStateIO (0 :: Int) (effectsSimple >> getState) :: IO Int)+        ]
simple-effects.cabal view
@@ -1,19 +1,20 @@ name:                simple-effects-version:             0.1.0.1-synopsis:            Simple project template from stack+version:             0.1.0.2+synopsis:            A simple effect system that integrates with MTL description:         Please see README.md-homepage:            https://github.com/githubuser/simple-effects#readme+homepage:            https://gitlab.com/LukaHorvat/simple-effects license:             BSD3 license-file:        LICENSE-author:              Author name here-maintainer:          example@example.com-copyright:           2016 Author name here-category:            Web+author:              Luka Horvat+maintainer:          luka.horvat9@gmail.com+copyright:           2016 Luka Horvat+category:            Control build-type:          Simple cabal-version:       >=1.10  library   exposed-modules:     Control.Effects+                     , Control.Effects1                      , Control.Effects.State                      , Control.Effects.Reader   hs-source-dirs:      src
src/Control/Effects.hs view
@@ -1,48 +1,50 @@-{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, DeriveFunctor
-           , GeneralizedNewtypeDeriving, UndecidableInstances, StandaloneDeriving
-           , IncoherentInstances #-}
-module Control.Effects where
-
-import Interlude
-
-import Control.Monad.Reader
-import Control.Monad.Trans.Control
-import Control.Monad.Base
-
-type family EffectMsg eff :: *
-type family EffectRes eff :: *
-
-class Monad m => MonadEffect eff m where
-    -- | Use the effect described by 'eff'.
-    effect :: proxy eff -> EffectMsg eff -> m (EffectRes eff)
-
--- | The 'EffectHandler' is rally just a 'ReaderT' carrying around the function that knows how to
---   handle the effect.
-newtype EffectHandler eff m a = EffectHandler
-    { unpackEffectHandler :: ReaderT (EffectMsg eff -> m (EffectRes eff)) m a }
-    deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadCatch, MonadThrow, MonadRandom)
-
-instance MonadTrans (EffectHandler eff) where
-    lift = EffectHandler . lift
-
-instance MonadReader s m => MonadReader s (EffectHandler eff m) where
-    ask = EffectHandler (lift ask)
-    local f (EffectHandler rdr) = EffectHandler (ReaderT $ local f . runReaderT rdr)
-
-deriving instance MonadBase IO m => MonadBase IO (EffectHandler eff m)
-
-instance MonadBaseControl IO m => MonadBaseControl IO (EffectHandler eff m) where
-    type StM (EffectHandler eff m) a = StM (ReaderT (EffectMsg eff -> m (EffectRes eff)) m) a
-    liftBaseWith f = EffectHandler $ liftBaseWith $ \q -> f (q . unpackEffectHandler)
-    restoreM = EffectHandler . restoreM
-
-instance {-# OVERLAPPABLE #-} (MonadEffect eff m, MonadTrans t, Monad (t m))
-         => MonadEffect eff (t m) where
-    effect p msg = lift (effect p msg)
-
-instance Monad m => MonadEffect eff (EffectHandler eff m) where
-    effect _ msg = EffectHandler (ReaderT ($ msg))
-
--- | Handle the effect described by 'eff'.
-handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a
-handleEffect f eh = runReaderT (unpackEffectHandler eh) f
+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, DeriveFunctor+           , GeneralizedNewtypeDeriving, UndecidableInstances, StandaloneDeriving+           , IncoherentInstances #-}+module Control.Effects (module Control.Effects, module Control.Effects1) where++import Interlude++import Control.Monad.Reader+import Control.Monad.Trans.Control+import Control.Monad.Base++import Control.Effects1++type family EffectMsg eff :: *+type family EffectRes eff :: *++class Monad m => MonadEffect eff m where+    -- | Use the effect described by 'eff'.+    effect :: proxy eff -> EffectMsg eff -> m (EffectRes eff)++-- | The 'EffectHandler' is rally just a 'ReaderT' carrying around the function that knows how to+--   handle the effect.+newtype EffectHandler eff m a = EffectHandler+    { unpackEffectHandler :: ReaderT (EffectMsg eff -> m (EffectRes eff)) m a }+    deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadCatch, MonadThrow, MonadRandom)++instance MonadTrans (EffectHandler eff) where+    lift = EffectHandler . lift++instance MonadReader s m => MonadReader s (EffectHandler eff m) where+    ask = EffectHandler (lift ask)+    local f (EffectHandler rdr) = EffectHandler (ReaderT $ local f . runReaderT rdr)++deriving instance MonadBase IO m => MonadBase IO (EffectHandler eff m)++instance MonadBaseControl IO m => MonadBaseControl IO (EffectHandler eff m) where+    type StM (EffectHandler eff m) a = StM (ReaderT (EffectMsg eff -> m (EffectRes eff)) m) a+    liftBaseWith f = EffectHandler $ liftBaseWith $ \q -> f (q . unpackEffectHandler)+    restoreM = EffectHandler . restoreM++instance {-# OVERLAPPABLE #-} (MonadEffect eff m, MonadTrans t, Monad (t m))+         => MonadEffect eff (t m) where+    effect p msg = lift (effect p msg)++instance Monad m => MonadEffect eff (EffectHandler eff m) where+    effect _ msg = EffectHandler (ReaderT ($ msg))++-- | Handle the effect described by 'eff'.+handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a+handleEffect f eh = runReaderT (unpackEffectHandler eh) f
src/Control/Effects/Reader.hs view
@@ -1,22 +1,22 @@-{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts #-}
-module Control.Effects.Reader (module Control.Effects.Reader, module Control.Effects) where
-
-import Interlude
-
-import Control.Lens
-
-import Control.Effects
-
-data ReadEnv e
-
-type instance EffectMsg (ReadEnv e) = ()
-type instance EffectRes (ReadEnv e) = e
-
-readEnv :: forall m e. MonadEffect (ReadEnv e) m => m e
-readEnv = effect (Proxy :: Proxy (ReadEnv e)) ()
-
-handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a
-handleReadEnv = handleEffect . const
-
-handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a
-handleSubreader f = handleReadEnv (f <$> readEnv)
+{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts #-}+module Control.Effects.Reader (module Control.Effects.Reader, module Control.Effects) where++import Interlude++import Control.Lens++import Control.Effects++data ReadEnv e++type instance EffectMsg (ReadEnv e) = ()+type instance EffectRes (ReadEnv e) = e++readEnv :: forall m e. MonadEffect (ReadEnv e) m => m e+readEnv = effect (Proxy :: Proxy (ReadEnv e)) ()++handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a+handleReadEnv = handleEffect . const++handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a+handleSubreader f = handleReadEnv (f <$> readEnv)
src/Control/Effects/State.hs view
@@ -1,65 +1,65 @@-{-# LANGUAGE TypeFamilies, ScopedTypeVariables, FlexibleContexts, Rank2Types, ConstraintKinds #-}
-module Control.Effects.State (module Control.Effects.State, module Control.Effects) where
-
-import Interlude
-
-import Data.IORef
-import Control.Lens
-
-import Control.Effects
-
-data GetState s
-data SetState s
-
-type instance EffectMsg (GetState s) = ()
-type instance EffectRes (GetState s) = s
-
-type instance EffectMsg (SetState s) = s
-type instance EffectRes (SetState s) = ()
-
-getState :: forall m s. MonadEffect (GetState s) m => m s
-getState = effect (Proxy :: Proxy (GetState s)) ()
-
-setState :: forall m s. MonadEffect (SetState s) m => s -> m ()
-setState = effect (Proxy :: Proxy (SetState s))
-
-modifyState :: forall m s. (MonadEffect (GetState s) m, MonadEffect (SetState s) m) => (s -> s) -> m ()
-modifyState f = setState . f =<< getState
-
-handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a
-handleGetState = handleEffect . const
-
-handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a
-handleSetState = handleEffect
-
-handleStateIO :: MonadIO m => s
-                           -> EffectHandler (GetState s) (EffectHandler (SetState s) m) a
-                           -> m a
-handleStateIO initial m = do
-    ref <- liftIO (newIORef initial)
-    m & handleGetState (liftIO  (readIORef  ref))
-      & handleSetState (liftIO . writeIORef ref)
-
-handleState :: Monad m => s
-                       -> EffectHandler (GetState s)
-                         (EffectHandler (SetState s) 
-                         (StateT s m)) a
-                       -> m a
-handleState initial m = evalStateT (handleSetState put $ handleGetState get m) initial
-
-handleSubstate :: forall s t m a. (MonadEffect (GetState s) m, MonadEffect (SetState s) m)
-               => Lens' s t
-               -> t
-               -> EffectHandler (GetState t) (EffectHandler (SetState t) m) a
-               -> m a
-handleSubstate lensST initial m = do
-    oldState <- getState
-    setState (set lensST initial oldState)
-    res <- m & handleGetState (view lensST <$> getState)
-             & handleSetState (\s -> do
-                 oldState <- getState
-                 setState (oldState & lensST .~ s))
-    setState oldState
-    return res
-
-type MonadEffectState s m = (MonadEffect (GetState s) m, MonadEffect (SetState s) m)
+{-# LANGUAGE TypeFamilies, ScopedTypeVariables, FlexibleContexts, Rank2Types, ConstraintKinds #-}+module Control.Effects.State (module Control.Effects.State, module Control.Effects) where++import Interlude++import Data.IORef+import Control.Lens++import Control.Effects++data GetState s+data SetState s++type instance EffectMsg (GetState s) = ()+type instance EffectRes (GetState s) = s++type instance EffectMsg (SetState s) = s+type instance EffectRes (SetState s) = ()++getState :: forall m s. MonadEffect (GetState s) m => m s+getState = effect (Proxy :: Proxy (GetState s)) ()++setState :: forall m s. MonadEffect (SetState s) m => s -> m ()+setState = effect (Proxy :: Proxy (SetState s))++modifyState :: forall m s. (MonadEffect (GetState s) m, MonadEffect (SetState s) m) => (s -> s) -> m ()+modifyState f = setState . f =<< getState++handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a+handleGetState = handleEffect . const++handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a+handleSetState = handleEffect++handleStateIO :: MonadIO m => s+                           -> EffectHandler (GetState s) (EffectHandler (SetState s) m) a+                           -> m a+handleStateIO initial m = do+    ref <- liftIO (newIORef initial)+    m & handleGetState (liftIO  (readIORef  ref))+      & handleSetState (liftIO . writeIORef ref)++handleState :: Monad m => s+                       -> EffectHandler (GetState s)+                         (EffectHandler (SetState s) +                         (StateT s m)) a+                       -> m a+handleState initial m = evalStateT (handleSetState put $ handleGetState get m) initial++handleSubstate :: forall s t m a. (MonadEffect (GetState s) m, MonadEffect (SetState s) m)+               => Lens' s t+               -> t+               -> EffectHandler (GetState t) (EffectHandler (SetState t) m) a+               -> m a+handleSubstate lensST initial m = do+    oldState <- getState+    setState (set lensST initial oldState)+    res <- m & handleGetState (view lensST <$> getState)+             & handleSetState (\s -> do+                 oldState <- getState+                 setState (oldState & lensST .~ s))+    setState oldState+    return res++type MonadEffectState s m = (MonadEffect (GetState s) m, MonadEffect (SetState s) m)
+ src/Control/Effects1.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, DeriveFunctor
+           , GeneralizedNewtypeDeriving, UndecidableInstances, StandaloneDeriving
+           , IncoherentInstances, RankNTypes #-}
+module Control.Effects1 where
+
+import Interlude
+
+import Control.Monad.Reader
+import Control.Monad.Trans.Control
+import Control.Monad.Base
+
+type family EffectMsg1 eff :: * -> *
+type family EffectRes1 eff :: * -> *
+
+class Monad m => MonadEffect1 eff m where
+    -- | Use the effect described by 'eff'.
+    effect1 :: proxy eff -> EffectMsg1 eff a -> m (EffectRes1 eff a)
+
+newtype EffHandling1 eff m = EffHandling1 {
+    getHandling1 :: forall a. EffectMsg1 eff a -> m (EffectRes1 eff a) }
+
+-- | The 'EffectHandler1' is rally just a 'ReaderT' carrying around the function that knows how to
+--   handle the effect.
+newtype EffectHandler1 eff m a = EffectHandler1
+    { unpackEffectHandler1 :: ReaderT (EffHandling1 eff m) m a }
+    deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadCatch, MonadThrow, MonadRandom)
+
+instance MonadTrans (EffectHandler1 eff) where
+    lift = EffectHandler1 . lift
+
+instance MonadReader s m => MonadReader s (EffectHandler1 eff m) where
+    ask = EffectHandler1 (lift ask)
+    local f (EffectHandler1 rdr) = EffectHandler1 (ReaderT $ local f . runReaderT rdr)
+
+deriving instance MonadBase IO m => MonadBase IO (EffectHandler1 eff m)
+
+instance MonadBaseControl IO m => MonadBaseControl IO (EffectHandler1 eff m) where
+    type StM (EffectHandler1 eff m) a = StM (ReaderT (EffHandling1 eff m) m) a
+    liftBaseWith f = EffectHandler1 $ liftBaseWith $ \q -> f (q . unpackEffectHandler1)
+    restoreM = EffectHandler1 . restoreM
+
+instance {-# OVERLAPPABLE #-} (MonadEffect1 eff m, MonadTrans t, Monad (t m))
+         => MonadEffect1 eff (t m) where
+    effect1 p msg = lift (effect1 p msg)
+
+instance Monad m => MonadEffect1 eff (EffectHandler1 eff m) where
+    effect1 _ msg = EffectHandler1 (ReaderT (($ msg) . getHandling1))
+
+-- | Handle the effect described by 'eff'.
+handleEffect1 :: Monad m => (forall a. EffectMsg1 eff a -> m (EffectRes1 eff a))
+             -> EffectHandler1 eff m a -> m a
+handleEffect1 f eh = runReaderT (unpackEffectHandler1 eh) (EffHandling1 f)