Performance/Monads
From HaskellWiki
Line 3: | Line 3: | ||
== Unroll your MTL stacks == | == Unroll your MTL stacks == | ||
− | MTL is an excellent for programming with monads | + | MTL is an excellent library for programming with monads. However stacked monad transformers do not inline well and the library is in need of an optimization pass. As a result, it can often impose a performance hit of up to 300% (your code will run up to three times slower). |
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. | 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. |
Revision as of 08:47, 24 July 2007
Haskell Performance Resource
Constructs: Techniques: |
Unroll your MTL stacks
MTL is an excellent library for programming with monads. However stacked monad transformers do not inline well and the library is in need of an optimization pass. As a result, it can often impose a performance hit of up to 300% (your code will run up to three times slower).
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.