-- |
-- Copyright  : (c) Ivan Perez, 2019-2022
--              (c) Ivan Perez and Manuel Baerenz, 2016-2018
-- License    : BSD3
-- Maintainer : ivan.perez@keera.co.uk
--
-- Well-initialised loops.
module FRP.BearRiver.Loop
    (
      -- * Loops with guaranteed well-defined feedback
      loopPre
    , loopIntegral
    )
  where

-- External imports
import Control.Arrow     (loop, second, (>>>))
import Control.Monad.Fix (MonadFix)
import Data.VectorSpace  (VectorSpace)

-- Internal imports
import FRP.BearRiver.Delays       (iPre)
import FRP.BearRiver.Integration  (integral)
import FRP.BearRiver.InternalCore (SF)

-- * Loops with guaranteed well-defined feedback

-- | Loop with an initial value for the signal being fed back.
loopPre :: MonadFix m => c -> SF m (a, c) (b, c) -> SF m a b
loopPre :: forall (m :: * -> *) c a b.
MonadFix m =>
c -> SF m (a, c) (b, c) -> SF m a b
loopPre c
cInit SF m (a, c) (b, c)
sf = SF m (a, c) (b, c) -> MSF (ClockInfo m) a b
forall b d c.
MSF (ClockInfo m) (b, d) (c, d) -> MSF (ClockInfo m) b c
forall (a :: * -> * -> *) b d c.
ArrowLoop a =>
a (b, d) (c, d) -> a b c
loop (MSF (ClockInfo m) c c -> MSF (ClockInfo m) (a, c) (a, c)
forall b c d.
MSF (ClockInfo m) b c -> MSF (ClockInfo m) (d, b) (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (c -> MSF (ClockInfo m) c c
forall (m :: * -> *) a. Monad m => a -> SF m a a
iPre c
cInit) MSF (ClockInfo m) (a, c) (a, c)
-> SF m (a, c) (b, c) -> SF m (a, c) (b, c)
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> SF m (a, c) (b, c)
sf)

-- | Loop by integrating the second value in the pair and feeding the result
-- back. Because the integral at time 0 is zero, this is always well defined.
loopIntegral :: (MonadFix m, Fractional s, VectorSpace c s) => SF m (a, c) (b, c) -> SF m a b
loopIntegral :: forall (m :: * -> *) s c a b.
(MonadFix m, Fractional s, VectorSpace c s) =>
SF m (a, c) (b, c) -> SF m a b
loopIntegral SF m (a, c) (b, c)
sf = SF m (a, c) (b, c) -> MSF (ClockInfo m) a b
forall b d c.
MSF (ClockInfo m) (b, d) (c, d) -> MSF (ClockInfo m) b c
forall (a :: * -> * -> *) b d c.
ArrowLoop a =>
a (b, d) (c, d) -> a b c
loop (MSF (ClockInfo m) c c -> MSF (ClockInfo m) (a, c) (a, c)
forall b c d.
MSF (ClockInfo m) b c -> MSF (ClockInfo m) (d, b) (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second MSF (ClockInfo m) c c
forall (m :: * -> *) s a.
(Monad m, Fractional s, VectorSpace a s) =>
SF m a a
integral MSF (ClockInfo m) (a, c) (a, c)
-> SF m (a, c) (b, c) -> SF m (a, c) (b, c)
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> SF m (a, c) (b, c)
sf)