-- |
-- Module      : FRP.BearRiver.Basic
-- Copyright   : (c) Ivan Perez, 2014-2022
--               (c) George Giorgidze, 2007-2012
--               (c) Henrik Nilsson, 2005-2006
--               (c) Antony Courtney and Henrik Nilsson, Yale University, 2003-2004
-- License     : BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  : ivan.perez@keera.co.uk
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
--
-- Defines basic signal functions, and elementary ways of altering them.
--
-- This module defines very basic ways of creating and modifying signal
-- functions. In particular, it defines ways of creating constant output
-- producing SFs, and SFs that just pass the signal through unmodified.
--
-- It also defines ways of altering the input and the output signal only by
-- inserting one value in the signal, or by transforming it.
module FRP.BearRiver.Basic
    (
      -- * Basic signal functions
      identity
    , constant

      -- ** Initialization
    , (-->)
    , (-:>)
    , (>--)
    , (-=>)
    , (>=-)
    , initially
    )
  where

-- External imports
import qualified Control.Category as Category

-- Internal imports (dunai)
import Data.MonadicStreamFunction.InternalCore (MSF (MSF, unMSF))

-- Internal imports
import FRP.BearRiver.InternalCore (SF, arr)

infixr 0 -->, -:>, >--, -=>, >=-

-- * Basic signal functions

-- | Identity: identity = arr id
--
-- Using 'identity' is preferred over lifting id, since the arrow combinators
-- know how to optimise certain networks based on the transformations being
-- applied.
identity :: Monad m => SF m a a
identity :: forall (m :: * -> *) a. Monad m => SF m a a
identity = MSF (ClockInfo m) a a
forall a. MSF (ClockInfo m) a a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
Category.id

-- | Identity: constant b = arr (const b)
--
-- Using 'constant' is preferred over lifting const, since the arrow combinators
-- know how to optimise certain networks based on the transformations being
-- applied.
constant :: Monad m => b -> SF m a b
constant :: forall (m :: * -> *) b a. Monad m => b -> SF m a b
constant = (a -> b) -> MSF (ClockInfo m) a b
forall b c. (b -> c) -> MSF (ClockInfo m) b c
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr ((a -> b) -> MSF (ClockInfo m) a b)
-> (b -> a -> b) -> b -> MSF (ClockInfo m) a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> a -> b
forall a b. a -> b -> a
const

-- * Initialization

-- | Initialization operator (cf. Lustre/Lucid Synchrone).
--
-- The output at time zero is the first argument, and from that point on it
-- behaves like the signal function passed as second argument.
(-->) :: Monad m => b -> SF m a b -> SF m a b
b
b0 --> :: forall (m :: * -> *) b a. Monad m => b -> SF m a b -> SF m a b
--> SF m a b
sf = (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((a -> ClockInfo m (b, SF m a b)) -> SF m a b)
-> (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall a b. (a -> b) -> a -> b
$ \a
a -> do
  (b
_b, SF m a b
sf') <- SF m a b -> a -> ClockInfo m (b, SF m a b)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF SF m a b
sf a
a
  (b, SF m a b) -> ClockInfo m (b, SF m a b)
forall a. a -> ReaderT DTime m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b0, SF m a b
sf')

-- | Output pre-insert operator.
--
-- Insert a sample in the output, and from that point on, behave like the given
-- sf.
(-:>) :: Monad m => b -> SF m a b -> SF m a b
b
b -:> :: forall (m :: * -> *) b a. Monad m => b -> SF m a b -> SF m a b
-:> SF m a b
sf = (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((a -> ClockInfo m (b, SF m a b)) -> SF m a b)
-> (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall a b. (a -> b) -> a -> b
$ \a
_a -> (b, SF m a b) -> ClockInfo m (b, SF m a b)
forall a. a -> ReaderT DTime m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, SF m a b
sf)

-- | Input initialization operator.
--
-- The input at time zero is the first argument, and from that point on it
-- behaves like the signal function passed as second argument.
(>--) :: Monad m => a -> SF m a b -> SF m a b
a
a0 >-- :: forall (m :: * -> *) a b. Monad m => a -> SF m a b -> SF m a b
>-- SF m a b
sf = (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((a -> ClockInfo m (b, SF m a b)) -> SF m a b)
-> (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall a b. (a -> b) -> a -> b
$ \a
_ -> SF m a b -> a -> ClockInfo m (b, SF m a b)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF SF m a b
sf a
a0

-- | Transform initial output value.
--
-- Applies a transformation 'f' only to the first output value at time zero.
(-=>) :: Monad m => (b -> b) -> SF m a b -> SF m a b
b -> b
f -=> :: forall (m :: * -> *) b a.
Monad m =>
(b -> b) -> SF m a b -> SF m a b
-=> SF m a b
sf = (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((a -> ClockInfo m (b, SF m a b)) -> SF m a b)
-> (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall a b. (a -> b) -> a -> b
$ \a
a -> do
  (b
b, SF m a b
sf') <- SF m a b -> a -> ClockInfo m (b, SF m a b)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF SF m a b
sf a
a
  (b, SF m a b) -> ClockInfo m (b, SF m a b)
forall a. a -> ReaderT DTime m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> b
f b
b, SF m a b
sf')

-- | Transform initial input value.
--
-- Applies a transformation 'f' only to the first input value at time zero.
(>=-) :: Monad m => (a -> a) -> SF m a b -> SF m a b
a -> a
f >=- :: forall (m :: * -> *) a b.
Monad m =>
(a -> a) -> SF m a b -> SF m a b
>=- SF m a b
sf = (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((a -> ClockInfo m (b, SF m a b)) -> SF m a b)
-> (a -> ClockInfo m (b, SF m a b)) -> SF m a b
forall a b. (a -> b) -> a -> b
$ \a
a -> do
  (b
b, SF m a b
sf') <- SF m a b -> a -> ClockInfo m (b, SF m a b)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF SF m a b
sf (a -> a
f a
a)
  (b, SF m a b) -> ClockInfo m (b, SF m a b)
forall a. a -> ReaderT DTime m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, SF m a b
sf')

-- | Override initial value of input signal.
initially :: Monad m => a -> SF m a a
initially :: forall (m :: * -> *) a. Monad m => a -> SF m a a
initially = (a -> SF m a a -> SF m a a
forall (m :: * -> *) b a. Monad m => b -> SF m a b -> SF m a b
--> SF m a a
forall (m :: * -> *) a. Monad m => SF m a a
identity)