Performance/Monads
From HaskellWiki
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.