[Haskell-cafe] Daunting heap profile when using (<>)

martin martin.drautzburg at web.de
Sat Nov 14 10:10:15 UTC 2015

Hello all,

I have a Logger which produces log entries and a new version of itself

newtype Logger evt dom log = Lgr {runLogger :: Timed evt -> dom -> (log, Logger evt dom log)}

Loggers are used in a function like this

runSim :: (Ord evt, Monoid log) => SimBehaviour evt dom log -> SimState evt dom log -> SimState evt dom log
runSim (!lgr, !hdr, xtp) (!log,!dom,!evq)  =
        case step of
            Nothing -> (log, dom, evq) -- end of simulation
            Just (newEvq, newDom, newHdr, newLgr, newLog) -> runSim (newLgr,newHdr,xtp) (newLog,newDom,newEvq)
            -- check for end conditions or run handler
            step = do
                (evt, evts) <- H.view evq -- no more Events -> Nothing
                if xtp (evt,dom)  then Nothing
                        let (evq', dom', hdr') = runHandler hdr evt dom
                            (log',lgr')        = runLogger lgr evt dom'        -- <--
                        -- append new event and new log entries
                        in return (evq'<>evts, dom', hdr', lgr', log'<>log)    -- <--

I then wrote a function to combine two Loggers

addLgr (lgr1) (lgr2) = Lgr lgr
            lgr tev dom = let (log1', lgr1') = runLogger lgr1  tev dom
                              (log2', lgr2') = runLogger lgr2  tev dom
                              (!log') = log2'  <> log1'                       -- x --
--                          in (log2', addLgr lgr1' lgr2')
                          in (log', addLgr lgr1' lgr2')

When called a million times, this produces a heap profile which climbs steadily (with or without the stricness
annotation in line x). When I omit the (<>) as in the commented line, the heap stays flat. My log is really just a list
of strings and most of the time the loggers do not produce any output, i.e. they return an empty list.

Am I on the right track, that this trouble is probably caused by laziness and that forcing strictness is the way to go?

Could it be that this is because ! does not fully evaluate its argument, but just to WHNF? Or is there a more obvious
reason, I just fail to see.

Where to go from here?

More information about the Haskell-Cafe mailing list