-- A very simple library for manipulating continuous signals.
module Signal.Shallow
  ( Time
  , Signal  -- the Signal type is abstract
  , ($$), constS, mapS, mapT, sample, timeS
  ) where

-- smart constructors
constS :: a -> Signal a
timeS  ::      Signal Time
-- Combinators
($$)   :: Signal (a -> b) -> Signal a -> Signal b
mapS   :: (a -> b)        -> Signal a -> Signal b
mapT   :: (Time -> Time)  -> Signal a -> Signal a
-- run function
sample :: Signal a -> Time -> a  

type Time = Double
newtype Signal a = Sig {unSig :: Time -> a}

-- | The constant signal.
constS x = Sig (\t -> x)

-- | The time signal
timeS = Sig id

-- | Function application lifted to signals.
fs $$ xs = Sig (\t -> (unSig fs t) (unSig xs t))

-- | Mapping a function over a signal.
mapS f xs = constS f $$ xs

-- | Transforming the time.
mapT f xs = Sig (\t -> unSig xs (f t))

-- | Sampling a signal at a given time point.
-- This is the /semantic function/ of our library.
sample = unSig