{-# LANGUAGE GADTs #-}
-- A very simple library for manipulating continuous signals.
module Signal.Deep
  ( 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
data Signal a where
  ConstS :: a -> Signal a
  TimeS  :: Signal Time
  MapT   :: (Time -> Time) -> Signal a -> Signal a
  (:$$)  :: Signal (a -> b) -> Signal a -> Signal b

-- | The constant signal.
constS x = ConstS x

-- | The time signal
timeS = TimeS

-- | Function application lifted to signals.
fs $$ xs = fs :$$ xs

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

-- | Transforming the time.
mapT = MapT

-- | Sampling a signal at a given time point.
sample (ConstS x) = const x
sample TimeS      = id
sample (f :$$ s)  = \t -> sample f t $ sample s t
sample (MapT f s) = sample s . f