I collect realtime signals, compute derived signals and store both raw and derived data in a circular buffer, so I hold only last million of samples.
Sometimes I need to serialize current values for all signals. So I need something like:
type D0 a = M.Map SignalType D1
data D1 a = D1
{ foo :: M.Map DoorType a
, bar :: D2 a
, baz :: a
}
data D2 = D2
{
quux :: a
, zoo :: a
}
data MyData = D0 SignalBuffer
data CurrentSignals = D0 SignalValue
SignalBuffer
is a sequence of SignalValue
. It can be an unboxed array of floats. Haskell can derive Functor
instances for me, so I can use fmap
to fetch last SignalValue
from every SignalBuffer
and pass the structure to Aeson
to serialize.
How do I implement a circular buffer API for SignalBuffer
so I can push new values to all the buffers when new ticks arrive? I'd like to conserve memory, so I think I have to use unboxed arrays. Is it advantageous to use mutable unboxed arrays (STUArray
?) so array updates don't pile up in memory? Is it possible to use mutable arrays in this setting at all? I'm ready to change MyData
and CurrentSignals
to whatever does the job.
I know how to implement circular buffers, the question is how to elegantly apply the updates to MyData
.
I'm thinking of something like
type UpdateFunc a = MyData -> SignalValue -> Modifier SignalBuffer
updateAllBuffers :: D0 UpdateFunc -> Modifier MyData
Some signals are "convolutions" of other signals (not real convolutions, but a similar kind of processing). To update a buffer for a signal I need to access buffers of other signals - that's why UpdateFunc accepts MyData
and SignalValue
and returns a buffer modification function.
updateAllBuffers
then "zips" D0 UpdateFunc
and MyData
to get new MyData
.
Of course I'm ready to use whatever Modifier
fits my task - it can be a function, a monadic value etc.