THEff 0.1.0.1 → 0.1.1.0
raw patch · 10 files changed
+415/−85 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.THEff.Reader.Strict: ReaderAction :: (Reader' v e) -> Reader e o v a
+ Control.THEff.Reader.Strict: ReaderOuter :: (o m e) -> Reader e o v a
+ Control.THEff.Reader.Strict: ReaderResult :: a -> Reader e o v a
+ Control.THEff.Reader.Strict: ask :: EffClass Reader' v e => Eff e v
+ Control.THEff.Reader.Strict: asks :: EffClass Reader' r e => (r -> v) -> Eff e v
+ Control.THEff.Reader.Strict: data Reader (m :: * -> *) e o v a
+ Control.THEff.Reader.Strict: data Reader' v e
+ Control.THEff.Reader.Strict: effReader :: EffClass Reader' v e => Reader' v r -> Eff e r
+ Control.THEff.Reader.Strict: runEffReader :: Monad m => (u t r -> (r -> m (ReaderResT a)) -> m (ReaderResT a)) -> (Reader m1 e o w a1 -> r) -> (r -> Reader t r u v a) -> ReaderArgT v -> Eff r a1 -> m (ReaderResT a)
+ Control.THEff.Reader.Strict: type ReaderArgT v = v
+ Control.THEff.Reader.Strict: type ReaderResT r = r
+ Control.THEff.State.Strict: StateAction :: (State' v e) -> State e o v a
+ Control.THEff.State.Strict: StateOuter :: (o m e) -> State e o v a
+ Control.THEff.State.Strict: StateResult :: a -> State e o v a
+ Control.THEff.State.Strict: data State (m :: * -> *) e o v a
+ Control.THEff.State.Strict: data State' v e
+ Control.THEff.State.Strict: effState :: EffClass State' v e => State' v r -> Eff e r
+ Control.THEff.State.Strict: get :: EffClass State' v e => Eff e v
+ Control.THEff.State.Strict: modify :: EffClass State' v e => (v -> v) -> Eff e ()
+ Control.THEff.State.Strict: put :: EffClass State' v e => v -> Eff e ()
+ Control.THEff.State.Strict: runEffState :: Monad m => (u t r -> (r -> m (StateResT z v)) -> m (StateResT z v)) -> (State m1 e o w a -> r) -> (r -> State t r u v z) -> StateArgT v -> Eff r a -> m (StateResT z v)
+ Control.THEff.State.Strict: stateOnly :: (t -> e -> (r, v)) -> t -> e -> v
+ Control.THEff.State.Strict: type StateArgT v = v
+ Control.THEff.State.Strict: type StateResT r v = (r, v)
+ Control.THEff.State.Strict: withoutState :: (t -> e -> (r, v)) -> t -> e -> r
+ Control.THEff.Writer.Strict: WriterAction :: (Writer' v e) -> Writer e o v a
+ Control.THEff.Writer.Strict: WriterOuter :: (o m e) -> Writer e o v a
+ Control.THEff.Writer.Strict: WriterResult :: a -> Writer e o v a
+ Control.THEff.Writer.Strict: data Writer (m :: * -> *) e o v a
+ Control.THEff.Writer.Strict: data Writer' v e
+ Control.THEff.Writer.Strict: effWriter :: EffClass Writer' v e => Writer' v r -> Eff e r
+ Control.THEff.Writer.Strict: runEffWriter :: (Monad m, Monoid v) => (u t r -> (r -> m (WriterResT z v)) -> m (WriterResT z v)) -> (Writer m1 e o w a -> r) -> (r -> Writer t r u v z) -> Eff r a -> m (WriterResT z v)
+ Control.THEff.Writer.Strict: tell :: EffClass Writer' v e => v -> Eff e ()
+ Control.THEff.Writer.Strict: type WriterResT r v = (r, v)
Files
- THEff.cabal +84/−80
- samples/SampleAll.hs +2/−2
- src/Control/THEff.hs +1/−1
- src/Control/THEff/Reader.hs +3/−0
- src/Control/THEff/Reader/Strict.hs +96/−0
- src/Control/THEff/State.hs +3/−0
- src/Control/THEff/State/Strict.hs +122/−0
- src/Control/THEff/TH/Internal.hs +0/−2
- src/Control/THEff/Writer.hs +3/−0
- src/Control/THEff/Writer/Strict.hs +101/−0
THEff.cabal view
@@ -1,81 +1,85 @@-name: THEff -version: 0.1.0.1 -synopsis: TH implementation of effects. -license: BSD3 -license-file: LICENSE -author: Kolodezny Diver -maintainer: kolodeznydiver@gmail.com -category: Control, Effect, TH -build-type: Simple -cabal-version: >=1.10 -description: - This package implements effects, as alternative to monad - transformers. Actually, the effects themselves are created without - the use of TH, but the binding of nested effects described by - mkEff splice. For example. - . - > mkEff "MyReader" ''Reader ''Int ''Lift - > mkEff "SomeState" ''State ''Bool ''MyReader - > mkEff "OtherRdr" ''Reader ''Float ''SomeState - > - > main:: IO () - > main = do - > r <- runMyReader 100 - > $ runSomeState False - > $ runOtherRdr pi $ do - > i :: Int <- ask -- MyReader - > f :: Float <- ask -- OtherRdr - > b <- get -- SomeState - > put $ not b -- SomeState - > lift $ putStrLn "print from effect!" -- Lift - > return $ show $ fromIntegral i * f - > print r - . - For more information about extensible effects , see the original paper at - <http://okmij.org/ftp/Haskell/extensible/exteff.pdf>. - But, this package is significantly different from the original. - It uses a chains of ordinary GADTs created by TH. - No Typeable, unsafe... , ExistentialQuantification ... - -extra-source-files: samples/*.hs - -Source-repository head - type: git - location: https://github.com/KolodeznyDiver/THEff.git - -library - ghc-options: -Wall - exposed-modules: Control.THEff - Control.THEff.Reader - Control.THEff.State - Control.THEff.Exception - Control.THEff.Catch - Control.THEff.Writer - Control.THEff.Fresh - Control.THEff.Validator - - -- Modules included in this library but not exported. - other-modules: Control.THEff.TH.Internal - - -- LANGUAGE extensions used by modules in this package. - other-extensions: KindSignatures - , FlexibleInstances - , FlexibleContexts - , MultiParamTypeClasses - , TemplateHaskell - , ViewPatterns - , RecordWildCards - , ScopedTypeVariables - , RankNTypes - , GADTs - - -- Other library packages from which modules are imported. - build-depends: base >=4.8 && <4.9 - ,template-haskell >=2.4 && <2.11 - - -- Directories containing source files. - hs-source-dirs: src - - -- Base language which the package is written in. - default-language: Haskell2010 +name: THEff+version: 0.1.1.0+synopsis: TH implementation of effects. +license: BSD3+license-file: LICENSE+author: Kolodezny Diver+maintainer: kolodeznydiver@gmail.com+category: Control, Effect, TH +build-type: Simple+cabal-version: >=1.10+description: + This package implements effects, as alternative to monad+ transformers. Actually, the effects themselves are created without + the use of TH, but the binding of nested effects described by + mkEff splice. For example.+ .+ > mkEff "MyReader" ''Reader ''Int ''Lift+ > mkEff "SomeState" ''State ''Bool ''MyReader+ > mkEff "OtherRdr" ''Reader ''Float ''SomeState+ > + > main:: IO ()+ > main = do+ > r <- runMyReader 100 + > $ runSomeState False+ > $ runOtherRdr pi $ do+ > i :: Int <- ask -- MyReader + > f :: Float <- ask -- OtherRdr+ > b <- get -- SomeState+ > put $ not b -- SomeState + > lift $ putStrLn "print from effect!" -- Lift + > return $ show $ fromIntegral i * f + > print r+ .+ For more information about extensible effects , see the original paper at+ <http://okmij.org/ftp/Haskell/extensible/exteff.pdf>.+ But, this package is significantly different from the original.+ It uses a chains of ordinary GADTs created by TH. + No Typeable, unsafe... , ExistentialQuantification ...++extra-source-files: samples/*.hs+ +Source-repository head+ type: git+ location: https://github.com/KolodeznyDiver/THEff.git+ +library+ ghc-options: -Wall + exposed-modules: Control.THEff+ Control.THEff.Reader+ Control.THEff.State+ Control.THEff.Exception+ Control.THEff.Catch+ Control.THEff.Writer+ Control.THEff.Fresh+ Control.THEff.Validator+ Control.THEff.Writer.Strict+ Control.THEff.Reader.Strict+ Control.THEff.State.Strict + + -- Modules included in this library but not exported.+ other-modules: Control.THEff.TH.Internal+ + -- LANGUAGE extensions used by modules in this package.+ other-extensions: KindSignatures+ , FlexibleInstances+ , FlexibleContexts+ , MultiParamTypeClasses+ , TemplateHaskell+ , ViewPatterns+ , RecordWildCards+ , ScopedTypeVariables+ , RankNTypes+ , GADTs+ , BangPatterns+ + -- Other library packages from which modules are imported.+ build-depends: base >=4.8 && <4.9+ ,template-haskell >=2.4 && <2.11+ + -- Directories containing source files.+ hs-source-dirs: src+ + -- Base language which the package is written in.+ default-language: Haskell2010
samples/SampleAll.hs view
@@ -21,8 +21,8 @@ mkEff "MyReader" ''Reader ''Int ''Lift mkEff "SomeState" ''State ''Bool ''MyReader mkEff "OtherRdr" ''Reader ''Float ''SomeState-mkEff "MyWriter" ''Writer ''String ''OtherRdr-mkEff "MyException" ''Except ''String ''MyWriter+mkEff "MyWriter" ''Writer ''String ''OtherRdr+mkEff "MyException" ''Except ''String ''MyWriter mkEff "MyCatch" ''Catch ''Int ''MyException mkEff "UnicalChar" ''Fresh ''Char ''MyCatch mkEff "MyVldtr" ''Validator ''Float ''UnicalChar
src/Control/THEff.hs view
@@ -106,7 +106,7 @@ newtype NoEff (m:: * -> *) a = NoEff { unNoEff :: a} -- | This function is used in the 'mkEff' generated runEEEE... functions. --- > @effNoEff _ = error "THEff: Attempting to call the effect NoEff that does not have any actions!"@+-- @effNoEff _ = error "THEff: Attempting to call the effect NoEff that does not have any actions!"@ effNoEff :: a -> b effNoEff _ = error "THEff: Attempting to call the effect NoEff that does not have any actions!"
src/Control/THEff/Reader.hs view
@@ -7,6 +7,9 @@ module Control.THEff.Reader ( -- * Overview -- |+-- This version builds its output lazily; for a strict version with+-- the same interface, see "Control.THEff.Reader.Strict".+-- -- > {-# LANGUAGE KindSignatures #-} -- > {-# LANGUAGE FlexibleInstances #-} -- > {-# LANGUAGE MultiParamTypeClasses #-}
+ src/Control/THEff/Reader/Strict.hs view
@@ -0,0 +1,96 @@+{-# OPTIONS_HADDOCK show-extensions #-}++{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BangPatterns #-}++module Control.THEff.Reader.Strict (+ -- * Overview +-- |+-- This version builds its output strictly; for a lazy version with+-- the same interface, see "Control.THEff.Reader".+--+-- > {-# LANGUAGE KindSignatures #-}+-- > {-# LANGUAGE FlexibleInstances #-}+-- > {-# LANGUAGE MultiParamTypeClasses #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- > +-- > import Control.THEff+-- > import Control.THEff.Reader.Strict+-- > +-- > mkEff "CharReader" ''Reader ''Char ''NoEff+-- > mkEff "StrReader" ''Reader ''String ''CharReader+-- > +-- > main:: IO ()+-- > main = putStrLn $ runCharReader 'T' $ runStrReader "est" $ do+-- > c <- ask+-- > s <- ask+-- > return $ c:s+-- +-- __/Output :/__ "Test"++ -- * Types and functions used in mkEff+ Reader' + , Reader(..)+ , ReaderArgT+ , ReaderResT+ , effReader+ , runEffReader+ -- * Functions that use this effect + , ask+ , asks+ ) where++import Control.THEff++-- | Actually, the effect type+-- - __/v/__ - Type - the parameter of the effect.+-- - __/e/__ - mkEff generated type.+newtype Reader' v e = Reader' (v -> e)++-- | Type implements link in the chain of effects.+-- Constructors must be named __/{EffectName}{Outer|WriterAction|WriterResult}/__+-- and have a specified types of fields.+-- - __/m/__ - Or Monad (if use the 'Lift') or phantom type - stub (if used 'NoEff').+-- - __/o/__ - Type of outer effect.+-- - __/a/__ - The result of mkEff generated runEEEE... function.+data Reader (m:: * -> *) e o v a = ReaderOuter (o m e)+ | ReaderAction (Reader' v e)+ | ReaderResult a ++-- | Type of fourth argument of runEffReader and first argument of runEEEE. +type ReaderArgT v = v++-- | Result type of runEEEE. +type ReaderResT r = r++-- | This function is used in the 'mkEff' generated runEEEE functions and typically +-- in effect action functions. Calling the effect action.+effReader:: EffClass Reader' v e => Reader' v r -> Eff e r+effReader (Reader' g) = effAction $ \k -> Reader' (k . g)++-- | The main function of the effect implementing. +-- This function is used in the 'mkEff' generated runEEEE functions. +runEffReader :: forall (t :: * -> *) (u :: (* -> *) -> * -> *) (m :: * -> *) a v + (m1 :: * -> *) e (o :: (* -> *) -> * -> *) w a1 r. Monad m =>+ (u t r -> (r -> m (ReaderResT a)) -> m (ReaderResT a)) -- ^ The outer effect function+ -> (Reader m1 e o w a1 -> r) -- ^ The chain of effects link wrapper.+ -> (r -> Reader t r u v a) -- ^ The chain of effects link unwrapper.+ -> ReaderArgT v -- ^ The initial value of argument of effect.+ -> Eff r a1+ -> m (ReaderResT a)+runEffReader outer to un !v m = loop $ runEff m (to . ReaderResult)+ where+ loop = select . un+ select (ReaderOuter f) = outer f loop+ select (ReaderAction (Reader' g)) = loop $ g v+ select (ReaderResult r) = return r++-- | Get reader value+ask :: EffClass Reader' v e => Eff e v+ask = effReader $ Reader' id++-- | Get and convert the value of the reader+asks :: EffClass Reader' r e => (r -> v) -> Eff e v+asks f = effReader $ Reader' f
src/Control/THEff/State.hs view
@@ -7,6 +7,9 @@ module Control.THEff.State ( -- * Overview -- |+-- This version builds its output lazily; for a strict version with+-- the same interface, see "Control.THEff.State.Strict".+-- -- > {-# LANGUAGE KindSignatures #-} -- > {-# LANGUAGE FlexibleInstances #-} -- > {-# LANGUAGE MultiParamTypeClasses #-}
+ src/Control/THEff/State/Strict.hs view
@@ -0,0 +1,122 @@+{-# OPTIONS_HADDOCK show-extensions #-}++{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BangPatterns #-}++module Control.THEff.State.Strict (+ -- * Overview +-- |+-- This version builds its output strictly; for a lazy version with+-- the same interface, see "Control.THEff.State".+--+-- > {-# LANGUAGE KindSignatures #-}+-- > {-# LANGUAGE FlexibleInstances #-}+-- > {-# LANGUAGE MultiParamTypeClasses #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- > +-- > import Control.THEff+-- > import Control.THEff.State.Strict+-- > +-- > mkEff "Example1" ''State ''Int ''NoEff+-- > mkEff "Example2" ''State ''Float ''Example1+-- > +-- > main:: IO ()+-- > main = print $ runExample1 123 +-- > $ runExample2 pi $ do+-- > i <- get+-- > modify ((1 :: Int) +)+-- > put $ i * (2 :: Float)+-- > return $ show i +-- +-- __/Output :/__ (("3.1415927",6.2831855),124)++ -- * Types and functions used in mkEff+ State'+ , State(..) + , StateArgT+ , StateResT+ , effState+ , runEffState + -- * Functions that use this effect + , get+ , put+ , modify+ -- * Helper functions+ , stateOnly+ , withoutState+ ) where++import Control.THEff++-- | Actually, the effect type+-- - __/v/__ - Type - the parameter of the effect.+-- - __/e/__ - mkEff generated type.+data State' v e = State' (v -> v) (v -> e) ++-- | Type implements link in the chain of effects.+-- Constructors must be named __/{EffectName}{Outer|WriterAction|WriterResult}/__+-- and have a specified types of fields.+-- - __/m/__ - Or Monad (if use the 'Lift') or phantom type - stub (if used 'NoEff').+-- - __/o/__ - Type of outer effect.+-- - __/a/__ - The result of mkEff generated runEEEE... function.+data State (m:: * -> *) e o v a = StateOuter (o m e)+ | StateAction (State' v e) + | StateResult a++-- | Type of fourth argument of runEffState and first argument of runEEEE. +type StateArgT v = v++-- | Result type of runEEEE. +type StateResT r v = (r, v)++-- | This function is used in the 'mkEff' generated runEEEE functions and typically +-- in effect action functions. Calling the effect action.+effState:: EffClass State' v e => State' v r -> Eff e r+effState (State' f g) = effAction $ \k -> State' f (k . g)++-- | The main function of the effect implementing. +-- This function is used in the 'mkEff' generated runEEEE functions. +runEffState :: forall (t :: * -> *) (u :: (* -> *) -> * -> *) (m :: * -> *) + z v (m1 :: * -> *) e (o :: (* -> *) -> * -> *) w a r. Monad m =>+ (u t r -> (r -> m (StateResT z v)) -> m (StateResT z v)) -- ^ The outer effect function+ -> (State m1 e o w a -> r) -- ^ The chain of effects link wrapper.+ -> (r -> State t r u v z) -- ^ The chain of effects link unwrapper.+ -> StateArgT v -- ^ The initial value of argument of effect.+ -> Eff r a+ -> m (StateResT z v)+runEffState outer to un v m = loop v $ runEff m (to . StateResult)+ where + loop !s = select . un where+ select (StateOuter f) = outer f (loop s)+ select (StateAction (State' t k)) = let s' = t s in loop s' (k s')+ select (StateResult r) = return (r,s)++-- | Get state value+get :: EffClass State' v e => Eff e v+get = effState $ State' id id+ +-- | Put state value+put :: EffClass State' v e => v -> Eff e ()+put !s = modify $ const s+ +-- | Modify state value+modify :: EffClass State' v e => (v -> v) -> Eff e ()+modify f = effState $ State' f (const ())+ +-- | @ stateOnly runExample1 123 === snd (runExample1 123) @+stateOnly :: forall v e r t. + (t -> e -> (r, v)) -- ^ State effect runEEEE function+ -> t -- ^ The initial value of argument of effect. + -> e -- ^ Eff (MyState m ...) ... + -> v+stateOnly f v = snd . (f v)++-- | @ withoutState runExample1 123 === fst (runExample1 123) @+withoutState :: forall v e r t. + (t -> e -> (r, v)) -- ^ State effect runEEEE function+ -> t -- ^ The initial value of argument of effect. + -> e -- ^ Eff (MyState m ...) ... + -> r+withoutState f v = fst . (f v)
src/Control/THEff/TH/Internal.hs view
@@ -1,7 +1,5 @@ {-# OPTIONS_HADDOCK show-extensions #-} -{-# OPTIONS_HADDOCK show-extensions #-}- {-# LANGUAGE TemplateHaskell, ViewPatterns, RecordWildCards #-} module Control.THEff.TH.Internal(mkEff) where
src/Control/THEff/Writer.hs view
@@ -7,6 +7,9 @@ module Control.THEff.Writer ( -- * Overview -- |+-- This version builds its output lazily; for a strict version with+-- the same interface, see "Control.THEff.Writer.Strict".+-- -- > {-# LANGUAGE KindSignatures #-} -- > {-# LANGUAGE FlexibleInstances #-} -- > {-# LANGUAGE MultiParamTypeClasses #-}
+ src/Control/THEff/Writer/Strict.hs view
@@ -0,0 +1,101 @@+{-# OPTIONS_HADDOCK show-extensions #-}++{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BangPatterns #-}++module Control.THEff.Writer.Strict (+ -- * Overview +-- |+-- This version builds its output strictly; for a lazy version with+-- the same interface, see "Control.THEff.Writer".+--+-- > {-# LANGUAGE KindSignatures #-}+-- > {-# LANGUAGE FlexibleInstances #-}+-- > {-# LANGUAGE MultiParamTypeClasses #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- > +-- > import Control.THEff+-- > import Control.THEff.Writer.Strict+-- > import Control.Monad(forM_) +-- > import Data.Monoid+-- > +-- > type IntAccum = Sum Int+-- > +-- > mkEff "StrWriter" ''Writer ''String ''NoEff+-- > mkEff "IntWriter" ''Writer ''IntAccum ''StrWriter+-- > +-- > main:: IO ()+-- > main = putStrLn $ uncurry (flip (++)) $ runStrWriter $ do+-- > tell "Result"+-- > (r, Sum v) <- runIntWriter $ do+-- > tell "="+-- > forM_ [1::Int .. 10]+-- > (tell . Sum)+-- > return (pi :: Float)+-- > return $ show $ r * fromIntegral v+-- +-- __/Output :/__ Result=172.7876+--+-- Note that for the effect `Writer' `mkEff' generates unary function runEEEE. `mkEff' chooses +-- generation unary or binary function runEEEE based on number of arguments of effect function. +-- E.g. runEffWriter.++ -- * Types and functions used in mkEff+ Writer'+ , Writer(..) + , WriterResT+ , effWriter+ , runEffWriter + -- * Functions that use this effect + , tell+ ) where++import Control.THEff+import Data.Monoid++-- | Actually, the effect type+-- - __/v/__ - Type - the parameter of the effect.+-- - __/e/__ - mkEff generated type.+data Writer' v e = Writer' !v (() -> e) ++-- | Type implements link in the chain of effects.+-- Constructors must be named __/{EffectName}{Outer|WriterAction|WriterResult}/__+-- and have a specified types of fields.+-- - __/m/__ - Or Monad (if use the 'Lift') or phantom type - stub (if used 'NoEff').+-- - __/o/__ - Type of outer effect.+-- - __/a/__ - The result of mkEff generated runEEEE... function.+data Writer (m:: * -> *) e o v a = WriterOuter (o m e)+ | WriterAction (Writer' v e) + | WriterResult a++-- | Result type of runEEEE. +type WriterResT r v = (r, v)++-- | This function is used in the 'mkEff' generated runEEEE functions and typically +-- in effect action functions. Calling the effect action.+effWriter:: EffClass Writer' v e => Writer' v r -> Eff e r+effWriter (Writer' v g) = effAction $ \k -> Writer' v (k . g)+ +-- | The main function of the effect implementing. +-- This function is used in the 'mkEff' generated runEEEE functions. +runEffWriter :: forall (t :: * -> *) (u :: (* -> *) -> * -> *) (m :: * -> *) + z v (m1 :: * -> *) e (o :: (* -> *) -> * -> *) w a r. (Monad m, Monoid v) =>+ (u t r -> (r -> m (WriterResT z v)) -> m (WriterResT z v)) -- ^ The outer effect function+ -> (Writer m1 e o w a -> r) -- ^ The chain of effects link wrapper.+ -> (r -> Writer t r u v z) -- ^ The chain of effects link unwrapper.+-- -> WriterArgT v -- unused argument!+ -> Eff r a+ -> m (WriterResT z v)+runEffWriter outer to un m = loop mempty $ runEff m (to . WriterResult)+ where + loop !s = select . un where+ select (WriterOuter g) = outer g (loop s)+ select (WriterAction (Writer' v k)) = let s' = s `mappend` v -- (f v)+ in loop s' (k ())+ select (WriterResult r) = return (r,s)++-- | Add value to monoid. +tell :: EffClass Writer' v e => v -> Eff e ()+tell !v = effWriter $ Writer' v (const ())