{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} -- | -- Module: Control.Monad.Factory.Class -- Copyright: 2019 Daniel YU -- License: MIT -- Maintainer: leptonyu@gmail.com -- Stability: experimental -- Portability: portable -- module Control.Monad.Factory.Class( MonadFactory(..) , defer , asksEnv , withEnv , modifyEnv , runEnv ) where -- | Monads which allow to produce @component@ under @env@, and @env@ can be changed by this procedure. class (Monad m, Monad n) => MonadFactory env n m | m -> env n where -- | Return the environment of the monad. getEnv :: m env -- | Replace the environment inside the monad. putEnv :: env -> m () -- | Produce a resource component, with open and close. produce :: n component -- ^ Open resource -> (component -> n ()) -- ^ Close resource -> m component -- | Asks sub value of env. asksEnv :: MonadFactory env n m => (env -> a) -> m a asksEnv f = f <$> getEnv -- | Defer to run side effect when closeing resource. defer :: MonadFactory env n m => n () -> m () defer = produce (return ()) . const -- | Change environment @env@. withEnv :: MonadFactory env n m => (env -> m env) -> m () withEnv f = getEnv >>= f >>= putEnv -- | Modify environment @env@. modifyEnv :: MonadFactory env n m => (env -> env) -> m () modifyEnv f = getEnv >>= putEnv . f -- | Run factory, return component @c@ and updated environment @env@. runEnv :: MonadFactory env n m => m c -> m (env, c) runEnv ma = do a <- ma e <- getEnv return (e, a)