Difference between revisions of "Performance/Monads"

From HaskellWiki
Jump to navigation Jump to search
 
Line 16: Line 16:
 
<haskell>
 
<haskell>
 
type DRM = DRMonad
 
type DRM = DRMonad
newtype DRMonad a = DRMonad {runDRMonad :: DNA -> (Either Finish a,DNA,RNA)}
+
newtype DRMonad a e s w = DRMonad {runDRMonad :: s -> (Either e a,s,w)}
   
instance Monad DRMonad where
+
instance (Monoid m, Error e) => Monad (DRMonad e s w) where
 
return x = DRMonad(\s -> (Right x, s, mempty))
 
return x = DRMonad(\s -> (Right x, s, mempty))
 
(>>= = bindDRMonad
 
(>>= = bindDRMonad
fail _ = DRMonad (\s->(Left Finish,s,mempty))
+
fail _ = DRMonad (\s->(Left e,s,mempty))
   
 
{-# INLINE bindDRMonad #-}
 
{-# INLINE bindDRMonad #-}
 
{-# INLINE bindDRMonad2 #-}
 
{-# INLINE bindDRMonad2 #-}
bindDRMonad :: DRMonad a -> (a -> DRMonad b) -> DRMonad b
+
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
 
bindDRMonad m f = DRMonad$ \s -> case runDRMonad m s of
 
(x',s',w) ->
 
(x',s',w) ->

Revision as of 01:11, 24 July 2007

Haskell Performance Resource

Constructs:
Data Types - Functions
Overloading - FFI - Arrays
Strings - Integers - I/O
Floating point - Concurrency
Modules - Monads

Techniques:
Strictness - Laziness
Avoiding space leaks
Accumulating parameter

Implementation-Specific:
GHC - nhc98 - Hugs
Yhc - JHC

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
newtype DRMonad a e s w = 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')