content: {-|
  
  This module contains the reference implementation for the pure subset
  of the simple variant of Elerea.  I/O embedding is substituted by
  conversion from and to lists.
  
  -}
  
  module FRP.Elerea.Simple.Pure
      (
      -- * The signal abstraction
        Signal
      , SignalGen
      -- * Inputs and outputs
      , fromList
      , toList
      , start
      -- * Basic building blocks
      , delay
      , snapshot
      , generator
      , memo
      , until
      -- * Derived combinators
      , stateful
      , transfer
      , transfer2
      , transfer3
      , transfer4
      ) where
  
  import Control.Applicative
  import Control.Monad
  import Control.Monad.Fix
  
  type Signal a = Int -> a
  
  type SignalGen a = Int -> a
  
  fromList :: [a] -> Signal a
  fromList = (!!)
  
  toList :: Signal a -> [a]
  toList s = map s [0..]
  
  start :: SignalGen (Signal a) -> [a]
  start g = toList (g 0)
  
  delay :: a -> Signal a -> SignalGen (Signal a)
  delay x0 s t_start t_sample
      | t_start < t_sample  = s (t_sample-1)
      | t_start == t_sample = x0
      | otherwise           = error "This signal doesn't exist yet."
  
  generator :: Signal (SignalGen a) -> SignalGen (Signal a)
  generator s _t_start t_sample = s t_sample t_sample
  
  snapshot :: Signal a -> SignalGen a
  snapshot = id
  
  memo :: Signal a -> SignalGen (Signal a)
  memo = const
  
  stateful :: a -> (a -> a) -> SignalGen (Signal a)
  stateful x0 f = mfix $ \sig -> delay x0 (f <$> sig)
  
  transfer :: a -> (t -> a -> a) -> Signal t -> SignalGen (Signal a)
  transfer x0 f s = mfix $ \sig -> do
      sig' <- delay x0 sig
      memo (liftA2 f s sig')
  
  transfer2 :: a -> (t1 -> t2 -> a -> a) -> Signal t1 -> Signal t2 -> SignalGen (Signal a)
  transfer2 x0 f s1 s2 = mfix $ \sig -> do
      sig' <- delay x0 sig
      memo (liftA3 f s1 s2 sig')
  
  transfer3 :: a -> (t1 -> t2 -> t3 -> a -> a) -> Signal t1 -> Signal t2 -> Signal t3 -> SignalGen (Signal a)
  transfer3 x0 f s1 s2 s3 = mfix $ \sig -> do
      sig' <- delay x0 sig
      memo (liftM4 f s1 s2 s3 sig')
  
  transfer4 :: a -> (t1 -> t2 -> t3 -> t4 -> a -> a) -> Signal t1 -> Signal t2 -> Signal t3 -> Signal t4 -> SignalGen (Signal a)
  transfer4 x0 f s1 s2 s3 s4 = mfix $ \sig -> do
      sig' <- delay x0 sig
      memo (liftM5 f s1 s2 s3 s4 sig')
  