monad-gen (empty) → 0.1.0.0
raw patch · 4 files changed
+131/−0 lines, 4 filesdep +basedep +mtldep +transformerssetup-changed
Dependencies added: base, mtl, transformers
Files
- LICENSE +20/−0
- Setup.hs +2/−0
- monad-gen.cabal +26/−0
- src/Control/Monad/Gen.hs +83/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2014 Danny Gratzer++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ monad-gen.cabal view
@@ -0,0 +1,26 @@+name: monad-gen+version: 0.1.0.0+synopsis: A simple monad for generating fresh integers+description: It's a common in Haskell programs to thread some state+ through the application using @State@ or some other similar pattern.++ This package simply wraps @State@ and uses it to generate fresh values,+ any @Enum@ value will work.+license: MIT+license-file: LICENSE+author: Danny Gratzer+maintainer: danny.gratzer@gmail.com+category: Utility++build-type: Simple++cabal-version: >=1.10+++library+ exposed-modules: Control.Monad.Gen+ other-extensions: FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, DeriveFunctor+ build-depends: base >=4.6 && <5.0, mtl == 2.*, transformers > 0.3+ hs-source-dirs: src+ default-language: Haskell2010+
+ src/Control/Monad/Gen.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances, DeriveFunctor, FunctionalDependencies #-}+module Control.Monad.Gen+ ( GenT+ , Gen+ , MonadGen(..)+ , runGenT+ , runGen+ , runGenTInt+ , runGenInt) where+import Control.Applicative+import Control.Monad.Cont+import Control.Monad.Identity+import Control.Monad.Reader+import Control.Monad.State+import Control.Monad.Writer+import Control.Monad.Trans.Identity+import Control.Monad.Error+import Control.Monad.Trans.Maybe+import Control.Monad.Trans.List+import qualified Control.Monad.Trans.State as State+-- | The monad transformer for generating fresh values.+newtype GenT e m a = GenT {unGenT :: StateT e m a}+ deriving(Functor)+instance Monad m => Monad (GenT e m) where+ return = GenT . return+ (GenT m) >>= f = GenT $ m >>= unGenT . f+instance (Functor f, Monad f) => Applicative (GenT e f) where+ pure = GenT . pure+ (GenT f) <*> (GenT a) = GenT $ f <*> a++type Gen e = GenT e Identity++instance MonadTrans (GenT e) where+ lift = GenT . lift++instance MonadReader r m => MonadReader r (GenT e m) where+ local f = GenT . local f . unGenT+ ask = GenT ask+instance MonadState s m => MonadState s (GenT e m) where+ get = GenT $ lift get+ put = GenT . lift . put+instance (MonadWriter w m) => MonadWriter w (GenT e m) where+ tell m = lift $ tell m+ listen = GenT . listen . unGenT+ pass = GenT . pass . unGenT++-- | The MTL style class for generating fresh values+class Monad m => MonadGen e m | m -> e where+ -- | Generate a fresh value @e@, @gen@ should never produce the+ -- same value within a monadic computation.+ gen :: m e++instance (Monad m, Enum e) => MonadGen e (GenT e m) where+ gen = GenT $ modify succ >> get+instance MonadGen e m => MonadGen e (IdentityT m) where+ gen = lift gen+instance MonadGen e m => MonadGen e (StateT s m) where+ gen = lift gen+instance MonadGen e m => MonadGen e (ReaderT s m) where+ gen = lift gen+instance (MonadGen e m, Monoid s) => MonadGen e (WriterT s m) where+ gen = lift gen+instance MonadGen e m => MonadGen e (ListT m) where+ gen = lift gen+instance MonadGen e m => MonadGen e (MaybeT m) where+ gen = lift gen+instance (MonadGen e m, Error err) => MonadGen e (ErrorT err m) where+ gen = lift gen++runGenT :: Monad m => e -> GenT e m a -> m a+runGenT e = flip evalStateT e . unGenT++runGen :: e -> Gen e a -> a+runGen e = runIdentity . runGenT e++-- | A shortcut for the common case where we want fresh+-- `Integer`s.+runGenTInt :: Monad m => GenT Integer m a -> m a+runGenTInt = runGenT 0++runGenInt :: Gen Integer a -> a+runGenInt = runIdentity . runGenTInt