Difference between revisions of "New monads"
(add link to MonadLib) |
(Link to wiki page on monadLib instead of old galios.com pages) |
||
(29 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
__TOC__ |
__TOC__ |
||
+ | |||
+ | Remember to add a [ [ Category:Code ] ] tag to any new sub-pages. |
||
== MonadBase == |
== MonadBase == |
||
Line 5: | Line 7: | ||
It seems that the liftIO function from MonadIO can be generalized to access whatever the base of a transformer stack happens to be. So there is no need for a liftSTM, liftST, etc. |
It seems that the liftIO function from MonadIO can be generalized to access whatever the base of a transformer stack happens to be. So there is no need for a liftSTM, liftST, etc. |
||
+ | View [[New monads/MonadBase]]. |
||
− | <haskell> |
||
− | -- By Chris Kuklewicz |
||
− | module MonadBase(MonadBase,liftBase,MonadIO',liftIO') where |
||
+ | == MonadLib == |
||
− | import Data.Monoid(Monoid) |
||
− | import Control.Monad.Trans(lift,MonadTrans) |
||
− | -- All the base monads with GHC |
||
− | import Control.Monad.ST.Strict as S(ST) |
||
− | import Control.Monad.ST.Lazy as L(ST) |
||
− | import Control.Concurrent.STM(STM) |
||
− | import Control.Monad.Identity(Identity) |
||
− | import Text.ParserCombinators.Parsec(GenParser) |
||
− | -- And all the MonadIO instances: |
||
− | import Control.Monad.List(ListT) |
||
− | import Control.Monad.Cont(ContT) |
||
− | import Control.Monad.Error(ErrorT,Error) |
||
− | import Control.Monad.Reader(ReaderT) |
||
− | import Control.Monad.State(StateT) |
||
− | import Control.Monad.Writer(WriterT) |
||
− | import Control.Monad.RWS(RWST) |
||
+ | [[MonadLib]] is written by Iavor S. Diatchki. |
||
− | class (Monad m,Monad b) => MonadBase b m where |
||
− | liftBase :: b a -> m a |
||
+ | It is a new version of the mtl package with base monads: Id, and Lift, and transformers ReaderT, WriterT, StateT, ExceptionT, ChoiceT, and ContT. |
||
− | -- One can recover MonadIO and liftIO from MonadBase |
||
− | class (MonadBase IO m) => MonadIO' m where |
||
− | liftIO' :: IO a -> m a |
||
− | liftIO' = liftBase |
||
+ | It also defines BaseM which is like MonadBase above. |
||
− | -- Base monads |
||
− | instance MonadBase IO IO where liftBase = id |
||
− | instance MonadBase STM STM where liftBase = id |
||
− | instance MonadBase (GenParser tok st) (GenParser tok st) where liftBase = id |
||
− | instance MonadBase (S.ST s) (S.ST s) where liftBase = id |
||
− | instance MonadBase (L.ST s) (L.ST s) where liftBase = id |
||
− | instance MonadBase Maybe Maybe where liftBase = id |
||
− | instance MonadBase [] [] where liftBase = id |
||
− | instance (Error e) => MonadBase (Either e) (Either e) where liftBase = id |
||
− | instance MonadBase ((->) a) ((->) a) where liftBase = id |
||
− | instance MonadBase Identity Identity where liftBase = id |
||
+ | == MonadRandom == |
||
− | -- Trans monads |
||
− | instance MonadBase b m => MonadBase b (ListT m) where |
||
− | liftBase = lift . liftBase |
||
− | instance MonadBase b m => MonadBase b (ContT r m) where |
||
− | liftBase = lift . liftBase |
||
− | instance (Error e, MonadBase b m) => MonadBase b (ErrorT e m) where |
||
− | liftBase = lift . liftBase |
||
− | instance MonadBase b m => MonadBase b (ReaderT r m) where |
||
− | liftBase = lift . liftBase |
||
− | instance MonadBase b m => MonadBase b (StateT s m) where |
||
− | liftBase = lift . liftBase |
||
− | instance (Monoid w, MonadBase b m) => MonadBase b (WriterT w m) where |
||
− | liftBase = lift . liftBase |
||
− | instance (Monoid w, MonadBase b m) => MonadBase b (RWST r w s m) where |
||
− | liftBase = lift . liftBase |
||
− | </haskell> |
||
+ | A simple monad transformer to allow computations in the transformed monad to generate random values. |
||
− | And an artificial example: |
||
+ | View [[New monads/MonadRandom]]. |
||
− | <haskell> |
||
− | module Main where |
||
+ | ===MonadRandomSplittable=== |
||
− | import MonadBase |
||
+ | A refinement of MonadRandom to integrate RandomGen's split function. |
||
− | import Control.Monad.Reader |
||
− | import Control.Monad.Writer |
||
− | type Foo a = (WriterT [Int] (ReaderT String [])) a |
||
+ | View at [[New monads/MonadRandomSplittable]] |
||
− | foo :: Foo String |
||
− | foo = do |
||
− | x <- liftBase [1,2,3] |
||
− | s <- ask |
||
− | tell [succ x] |
||
− | return (s ++ show x) |
||
+ | == MaybeT == |
||
− | test = runReaderT (runWriterT foo) "hello" |
||
− | </haskell> |
||
+ | The Maybe monad deserves a transformer, just like the other classic monads. |
||
− | <pre> |
||
− | *Main> test |
||
− | [("hello1",[2]),("hello2",[3]),("hello3",[4])] |
||
− | </pre> |
||
+ | View [[New monads/MaybeT]]. |
||
− | == |
+ | == MonadSupply == |
+ | |||
+ | Here is a simple monad/monad transformer for computations which consume values from a (finite or infinite) supply. Note that due to pattern matching, running out of supply in a non-MonadZero monad will cause an error. |
||
+ | |||
+ | View [[New monads/MonadSupply]]. |
||
+ | |||
+ | == MonadUndo == |
||
+ | |||
+ | Here is a modified state monad transformer for keeping track of undo/redo states automatically. |
||
+ | |||
+ | View [[New monads/MonadUndo]]. |
||
+ | |||
+ | == MonadUnique == |
||
+ | |||
+ | This is a simple (trivial) monad transformer for supplying unique integer values to an algorithm. |
||
+ | |||
+ | View [[New monads/MonadUnique]]. |
||
+ | |||
+ | == MonadSTO == |
||
+ | |||
+ | Here's an extension of the ST monad in which the references are ordered and showable (they list their creation index). |
||
+ | |||
+ | View [[New monads/MonadSTO]]. |
||
+ | |||
+ | == MonadNondet == |
||
+ | |||
+ | There is a [[Sudoku#Monadic_Non-Deterministic_Solver | MonadNondet]] that when compiled with optimizations outperforms List. |
||
+ | |||
+ | == Stateful nondeterminism == |
||
+ | |||
+ | There is a [[Stateful nondeterminism]] monad for if you want to do nondeterministic computation with local states for each of your threads and a global state shared by all your threads. |
||
+ | |||
+ | == MonadAdvSTM == |
||
+ | |||
+ | Here is an extension of STM to easy interaction with IO after committing or retrying. Inspired by Simon P-J. |
||
+ | |||
+ | View [[New monads/MonadAdvSTM]]. |
||
+ | |||
+ | == TimedStateT == |
||
+ | |||
+ | A monad transformer which combines State, Reader, and Error functionality to give the effect of a StateT monad which checks clock-time and stops the current computation if a period is exceeded. |
||
+ | |||
+ | darcs get http://www.mapcar.org/haskell/TimedStateT/ |
||
+ | |||
+ | Haddocks: http://www.mapcar.org/haskell/TimedStateT/dist/doc/html/ |
||
+ | |||
+ | == MonadExit == |
||
+ | |||
+ | The Exit monad provides [[short-circuiting]] for complex program flow logic. |
||
+ | |||
+ | If you are using CPS or MonadCont only for this purpose, the Exit monad will likely simplify your program considerably. |
||
+ | |||
+ | View [[New monads/MonadExit|MonadExit]]. |
||
+ | |||
+ | == MonadSplit == |
||
+ | |||
+ | Represents the class of monads such that |
||
+ | |||
+ | <haskell>l == (msplit l >>= \(x,xs) -> return x `mplus` xs)</haskell> |
||
+ | |||
+ | In English, msplit is a counterpart to "mplus". |
||
+ | |||
+ | Using this, you can redefine many of the functions which previously depended on lists: foldM, scanM, inits, tails, and some derived functions. |
||
+ | |||
+ | Note: A more general form of this monad, |
||
+ | [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Foldable.html Data.Foldable], is now part of the |
||
+ | [http://haskell.org/ghc/docs/latest/html/libraries/ standard libraries]. |
||
+ | |||
+ | View [[New monads/MonadSplit]]. |
||
+ | |||
+ | == Lazy and Strict variants == |
||
+ | |||
+ | This section contains monads that have interesting Strict or Lazy properties. |
||
+ | |||
+ | === LazyWriterT === |
||
+ | |||
+ | This came up on the mailing list: Why is WriterT never lazy? The answer is it does not use lazy patterns with "~". So here is a more useful [[New monads/LazyWriterT]] that add two "~" to the definition of (>>=) and renames WriterT to LazyWriterT. |
||
+ | === Strict RWS === |
||
− | This is by Iavor S. Diatchki and can be found at http://www.cse.ogi.edu/~diatchki/monadLib/ |
||
+ | This was contribute by John Meacham on on the haskell-cafe mailing list. [[New monads/UnboxedRWS]] is an strict variant of RWS. |
||
− | It a new version of the mtl package with transformers: ReaderT WriterT StateT ExceptT SearchT ContT |
||
+ | [[Category:Idioms]] |
||
− | It also defined BaseM which is like MonadBase above. |
||
+ | [[Category:Monad]] |
||
+ | [[Category:Proposals]] |
Revision as of 23:10, 7 September 2010
Remember to add a [ [ Category:Code ] ] tag to any new sub-pages.
MonadBase
It seems that the liftIO function from MonadIO can be generalized to access whatever the base of a transformer stack happens to be. So there is no need for a liftSTM, liftST, etc.
View New monads/MonadBase.
MonadLib
MonadLib is written by Iavor S. Diatchki.
It is a new version of the mtl package with base monads: Id, and Lift, and transformers ReaderT, WriterT, StateT, ExceptionT, ChoiceT, and ContT.
It also defines BaseM which is like MonadBase above.
MonadRandom
A simple monad transformer to allow computations in the transformed monad to generate random values.
View New monads/MonadRandom.
MonadRandomSplittable
A refinement of MonadRandom to integrate RandomGen's split function.
View at New monads/MonadRandomSplittable
MaybeT
The Maybe monad deserves a transformer, just like the other classic monads.
View New monads/MaybeT.
MonadSupply
Here is a simple monad/monad transformer for computations which consume values from a (finite or infinite) supply. Note that due to pattern matching, running out of supply in a non-MonadZero monad will cause an error.
View New monads/MonadSupply.
MonadUndo
Here is a modified state monad transformer for keeping track of undo/redo states automatically.
View New monads/MonadUndo.
MonadUnique
This is a simple (trivial) monad transformer for supplying unique integer values to an algorithm.
View New monads/MonadUnique.
MonadSTO
Here's an extension of the ST monad in which the references are ordered and showable (they list their creation index).
View New monads/MonadSTO.
MonadNondet
There is a MonadNondet that when compiled with optimizations outperforms List.
Stateful nondeterminism
There is a Stateful nondeterminism monad for if you want to do nondeterministic computation with local states for each of your threads and a global state shared by all your threads.
MonadAdvSTM
Here is an extension of STM to easy interaction with IO after committing or retrying. Inspired by Simon P-J.
View New monads/MonadAdvSTM.
TimedStateT
A monad transformer which combines State, Reader, and Error functionality to give the effect of a StateT monad which checks clock-time and stops the current computation if a period is exceeded.
darcs get http://www.mapcar.org/haskell/TimedStateT/
Haddocks: http://www.mapcar.org/haskell/TimedStateT/dist/doc/html/
MonadExit
The Exit monad provides short-circuiting for complex program flow logic.
If you are using CPS or MonadCont only for this purpose, the Exit monad will likely simplify your program considerably.
View MonadExit.
MonadSplit
Represents the class of monads such that
l == (msplit l >>= \(x,xs) -> return x `mplus` xs)
In English, msplit is a counterpart to "mplus".
Using this, you can redefine many of the functions which previously depended on lists: foldM, scanM, inits, tails, and some derived functions.
Note: A more general form of this monad, Data.Foldable, is now part of the standard libraries.
View New monads/MonadSplit.
Lazy and Strict variants
This section contains monads that have interesting Strict or Lazy properties.
LazyWriterT
This came up on the mailing list: Why is WriterT never lazy? The answer is it does not use lazy patterns with "~". So here is a more useful New monads/LazyWriterT that add two "~" to the definition of (>>=) and renames WriterT to LazyWriterT.
Strict RWS
This was contribute by John Meacham on on the haskell-cafe mailing list. New monads/UnboxedRWS is an strict variant of RWS.