Tue Aug 4 22:03:22 EDT 2015
Applicative signal processor
Is it possible to have a type
Sig i -> (m) Sig o
representing say an accumulator say using Applicative? If so, then
instantiating Data for Sig is the only thing that needs to be done.
E.g. Arrow isn't necessary: (->) is enough.
Let's see. The core is:
(Sig f0 f) <*> (Sig a0 a) = Sig (f0, a0) fa where
fa (sf, sa) = do
-- Set order left-to-right
(sf', f') <- f sf
(sa', a') <- a sa
return ((sf', sa'), f' a')
It doesn't look like applicative itself can do antyhing but combining
pure functions with effects (the Applicative "container").
The construction of signal processors then has to come from extra
functionality. Primitives are constructed separately.
-- Construct primitive signal processors from update equations.
type Update m s i o = i -> s -> m (s, o)
type Proc m i o = Sig m i -> (Sig m o)
proc :: SigState m s => s -> Update m s i o -> Proc m i o
proc u0 u (Sig i0 i) = Sig o0 o where
o0 = (i0, u0)
o (si, su) = do
(si', i') <- i si
(su', o') <- u i' su
return $ ((si', su'), o')
What comes out here naturally, is that input arrays are better
represented by input signals!
So Somewhat surprising signals are "pure". The monad is completely
So the next question is: how to share signals?
Turn the above into a monad:
(Sig m i) -> (i -> Sig m o) -> (Sig m i)
The funny thing is that in writing this instance, it seems as if too
much flexibility is introduced: it is not true that a single input
value can influence w hole output Signal.
i -> Sig m o
Doesn't make sense.
This leads me to believe that sharing (memoization) is not a monad.