{- |
Combinators for composing signal networks sequentially and parallely.
-}

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
module FRP.Rhine.SN.Combinators where


-- rhine
import FRP.Rhine.ClSF.Core
import FRP.Rhine.Clock.Proxy
import FRP.Rhine.ResamplingBuffer.Util
import FRP.Rhine.Schedule
import FRP.Rhine.SN


-- | Postcompose a signal network with a pure function.
(>>>^)
  :: Monad m
  => SN m cl a b
  ->          (b -> c)
  -> SN m cl a      c
Synchronous ClSF m cl a b
clsf      >>>^ :: SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ b -> c
f = ClSF m cl a c -> SN m cl a c
forall cl (m :: Type -> Type) a b.
(cl ~ In cl, cl ~ Out cl) =>
ClSF m cl a b -> SN m cl a b
Synchronous (ClSF m cl a c -> SN m cl a c) -> ClSF m cl a c -> SN m cl a c
forall a b. (a -> b) -> a -> b
$ ClSF m cl a b
clsf ClSF m cl a b -> (b -> c) -> ClSF m cl a c
forall (a :: Type -> Type -> Type) b c d.
Arrow a =>
a b c -> (c -> d) -> a b d
>>^ b -> c
f
Sequential SN m clab a b
sn1 ResamplingBuffer m (Out clab) (In clcd) b c
rb SN m clcd c b
sn2 >>>^ b -> c
f = SN m clab a b
-> ResamplingBuffer m (Out clab) (In clcd) b c
-> SN m clcd c c
-> SN m (SequentialClock m clab clcd) a c
forall (m :: Type -> Type) clab clcd a b cl1 d.
(Clock m clab, Clock m clcd, Clock m (Out clab),
 Clock m (Out clcd), Clock m (In clab), Clock m (In clcd),
 GetClockProxy clab, GetClockProxy clcd, Time clab ~ Time clcd,
 Time clab ~ Time (Out clab), Time clcd ~ Time (In clcd)) =>
SN m clab a b
-> ResamplingBuffer m (Out clab) (In clcd) b cl1
-> SN m clcd cl1 d
-> SN m (SequentialClock m clab clcd) a d
Sequential SN m clab a b
sn1 ResamplingBuffer m (Out clab) (In clcd) b c
rb     (SN m clcd c c -> SN m (SequentialClock m clab clcd) a c)
-> SN m clcd c c -> SN m (SequentialClock m clab clcd) a c
forall a b. (a -> b) -> a -> b
$ SN m clcd c b
sn2 SN m clcd c b -> (b -> c) -> SN m clcd c c
forall (m :: Type -> Type) cl a b c.
Monad m =>
SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ b -> c
f
Parallel   SN m cl1 a b
sn1    SN m cl2 a b
sn2 >>>^ b -> c
f = SN m cl1 a c -> SN m cl2 a c -> SN m (ParallelClock m cl1 cl2) a c
forall (m :: Type -> Type) cl1 cl2 a b.
(Clock m cl1, Clock m cl2, Clock m (Out cl1), Clock m (Out cl2),
 GetClockProxy cl1, GetClockProxy cl2, Time cl1 ~ Time (Out cl1),
 Time cl2 ~ Time (Out cl2), Time cl1 ~ Time cl2,
 Time cl1 ~ Time (In cl1), Time cl2 ~ Time (In cl2)) =>
SN m cl1 a b -> SN m cl2 a b -> SN m (ParallelClock m cl1 cl2) a b
Parallel  (SN m cl1 a b
sn1 SN m cl1 a b -> (b -> c) -> SN m cl1 a c
forall (m :: Type -> Type) cl a b c.
Monad m =>
SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ b -> c
f) (SN m cl2 a b
sn2 SN m cl2 a b -> (b -> c) -> SN m cl2 a c
forall (m :: Type -> Type) cl a b c.
Monad m =>
SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ b -> c
f)


-- | Precompose a signal network with a pure function.
(^>>>)
  :: Monad m
  =>        (a -> b)
  -> SN m cl      b c
  -> SN m cl a      c
a -> b
f ^>>> :: (a -> b) -> SN m cl b c -> SN m cl a c
^>>> Synchronous ClSF m cl b c
clsf      = ClSF m cl a c -> SN m cl a c
forall cl (m :: Type -> Type) a b.
(cl ~ In cl, cl ~ Out cl) =>
ClSF m cl a b -> SN m cl a b
Synchronous (ClSF m cl a c -> SN m cl a c) -> ClSF m cl a c -> SN m cl a c
forall a b. (a -> b) -> a -> b
$ a -> b
f (a -> b) -> ClSF m cl b c -> ClSF m cl a c
forall (a :: Type -> Type -> Type) b c d.
Arrow a =>
(b -> c) -> a c d -> a b d
^>> ClSF m cl b c
clsf
a -> b
f ^>>> Sequential SN m clab b b
sn1 ResamplingBuffer m (Out clab) (In clcd) b c
rb SN m clcd c c
sn2 = SN m clab a b
-> ResamplingBuffer m (Out clab) (In clcd) b c
-> SN m clcd c c
-> SN m (SequentialClock m clab clcd) a c
forall (m :: Type -> Type) clab clcd a b cl1 d.
(Clock m clab, Clock m clcd, Clock m (Out clab),
 Clock m (Out clcd), Clock m (In clab), Clock m (In clcd),
 GetClockProxy clab, GetClockProxy clcd, Time clab ~ Time clcd,
 Time clab ~ Time (Out clab), Time clcd ~ Time (In clcd)) =>
SN m clab a b
-> ResamplingBuffer m (Out clab) (In clcd) b cl1
-> SN m clcd cl1 d
-> SN m (SequentialClock m clab clcd) a d
Sequential (a -> b
f (a -> b) -> SN m clab b b -> SN m clab a b
forall (m :: Type -> Type) a b cl c.
Monad m =>
(a -> b) -> SN m cl b c -> SN m cl a c
^>>> SN m clab b b
sn1) ResamplingBuffer m (Out clab) (In clcd) b c
rb      SN m clcd c c
sn2
a -> b
f ^>>> Parallel   SN m cl1 b c
sn1    SN m cl2 b c
sn2 = SN m cl1 a c -> SN m cl2 a c -> SN m (ParallelClock m cl1 cl2) a c
forall (m :: Type -> Type) cl1 cl2 a b.
(Clock m cl1, Clock m cl2, Clock m (Out cl1), Clock m (Out cl2),
 GetClockProxy cl1, GetClockProxy cl2, Time cl1 ~ Time (Out cl1),
 Time cl2 ~ Time (Out cl2), Time cl1 ~ Time cl2,
 Time cl1 ~ Time (In cl1), Time cl2 ~ Time (In cl2)) =>
SN m cl1 a b -> SN m cl2 a b -> SN m (ParallelClock m cl1 cl2) a b
Parallel   (a -> b
f (a -> b) -> SN m cl1 b c -> SN m cl1 a c
forall (m :: Type -> Type) a b cl c.
Monad m =>
(a -> b) -> SN m cl b c -> SN m cl a c
^>>> SN m cl1 b c
sn1) (a -> b
f (a -> b) -> SN m cl2 b c -> SN m cl2 a c
forall (m :: Type -> Type) a b cl c.
Monad m =>
(a -> b) -> SN m cl b c -> SN m cl a c
^>>> SN m cl2 b c
sn2)


-- | Compose two signal networks on the same clock in data-parallel.
--   At one tick of @cl@, both networks are stepped.
(****)
  :: Monad m
  => SN m cl  a      b
  -> SN m cl     c      d
  -> SN m cl (a, c) (b, d)
Synchronous ClSF m cl a b
clsf1 **** :: SN m cl a b -> SN m cl c d -> SN m cl (a, c) (b, d)
**** Synchronous ClSF m cl c d
clsf2 = ClSF m cl (a, c) (b, d) -> SN m cl (a, c) (b, d)
forall cl (m :: Type -> Type) a b.
(cl ~ In cl, cl ~ Out cl) =>
ClSF m cl a b -> SN m cl a b
Synchronous (ClSF m cl (a, c) (b, d) -> SN m cl (a, c) (b, d))
-> ClSF m cl (a, c) (b, d) -> SN m cl (a, c) (b, d)
forall a b. (a -> b) -> a -> b
$ ClSF m cl a b
clsf1 ClSF m cl a b -> ClSF m cl c d -> ClSF m cl (a, c) (b, d)
forall (a :: Type -> Type -> Type) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** ClSF m cl c d
clsf2
Sequential SN m clab a b
sn11 ResamplingBuffer m (Out clab) (In clcd) b c
rb1 SN m clcd c b
sn12 **** Sequential SN m clab c b
sn21 ResamplingBuffer m (Out clab) (In clcd) b c
rb2 SN m clcd c d
sn22 = SN m clab (a, c) (b, b)
-> ResamplingBuffer m (Out clab) (In clcd) (b, b) (c, c)
-> SN m clcd (c, c) (b, d)
-> SN m (SequentialClock m clab clcd) (a, c) (b, d)
forall (m :: Type -> Type) clab clcd a b cl1 d.
(Clock m clab, Clock m clcd, Clock m (Out clab),
 Clock m (Out clcd), Clock m (In clab), Clock m (In clcd),
 GetClockProxy clab, GetClockProxy clcd, Time clab ~ Time clcd,
 Time clab ~ Time (Out clab), Time clcd ~ Time (In clcd)) =>
SN m clab a b
-> ResamplingBuffer m (Out clab) (In clcd) b cl1
-> SN m clcd cl1 d
-> SN m (SequentialClock m clab clcd) a d
Sequential SN m clab (a, c) (b, b)
sn1 ResamplingBuffer m (Out clab) (In clcd) (b, b) (c, c)
rb SN m clcd (c, c) (b, d)
sn2
  where
    sn1 :: SN m clab (a, c) (b, b)
sn1 = SN m clab a b
sn11 SN m clab a b -> SN m clab c b -> SN m clab (a, c) (b, b)
forall (m :: Type -> Type) cl a b c d.
Monad m =>
SN m cl a b -> SN m cl c d -> SN m cl (a, c) (b, d)
**** SN m clab c b
SN m clab c b
sn21
    sn2 :: SN m clcd (c, c) (b, d)
sn2 = SN m clcd c b
sn12 SN m clcd c b -> SN m clcd c d -> SN m clcd (c, c) (b, d)
forall (m :: Type -> Type) cl a b c d.
Monad m =>
SN m cl a b -> SN m cl c d -> SN m cl (a, c) (b, d)
**** SN m clcd c d
SN m clcd c d
sn22
    rb :: ResamplingBuffer m (Out clab) (In clcd) (b, b) (c, c)
rb  = ResamplingBuffer m (Out clab) (In clcd) b c
rb1 ResamplingBuffer m (Out clab) (In clcd) b c
-> ResamplingBuffer m (Out clab) (In clcd) b c
-> ResamplingBuffer m (Out clab) (In clcd) (b, b) (c, c)
forall (m :: Type -> Type) cl1 cl2 a b c d.
Monad m =>
ResamplingBuffer m cl1 cl2 a b
-> ResamplingBuffer m cl1 cl2 c d
-> ResamplingBuffer m cl1 cl2 (a, c) (b, d)
*-* ResamplingBuffer m (Out clab) (In clcd) b c
ResamplingBuffer m (Out clab) (In clcd) b c
rb2
Parallel SN m cl1 a b
sn11 SN m cl2 a b
sn12 **** Parallel SN m cl1 c d
sn21 SN m cl2 c d
sn22
  = SN m cl1 (a, c) (b, d)
-> SN m cl2 (a, c) (b, d)
-> SN m (ParallelClock m cl1 cl2) (a, c) (b, d)
forall (m :: Type -> Type) cl1 cl2 a b.
(Clock m cl1, Clock m cl2, Clock m (Out cl1), Clock m (Out cl2),
 GetClockProxy cl1, GetClockProxy cl2, Time cl1 ~ Time (Out cl1),
 Time cl2 ~ Time (Out cl2), Time cl1 ~ Time cl2,
 Time cl1 ~ Time (In cl1), Time cl2 ~ Time (In cl2)) =>
SN m cl1 a b -> SN m cl2 a b -> SN m (ParallelClock m cl1 cl2) a b
Parallel (SN m cl1 a b
sn11 SN m cl1 a b -> SN m cl1 c d -> SN m cl1 (a, c) (b, d)
forall (m :: Type -> Type) cl a b c d.
Monad m =>
SN m cl a b -> SN m cl c d -> SN m cl (a, c) (b, d)
**** SN m cl1 c d
SN m cl1 c d
sn21) (SN m cl2 a b
sn12 SN m cl2 a b -> SN m cl2 c d -> SN m cl2 (a, c) (b, d)
forall (m :: Type -> Type) cl a b c d.
Monad m =>
SN m cl a b -> SN m cl c d -> SN m cl (a, c) (b, d)
**** SN m cl2 c d
SN m cl2 c d
sn22)
-- Note that the patterns above are the only ones that can occur.
-- This is ensured by the clock constraints in the SF constructors.
SN m cl a b
_ **** SN m cl c d
_ = [Char] -> SN m cl (a, c) (b, d)
forall a. HasCallStack => [Char] -> a
error [Char]
"Impossible pattern in ****"

-- | Compose two signal networks on different clocks in clock-parallel.
--   At one tick of @ParClock m cl1 cl2@, one of the networks is stepped,
--   dependent on which constituent clock has ticked.
--
--   Note: This is essentially an infix synonym of 'Parallel'
(||||)
  :: ( Monad m, Clock m clL, Clock m clR
     , Clock m (Out clL), Clock m (Out clR)
     , GetClockProxy clL, GetClockProxy clR
     , Time clL ~ Time clR
     , Time clL ~ Time (Out clL), Time clL ~ Time (In clL)
     , Time clR ~ Time (Out clR), Time clR ~ Time (In clR)
     )
  => SN m             clL      a b
  -> SN m                 clR  a b
  -> SN m (ParClock m clL clR) a b
|||| :: SN m clL a b -> SN m clR a b -> SN m (ParClock m clL clR) a b
(||||) = SN m clL a b -> SN m clR a b -> SN m (ParClock m clL clR) a b
forall (m :: Type -> Type) cl1 cl2 a b.
(Clock m cl1, Clock m cl2, Clock m (Out cl1), Clock m (Out cl2),
 GetClockProxy cl1, GetClockProxy cl2, Time cl1 ~ Time (Out cl1),
 Time cl2 ~ Time (Out cl2), Time cl1 ~ Time cl2,
 Time cl1 ~ Time (In cl1), Time cl2 ~ Time (In cl2)) =>
SN m cl1 a b -> SN m cl2 a b -> SN m (ParallelClock m cl1 cl2) a b
Parallel

-- | Compose two signal networks on different clocks in clock-parallel.
--   At one tick of @ParClock m cl1 cl2@, one of the networks is stepped,
--   dependent on which constituent clock has ticked.
(++++)
  :: ( Monad m, Clock m clL, Clock m clR
     , Clock m (Out clL), Clock m (Out clR)
     , GetClockProxy clL, GetClockProxy clR
     , Time clL ~ Time clR
     , Time clL ~ Time (Out clL), Time clL ~ Time (In clL)
     , Time clR ~ Time (Out clR), Time clR ~ Time (In clR)
     )
  => SN m             clL      a         b
  -> SN m                 clR  a           c
  -> SN m (ParClock m clL clR) a (Either b c)
SN m clL a b
snL ++++ :: SN m clL a b
-> SN m clR a c -> SN m (ParClock m clL clR) a (Either b c)
++++ SN m clR a c
snR = (SN m clL a b
snL SN m clL a b -> (b -> Either b c) -> SN m clL a (Either b c)
forall (m :: Type -> Type) cl a b c.
Monad m =>
SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ b -> Either b c
forall a b. a -> Either a b
Left) SN m clL a (Either b c)
-> SN m clR a (Either b c)
-> SN m (ParClock m clL clR) a (Either b c)
forall (m :: Type -> Type) clL clR a b.
(Monad m, Clock m clL, Clock m clR, Clock m (Out clL),
 Clock m (Out clR), GetClockProxy clL, GetClockProxy clR,
 Time clL ~ Time clR, Time clL ~ Time (Out clL),
 Time clL ~ Time (In clL), Time clR ~ Time (Out clR),
 Time clR ~ Time (In clR)) =>
SN m clL a b -> SN m clR a b -> SN m (ParClock m clL clR) a b
|||| (SN m clR a c
snR SN m clR a c -> (c -> Either b c) -> SN m clR a (Either b c)
forall (m :: Type -> Type) cl a b c.
Monad m =>
SN m cl a b -> (b -> c) -> SN m cl a c
>>>^ c -> Either b c
forall a b. b -> Either a b
Right)