boots 0.1.1 → 0.2
raw patch · 7 files changed
+234/−218 lines, 7 filesdep +bootsPVP ok
version bump matches the API change (PVP)
Dependencies added: boots
API changes (from Hackage documentation)
- Boots.Factory: (<<<) :: Category cat => cat b c -> cat a b -> cat a c
- Boots.Factory: (<>) :: Semigroup a => a -> a -> a
- Boots.Factory: (>>>) :: Category cat => cat a b -> cat b c -> cat a c
- Boots.Factory: ask :: MonadReader r m => m r
- Boots.Factory: asks :: MonadReader r m => (r -> a) -> m a
- Boots.Factory: boot :: Monad m => Factory m () (m ()) -> m ()
- Boots.Factory: bracket :: MonadCatch m => m res -> (res -> m ()) -> Factory m env res
- Boots.Factory: class MonadThrow m => MonadCatch (m :: Type -> Type)
- Boots.Factory: class Monad m => MonadIO (m :: Type -> Type)
- Boots.Factory: class Monad m => MonadReader r (m :: Type -> Type) | m -> r
- Boots.Factory: class Monad m => MonadThrow (m :: Type -> Type)
- Boots.Factory: data Factory m env component
- Boots.Factory: delay :: MonadCatch m => m () -> Factory m env ()
- Boots.Factory: infixr 1 <<<
- Boots.Factory: infixr 6 <>
- Boots.Factory: instance Control.Category.Category (Boots.Factory.Factory m)
- Boots.Factory: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Boots.Factory.Factory m env)
- Boots.Factory: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Boots.Factory.Factory m env)
- Boots.Factory: instance Control.Monad.Reader.Class.MonadReader env (Boots.Factory.Factory m env)
- Boots.Factory: instance GHC.Base.Applicative (Boots.Factory.Factory m env)
- Boots.Factory: instance GHC.Base.Functor (Boots.Factory.Factory m env)
- Boots.Factory: instance GHC.Base.Monad (Boots.Factory.Factory m env)
- Boots.Factory: instance GHC.Base.Monad m => Control.Monad.Cont.Class.MonadCont (Boots.Factory.Factory m env)
- Boots.Factory: instance GHC.Base.Monoid (Boots.Factory.Factory m env env)
- Boots.Factory: instance GHC.Base.Semigroup (Boots.Factory.Factory m env env)
- Boots.Factory: lift :: (MonadTrans t, Monad m) => m a -> t m a
- Boots.Factory: liftIO :: MonadIO m => IO a -> m a
- Boots.Factory: local :: MonadReader r m => (r -> r) -> m a -> m a
- Boots.Factory: natTrans :: (n () -> m ()) -> (m () -> n ()) -> Factory n env component -> Factory m env component
- Boots.Factory: offer :: Monad m => m a -> Factory m env a
- Boots.Factory: polish :: component -> [Factory m component component] -> Factory m env' component
- Boots.Factory: reader :: MonadReader r m => (r -> a) -> m a
- Boots.Factory: running :: env -> Factory m env c -> (c -> m ()) -> m ()
- Boots.Factory: throwM :: (MonadThrow m, Exception e) => e -> m a
- Boots.Factory: withFactory :: (env' -> env) -> Factory m env component -> Factory m env' component
- Boots.Factory: within :: env -> Factory m env component -> Factory m env' component
- Boots.Factory: wrap :: ((c -> m ()) -> m ()) -> Factory m env c
+ Control.Monad.Factory: (<<<) :: Category cat => cat b c -> cat a b -> cat a c
+ Control.Monad.Factory: (<>) :: Semigroup a => a -> a -> a
+ Control.Monad.Factory: (>>>) :: Category cat => cat a b -> cat b c -> cat a c
+ Control.Monad.Factory: Factory :: StateT env (ContT () m) component -> Factory m env component
+ Control.Monad.Factory: [unFactory] :: Factory m env component -> StateT env (ContT () m) component
+ Control.Monad.Factory: asksEnv :: MonadFactory env n m => (env -> a) -> m a
+ Control.Monad.Factory: boot :: Monad m => Factory m () (m ()) -> m ()
+ Control.Monad.Factory: class MonadThrow m => MonadCatch (m :: Type -> Type)
+ Control.Monad.Factory: class (Monad m, Monad n) => MonadFactory env n m | m -> env n
+ Control.Monad.Factory: class Monad m => MonadIO (m :: Type -> Type)
+ Control.Monad.Factory: class MonadCatch m => MonadMask (m :: Type -> Type)
+ Control.Monad.Factory: class Monad m => MonadThrow (m :: Type -> Type)
+ Control.Monad.Factory: defer :: MonadFactory env n m => n () -> m ()
+ Control.Monad.Factory: getEnv :: MonadFactory env n m => m env
+ Control.Monad.Factory: infixr 1 <<<
+ Control.Monad.Factory: infixr 6 <>
+ Control.Monad.Factory: instance Control.Category.Category (Control.Monad.Factory.Factory m)
+ Control.Monad.Factory: instance Control.Monad.Catch.MonadMask m => Control.Monad.Factory.Class.MonadFactory env m (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance Control.Monad.State.Class.MonadState env (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance GHC.Base.Applicative (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance GHC.Base.Functor (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance GHC.Base.Monad (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: instance GHC.Base.Monad m => Control.Monad.Cont.Class.MonadCont (Control.Monad.Factory.Factory m env)
+ Control.Monad.Factory: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Control.Monad.Factory: liftFT :: Monad m => m a -> Factory m env a
+ Control.Monad.Factory: liftIO :: MonadIO m => IO a -> m a
+ Control.Monad.Factory: modifyEnv :: MonadFactory env n m => (env -> env) -> m ()
+ Control.Monad.Factory: natTrans :: (n () -> m ()) -> (m () -> n ()) -> Factory n env component -> Factory m env component
+ Control.Monad.Factory: newtype Factory m env component
+ Control.Monad.Factory: produce :: MonadFactory env n m => n component -> (component -> n ()) -> m component
+ Control.Monad.Factory: putEnv :: MonadFactory env n m => env -> m ()
+ Control.Monad.Factory: runEnv :: MonadFactory env n m => m c -> m (env, c)
+ Control.Monad.Factory: running :: env -> Factory m env c -> (c -> m ()) -> m ()
+ Control.Monad.Factory: throwM :: (MonadThrow m, Exception e) => e -> m a
+ Control.Monad.Factory: tryBuild :: Bool -> Factory n env () -> Factory n env ()
+ Control.Monad.Factory: withEnv :: MonadFactory env n m => (env -> m env) -> m ()
+ Control.Monad.Factory: withFactory :: (env' -> env) -> Factory m env component -> Factory m env' component
+ Control.Monad.Factory: within :: env -> Factory m env component -> Factory m env' component
+ Control.Monad.Factory: wrap :: ((c -> m ()) -> m ()) -> Factory m env c
+ Control.Monad.Factory.Class: asksEnv :: MonadFactory env n m => (env -> a) -> m a
+ Control.Monad.Factory.Class: class (Monad m, Monad n) => MonadFactory env n m | m -> env n
+ Control.Monad.Factory.Class: defer :: MonadFactory env n m => n () -> m ()
+ Control.Monad.Factory.Class: getEnv :: MonadFactory env n m => m env
+ Control.Monad.Factory.Class: modifyEnv :: MonadFactory env n m => (env -> env) -> m ()
+ Control.Monad.Factory.Class: produce :: MonadFactory env n m => n component -> (component -> n ()) -> m component
+ Control.Monad.Factory.Class: putEnv :: MonadFactory env n m => env -> m ()
+ Control.Monad.Factory.Class: runEnv :: MonadFactory env n m => m c -> m (env, c)
+ Control.Monad.Factory.Class: withEnv :: MonadFactory env n m => (env -> m env) -> m ()
Files
- CHANGELOG.md +3/−0
- README.md +8/−15
- boots.cabal +10/−9
- src/Boots/Factory.hs +0/−179
- src/Control/Monad/Factory.hs +150/−0
- src/Control/Monad/Factory/Class.hs +53/−0
- test/Spec.hs +10/−15
+ CHANGELOG.md view
@@ -0,0 +1,3 @@+0.2 [2019.08.28]+-------------------+* Release use `Control.Monad.Factory`.
README.md view
@@ -5,9 +5,17 @@ [](http://stackage.org/lts/package/boots) [](http://stackage.org/nightly/package/boots) [](https://github.com/leptonyu/boots/blob/master/LICENSE)+ IoC Monad in Haskell. +### Packages based on boots++- [](https://hackage.haskell.org/package/boots-app) Factory for quickly building an application.+- [](https://hackage.haskell.org/package/boots-web) Factory for quickly building a web application.+- [](https://hackage.haskell.org/package/boots-cloud) Factory for quickly building a microservice.++ ### Motivation Simplify to create an application in Haskell.@@ -17,18 +25,3 @@ ## A Project Use boots to Build Refer to [鬼谷子](https://github.com/leptonyu/guiguzi)--### Have a Try--```Haskell-factory = do- log <- logFactory- conf <- confFactory- within (log, conf) $ do- a <- withFactory fst aFactory- b <- withFactory snd bFactory- polish AB{..}- [ xFactory- , yFactory- ] >>> bootFactory-```
boots.cabal view
@@ -4,13 +4,13 @@ -- -- see: https://github.com/sol/hpack ----- hash: 07ea4190e76748290f6abd6bd660c00f0d6ba2c91a51c3021fb010274bb510ac+-- hash: f2aa610e1c0d974992d89103041429343b5aa10e47a821783039d97408d2ee7f name: boots-version: 0.1.1+version: 0.2 synopsis: IoC Monad in Haskell-description: Inverse of control monad used in building large application.-category: Library, Application+description: Monad used to encapsulate components, similiar to an IoC container.+category: Library, Application, Monad, Factory, IoC homepage: https://github.com/leptonyu/boots#readme author: Daniel YU maintainer: leptonyu@gmail.com@@ -20,15 +20,17 @@ build-type: Simple extra-source-files: README.md+ CHANGELOG.md library exposed-modules:- Boots.Factory+ Control.Monad.Factory+ Control.Monad.Factory.Class other-modules: Paths_boots hs-source-dirs: src- default-extensions: FlexibleInstances MultiParamTypeClasses GeneralizedNewtypeDeriving OverloadedStrings RecordWildCards FlexibleContexts RankNTypes ScopedTypeVariables FunctionalDependencies ConstraintKinds+ default-extensions: RecordWildCards ScopedTypeVariables ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures build-depends: base >=4.10 && <5@@ -40,15 +42,14 @@ type: exitcode-stdio-1.0 main-is: Spec.hs other-modules:- Boots.Factory Paths_boots hs-source-dirs: test- src- default-extensions: FlexibleInstances MultiParamTypeClasses GeneralizedNewtypeDeriving OverloadedStrings RecordWildCards FlexibleContexts RankNTypes ScopedTypeVariables FunctionalDependencies ConstraintKinds+ default-extensions: RecordWildCards ScopedTypeVariables ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures build-depends: base >=4.10 && <5+ , boots , exceptions >=0.10.2 && <0.11 , hspec , mtl >=2.2.2 && <2.3
− src/Boots/Factory.hs
@@ -1,179 +0,0 @@-{-# LANGUAGE CPP #-}--- |--- Module: Boots.Factory--- Copyright: 2019 Daniel YU--- License: MIT--- Maintainer: leptonyu@gmail.com--- Stability: experimental--- Portability: portable------ IoC Monad in Haskell.------ * Motivation------ Simplify to create an application in Haskell.------ When we decide to create an application using Haskell.--- We may need using configurations, loggers as basic functions.--- If this application needs storages, caches, etc.,--- then we have to weaving the management of connection of these facilities into the application.--- Connections need to be created before and be destroyed after using them.--- There is a common strategy to manage connections, that is using `Control.Monad.Cont`.--- Then we can encapsulate the management of connections separately.--- For example, we can write a database plugin `Factory` @m@ @cxt@ @DBConnection@,--- which can manage the database connections in monad @m@ with context @cxt@.--- Context @cxt@ may be requested for getting configurations or logging functions.--- When all the components of application are encapsulated by plugins, then running an application will be simplified.------ * Factory------ 'Factory' has an environment @env@, which provides anything needs by the factory. @component@ is the production of--- the factory, it will be used by other 'Factory'. Finally to build a complete 'Factory' m () (m ()), which can be 'boot'.------ For example:------ > factory = do--- > log <- logFactory--- > conf <- confFactory--- > within (log, conf) $ do--- > a <- withFactory fst aFactory--- > b <- withFactory snd bFactory--- > polish AB{..}--- > [ xFactory--- > , yFactory--- > ] >>> bootFactory-module Boots.Factory(- -- * Definition- Factory- -- ** Run functions- , running- , boot- -- * Factory Construction- -- ** With- , withFactory- , within- -- ** Polish- , polish- -- ** Nature Transformation- , natTrans- -- ** Resource- , wrap- , bracket- , offer- , delay- -- * Reexport Function- -- ** Category Arrow- , (C.>>>)- , (C.<<<)- -- ** Monoid Join- , (<>)- -- ** Other- , MonadThrow(..)- , MonadCatch- , MonadReader(..)- , asks- , MonadIO(..)- , lift- ) where--import qualified Control.Category as C-import Control.Monad.Catch hiding (bracket)-import Control.Monad.Cont-import Control.Monad.Reader-import Unsafe.Coerce (unsafeCoerce)-#if __GLASGOW_HASKELL__ < 804-import Data.Semigroup-#endif---- | Factory defines how to generate a @component@ under the environment @env@ in monad @m@.--- It is similar to IoC container in oop, @env@ will provide anything to be wanted to generate @component@.----newtype Factory m env component- = Factory { unFactory :: ReaderT env (ContT () m) component }- deriving (Functor, Applicative, Monad, MonadReader env, MonadIO)--instance MonadThrow m => MonadThrow (Factory m env) where- {-# INLINE throwM #-}- throwM = offer . throwM--instance Monad m => MonadCont (Factory m env) where- {-# INLINE callCC #-}- callCC a = do- env <- ask- wrap . running env $ callCC a--instance Semigroup (Factory m env env) where- {-# INLINE (<>) #-}- a <> b = a >>= (`within` b)--instance Monoid (Factory m env env) where- {-# INLINE mempty #-}- mempty = ask- {-# INLINE mappend #-}- mappend = (<>)--instance C.Category (Factory m) where- {-# INLINE id #-}- id = ask- {-# INLINE (.) #-}- a . b = b >>= (`within` a)---- | Running the factory.-running :: env -> Factory m env c -> (c -> m ()) -> m ()-running env pma = runContT (runReaderT (unFactory pma) env)-{-# INLINE running #-}---- | Run the application using a specified factory.-boot :: Monad m => Factory m () (m ()) -> m ()-boot factory = running () factory id---- | Switch factory environment.-withFactory :: (env' -> env) -> Factory m env component -> Factory m env' component-withFactory = unsafeCoerce withReaderT-{-# INLINE withFactory #-}---- | Construct factory under @env@, and adapt it to fit another @env'@.-within :: env -> Factory m env component -> Factory m env' component-within = withFactory . const-{-# INLINE within #-}---- | Polish @component@ by a sequence of 'Factory', and construct a unified one.-polish :: component -> [Factory m component component] -> Factory m env' component-polish env = within env . mconcat-{-# INLINE polish #-}---- | Nature transform of one 'Factory' with monad @n@ into another with monad @m@.-natTrans :: (n () -> m ()) -> (m () -> n ()) -> Factory n env component -> Factory m env component-natTrans fnm fmn fac = do- env <- ask- wrap $ \fm -> fnm $ running env fac (fmn . fm)-{-# INLINE natTrans #-}---- | Wrap raw procedure into a 'Factory'.-wrap :: ((c -> m ()) -> m ()) -> Factory m env c-wrap = Factory . lift . ContT-{-# INLINE wrap #-}---- | Construct open-close resource into a 'Factory'.-bracket :: MonadCatch m => m res -> (res -> m ()) -> Factory m env res-bracket open close = wrap $ \f -> do- res <- open- a <- try $ f res- b <- try $ close res- go a b- where- go (Left e) _ = throwM (e :: SomeException)- go _ (Left e) = throwM (e :: SomeException)- go _ _ = return ()- {-# INLINE go #-}-{-# INLINE bracket #-}---- | Lift a monad @m@ into a 'Factory'.-offer :: Monad m => m a -> Factory m env a-offer ma = wrap (ma >>=)-{-# INLINE offer #-}---- | Put a delay action into 'Factory', it will run at close phase.-delay :: MonadCatch m => m () -> Factory m env ()-delay ma = bracket (return ()) (const ma)-{-# INLINE delay #-}
+ src/Control/Monad/Factory.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-- |+-- Module: Control.Monad.Factory+-- Copyright: 2019 Daniel YU+-- License: MIT+-- Maintainer: leptonyu@gmail.com+-- Stability: experimental+-- Portability: portable+--+-- IoC Monad in Haskell.+--+-- * Motivation+--+-- Simplify to create an application in Haskell.+--+-- When we decide to create an application using Haskell.+-- We may need using configurations, loggers as basic functions.+-- If this application needs storages, caches, etc.,+-- then we have to weaving the management of connection of these facilities into the application.+-- Connections need to be created before and be destroyed after using them.+-- There is a common strategy to manage connections, that is using `Control.Monad.Cont`.+-- Then we can encapsulate the management of connections separately.+-- For example, we can write a database plugin `Factory` @m@ @cxt@ @DBConnection@,+-- which can manage the database connections in monad @m@ with context @cxt@.+-- Context @cxt@ may be requested for getting configurations or logging functions.+-- When all the components of application are encapsulated by plugins, then running an application will be simplified.+--+-- * Factory+--+-- 'Factory' has an environment @env@, which provides anything needs by the factory. @component@ is the production of+-- the factory, it will be used by other 'Factory'. Finally to build a complete 'Factory' m () (m ()), which can be 'boot'.+--+--+module Control.Monad.Factory(+ -- * Monad+ MonadFactory(..)+ , defer+ , asksEnv+ , modifyEnv+ , withEnv+ , runEnv+ -- * Monad Instance+ , Factory(..)+ -- ** Run functions+ , running+ , boot+ -- ** With+ , within+ , withFactory+ , wrap+ , liftFT+ , natTrans+ , tryBuild+ -- * Reexport Function+ -- ** Category Arrow+ , (C.>>>)+ , (C.<<<)+ -- ** Monoid Join+ , (<>)+ -- ** Other+ , MonadThrow(..)+ , MonadCatch+ , MonadMask+ , MonadIO(..)+ , lift+ ) where++import qualified Control.Category as C+import Control.Monad.Catch+import Control.Monad.Cont+import Control.Monad.Factory.Class+import Control.Monad.State+#if __GLASGOW_HASKELL__ < 804+import Data.Semigroup+#endif+++-- | Factory defines how to generate a @component@ under the environment @env@ in monad @m@.+-- It is similar to IoC container in oop, @env@ will provide anything to be wanted to generate @component@.+--+newtype Factory m env component+ = Factory { unFactory :: StateT env (ContT () m) component }+ deriving (Functor, Applicative, Monad, MonadState env, MonadIO)++instance MonadThrow m => MonadThrow (Factory m env) where+ {-# INLINE throwM #-}+ throwM = liftFT . throwM++instance Monad m => MonadCont (Factory m env) where+ {-# INLINE callCC #-}+ callCC a = do+ env <- get+ wrap . running env $ callCC a++instance C.Category (Factory m) where+ {-# INLINE id #-}+ id = get+ {-# INLINE (.) #-}+ a . b = b >>= (`within` a)++instance MonadMask m => MonadFactory env m (Factory m env) where+ getEnv = get+ putEnv = put+ produce o = wrap . bracket o++-- | Running the factory.+running :: env -> Factory m env c -> (c -> m ()) -> m ()+running env pma = runContT (evalStateT (unFactory pma) env)+{-# INLINE running #-}++-- | Run the application using a specified factory.+boot :: Monad m => Factory m () (m ()) -> m ()+boot factory = running () factory id++-- | Construct factory under @env@, and adapt it to fit another @env'@.+within :: env -> Factory m env component -> Factory m env' component+within env = Factory . lift . (`evalStateT` env) . unFactory+{-# INLINE within #-}++-- | Construct factory under @env@, and adapt it to fit another @env'@.+withFactory :: (env' -> env) -> Factory m env component -> Factory m env' component+withFactory f (Factory ma) = do+ env <- get+ Factory (lift $ evalStateT ma (f env))+{-# INLINE withFactory #-}++-- | Wrap raw procedure into a 'Factory'.+wrap :: ((c -> m ()) -> m ()) -> Factory m env c+wrap = Factory . lift . ContT+{-# INLINE wrap #-}++-- | Lift a monad @m@ into a 'Factory'.+liftFT :: Monad m => m a -> Factory m env a+liftFT ma = wrap (ma >>=)+{-# INLINE liftFT #-}++-- | Nature transform of one 'Factory' with monad @n@ into another with monad @m@.+natTrans :: (n () -> m ()) -> (m () -> n ()) -> Factory n env component -> Factory m env component+natTrans fnm fmn fac = do+ env <- get+ wrap $ \fm -> fnm $ running env fac (fmn . fm)+{-# INLINE natTrans #-}++{-# INLINE tryBuild #-}+tryBuild :: Bool -> Factory n env () -> Factory n env ()+tryBuild b p = if b then p else return ()
+ src/Control/Monad/Factory/Class.hs view
@@ -0,0 +1,53 @@+{-# 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)
test/Spec.hs view
@@ -1,14 +1,14 @@ module Main where -import Boots.Factory import Control.Concurrent.MVar import Control.Exception (Exception)+import Control.Monad.Factory import Control.Monad.Identity import Test.Hspec main = hspec $ do- describe "Boots.Factory" specProperty+ describe "Control.Monad.Factory" specProperty data TestExp = Failure deriving Show@@ -27,20 +27,15 @@ boot (return $ return ()) `shouldBe` Just () it "boot - Error " $ do boot (return $ throwM Failure) `shouldBe` Nothing- context "With" $ do- it "withFactory" $ do- running ('A', True) (withFactory fst $ ask >>= \a -> offer (a `shouldBe` 'A')) return- running ('A', True) (withFactory snd $ ask >>= \a -> offer (a `shouldBe` True)) return it "within" $ do- running () (within 'A' $ ask >>= \a -> offer (a `shouldBe` 'A')) return- context "Polish" $ do- it "polish" $ do- running () (polish (0 :: Int) (replicate 10 $ withFactory (+1) ask)) (shouldBe 10)+ running () (within 'A' $ getEnv >>= \a -> liftFT (a `shouldBe` 'A')) return+ it "modify" $ do+ running () (within 'A' $ putEnv 'B' >> getEnv >>= \a -> liftFT (a `shouldBe` 'B')) return context "natTrans" $ do it "natTrans" $ do running () (natTrans runIdentityT IdentityT $ return ()) return `shouldBe` Just () context "Resource" $ do- it "bracket" $ do+ it "produce" $ do ref <- newMVar (0 :: Int) let open = do@@ -54,8 +49,8 @@ b `shouldBe` 2 return () boot $ do- a <- bracket open close- offer $ do+ a <- produce open close+ liftFT $ do a `shouldBe` 0 b <- swapMVar ref 2 b `shouldBe` 1@@ -63,8 +58,8 @@ it "bracket - error" $ do ref <- newMVar (0 :: Int) (`shouldThrow` anyException) $ boot $ do- a <- bracket (readMVar ref) (\_ -> throwM Failure)- _ <- offer $ do+ a <- produce (readMVar ref) (\_ -> throwM Failure)+ _ <- liftFT $ do a `shouldBe` 0 swapMVar ref 1 return (return ())