timeplot-1.0.24: Tools/TimePlot/Incremental.hs
{-# LANGUAGE GADTs, BangPatterns #-}
module Tools.TimePlot.Incremental where
import Data.Time
import qualified Data.List as L
import qualified Data.Map as M
import Control.Applicative
data StreamSummary a r where
Summary :: { insert :: a -> StreamSummary a r, finalize :: r } -> StreamSummary a r
instance Functor (StreamSummary a) where
fmap f (Summary insert res) = Summary (fmap f . insert) (f res)
instance Applicative (StreamSummary a) where
pure r = Summary (\_ -> pure r) r
(!fs) <*> (!xs) = Summary (\a -> insert fs a <*> insert xs a) (finalize fs $ finalize xs)
runStreamSummary :: StreamSummary a r -> [a] -> r
runStreamSummary !s [] = finalize s
runStreamSummary !s (a:as) = runStreamSummary (insert s a) as
stateful :: s -> (a -> s -> s) -> (s -> r) -> StreamSummary a r
stateful init insert finalize = go init
where
go !s = Summary (\a -> go (insert a s)) (finalize s)
filterMap :: (a -> Maybe b) -> StreamSummary b r -> StreamSummary a r
filterMap p s@(Summary insert res) = Summary insert' res
where
insert' a = case p a of { Nothing -> filterMap p s ; Just b -> filterMap p (insert b) }
mapInput :: (a -> b) -> StreamSummary b r -> StreamSummary a r
mapInput f (Summary insert res) = Summary (mapInput f . insert . f) res
collect :: StreamSummary a [a]
collect = stateful [] (:) reverse
byTimeBins :: (Ord t) => [t] -> StreamSummary (t,[a]) r -> StreamSummary (t,a) r
byTimeBins ts s = stateful init' insert' finalize'
where
init' = (ts, [], s)
insert' (t,a) (t1:t2:ts, curBin, !s)
| t < t1 = error "Times are not in ascending order"
| t < t2 = (t1:t2:ts, a:curBin, s)
| True = insert' (t, a) (t2:ts, [], insert s (t1, reverse curBin))
finalize' (t1:t2:ts, curBin, s) = finalize (insert s (t1,reverse curBin))
byKey :: (Ord k) => (k -> StreamSummary v r) -> StreamSummary (k,v) (M.Map k r)
byKey initByKey = stateful init' insert' finalize'
where
init' = M.empty
insert' (k,v) m = case M.lookup k m of
Nothing -> M.insert k (insert (initByKey k) v) m
Just !s -> M.insert k (insert s v) m
finalize' = fmap finalize