Closed hanshoglund closed 11 years ago
This may not actually be worth it. Consider:
Loose thinking: Control values are more similar to FRP events, i.e. they need to be processed spuriously. There is a difference between a DSP engine and an FRP system. Building a hybrid is an interesting challenge, but possibly the wrong thing to do here.
Another note: if we allow polymorphic signals Signal a
etc, we must also type the inputs and outputs, which does not work with the current state implementation. Consider
step :: Signal a -> State -> (a, State)
step = go
where
-- Ignoring Random and Time for now
go (Constant x) !s = {-# SCC "constant" #-} (x, s)
go (Lift _ f a) !s = {-# SCC "lift" #-} let
(!xa, !sa) = a `step` s
in (f xa, sa)
go (Lift2 _ f a b) !s = {-# SCC "lift2" #-} let
(!xa, !sa) = a `step` s
(!xb, !sb) = b `step` sa
in (f xa xb, sb)
go (Input c) !s = {-# SCC "input" #-} (readSamp c s, s)
go (Output n c a) !s = {-# SCC "output" #-} let
(xa, sa) = a `step` s
in (xa, writeSamp n c xa sa)
While constants and lifts are no problem, input and output would need to be restricted to doubles because readSamp :: Int -> State -> Double
and writeSamp :: Int -> Int -> Double -> State -> State
.
Maybe we could do this with GADTs and add new constructors ControlInput
and ControlOutput
for controls. However then we have the same problem. Maybe the best compromise is to use Dynamic
for this.
Closing and replacing with more specific: #6
Not just
Double
, butFloat
,Int
,(a,a)
,Typable a => a
etc.