Difference between revisions of "Performance/Monads"
From HaskellWiki
Line 15: | Line 15: | ||
<haskell> | <haskell> | ||
− | type DRM = DRMonad | + | type DRM = DRMonad Finish DNA RNA |
− | newtype DRMonad | + | newtype DRMonad e s w a = DRMonad {runDRMonad :: s -> (Either e a,s,w)} |
instance (Monoid m, Error e) => Monad (DRMonad e s w) where | instance (Monoid m, Error e) => Monad (DRMonad e s w) where |
Revision as of 08:41, 24 July 2007
Haskell Performance Resource
Constructs: Techniques: |
Unroll your MTL stacks
MTL is an excellent for programming with monads, however stacked monad transformers do not inline well and often impose a performance hit of up to 3X.
If you care about this, the best option is to flatten you stack of transformers into a single, hand unrolled monad. An extreme example follows.
This is a typical MTL monad stack
newtype DRM a = DRM {unDRM:: ErrorT Finish (RWS () DNA RNA) a} deriving (MonadState DNA, MonadWriter RNA, MonadError Finish, Monad)
We can unroll it as follows:
type DRM = DRMonad Finish DNA RNA
newtype DRMonad e s w a = DRMonad {runDRMonad :: s -> (Either e a,s,w)}
instance (Monoid m, Error e) => Monad (DRMonad e s w) where
return x = DRMonad(\s -> (Right x, s, mempty))
(>>= = bindDRMonad
fail _ = DRMonad (\s->(Left e,s,mempty))
{-# INLINE bindDRMonad #-}
{-# INLINE bindDRMonad2 #-}
bindDRMonad :: Monoid m => DRMonad a e s w -> (a -> DRMonad b e s w) -> DRMonad b e s w
bindDRMonad m f = DRMonad$ \s -> case runDRMonad m s of
(x',s',w) ->
bindDRMonad2 x' (s',w,f)
bindDRMonad2 x' (s',w, f) = case x' of
Left e -> (Left e, s', w)
Right r -> case runDRMonad (f r) s' of
(x'',s'',w') ->
(x'', s'', w `mappend` w')
After this, you will also want to add the instances for MonadState, MonadWriter, etc.