packages feed

rhine 0.8.0.1 → 0.8.1

raw patch · 13 files changed

+116/−26 lines, 13 filesdep ~basedep ~simple-affine-spacePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, simple-affine-space

API changes (from Hackage documentation)

- FRP.Rhine.Clock.Periodic: instance (GHC.Base.Monad m, FRP.Rhine.Clock.Periodic.NonemptyNatList v) => FRP.Rhine.Clock.Clock (Control.Monad.Schedule.ScheduleT GHC.Integer.Type.Integer m) (FRP.Rhine.Clock.Periodic.Periodic v)
- FRP.Rhine.Clock.Proxy: type family Cl a :: Type;
+ FRP.Rhine: [Feedback] :: (Clock m (In cl), Clock m (Out cl), Time (In cl) ~ Time cl, Time (Out cl) ~ Time cl) => ResBuf m (Out cl) (In cl) d c -> SN m cl (a, c) (b, d) -> SN m cl a b
+ FRP.Rhine: [FirstResampling] :: (Clock m (In cl), Clock m (Out cl), Time cl ~ Time (Out cl), Time cl ~ Time (In cl)) => SN m cl a b -> ResamplingBuffer m (In cl) (Out cl) c d -> SN m cl (a, c) (b, d)
+ FRP.Rhine: add :: TimeDifference d => d -> d -> d
+ FRP.Rhine: addTime :: TimeDomain time => time -> Diff time -> time
+ FRP.Rhine: feedbackRhine :: (Clock m (In cl), Clock m (Out cl), Time (In cl) ~ Time cl, Time (Out cl) ~ Time cl) => ResamplingBuffer m (Out cl) (In cl) d c -> Rhine m cl (a, c) (b, d) -> Rhine m cl a b
+ FRP.Rhine: type Cl a :: Type;
+ FRP.Rhine: type Tag cl;
+ FRP.Rhine: type Time cl;
+ FRP.Rhine.ClSF.Core: add :: TimeDifference d => d -> d -> d
+ FRP.Rhine.ClSF.Core: addTime :: TimeDomain time => time -> Diff time -> time
+ FRP.Rhine.ClSF.Core: type Tag cl;
+ FRP.Rhine.ClSF.Core: type Time cl;
+ FRP.Rhine.Clock: add :: TimeDifference d => d -> d -> d
+ FRP.Rhine.Clock: addTime :: TimeDomain time => time -> Diff time -> time
+ FRP.Rhine.Clock: type Tag cl;
+ FRP.Rhine.Clock: type Time cl;
+ FRP.Rhine.Clock.Periodic: instance (GHC.Base.Monad m, FRP.Rhine.Clock.Periodic.NonemptyNatList v) => FRP.Rhine.Clock.Clock (Control.Monad.Schedule.ScheduleT GHC.Num.Integer.Integer m) (FRP.Rhine.Clock.Periodic.Periodic v)
+ FRP.Rhine.Clock.Proxy: type Cl a :: Type;
+ FRP.Rhine.SN: [Feedback] :: (Clock m (In cl), Clock m (Out cl), Time (In cl) ~ Time cl, Time (Out cl) ~ Time cl) => ResBuf m (Out cl) (In cl) d c -> SN m cl (a, c) (b, d) -> SN m cl a b
+ FRP.Rhine.SN: [FirstResampling] :: (Clock m (In cl), Clock m (Out cl), Time cl ~ Time (Out cl), Time cl ~ Time (In cl)) => SN m cl a b -> ResamplingBuffer m (In cl) (Out cl) c d -> SN m cl (a, c) (b, d)
+ FRP.Rhine.Type: feedbackRhine :: (Clock m (In cl), Clock m (Out cl), Time (In cl) ~ Time cl, Time (Out cl) ~ Time cl) => ResamplingBuffer m (Out cl) (In cl) d c -> Rhine m cl (a, c) (b, d) -> Rhine m cl a b
- FRP.Rhine: (<<<) :: forall k cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
+ FRP.Rhine: (<<<) :: forall {k} cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
- FRP.Rhine: (>>>) :: forall k cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
+ FRP.Rhine: (>>>) :: forall {k} cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
- FRP.Rhine: class Category a => Arrow (a :: Type -> Type -> Type)
+ FRP.Rhine: class Category a => Arrow (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: class Arrow a => ArrowApply (a :: Type -> Type -> Type)
+ FRP.Rhine: class Arrow a => ArrowApply (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: class Arrow a => ArrowChoice (a :: Type -> Type -> Type)
+ FRP.Rhine: class Arrow a => ArrowChoice (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: class Arrow a => ArrowLoop (a :: Type -> Type -> Type)
+ FRP.Rhine: class Arrow a => ArrowLoop (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: class ArrowZero a => ArrowPlus (a :: Type -> Type -> Type)
+ FRP.Rhine: class ArrowZero a => ArrowPlus (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: class Arrow a => ArrowZero (a :: Type -> Type -> Type)
+ FRP.Rhine: class Arrow a => ArrowZero (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine: type family Cl a :: Type;
+ FRP.Rhine: type family In cl
- FRP.Rhine.ClSF.Core: (<<<) :: forall k cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
+ FRP.Rhine.ClSF.Core: (<<<) :: forall {k} cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
- FRP.Rhine.ClSF.Core: (>>>) :: forall k cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
+ FRP.Rhine.ClSF.Core: (>>>) :: forall {k} cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
- FRP.Rhine.ClSF.Core: class Category a => Arrow (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class Category a => Arrow (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: class Arrow a => ArrowApply (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class Arrow a => ArrowApply (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: class Arrow a => ArrowChoice (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class Arrow a => ArrowChoice (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: class Arrow a => ArrowLoop (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class Arrow a => ArrowLoop (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: class ArrowZero a => ArrowPlus (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class ArrowZero a => ArrowPlus (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: class Arrow a => ArrowZero (a :: Type -> Type -> Type)
+ FRP.Rhine.ClSF.Core: class Arrow a => ArrowZero (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.ClSF.Core: type family Tag cl;
+ FRP.Rhine.ClSF.Core: type family Diff time;
- FRP.Rhine.Clock: (<<<) :: forall k cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
+ FRP.Rhine.Clock: (<<<) :: forall {k} cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
- FRP.Rhine.Clock: (>>>) :: forall k cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
+ FRP.Rhine.Clock: (>>>) :: forall {k} cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
- FRP.Rhine.Clock: class Category a => Arrow (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class Category a => Arrow (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.Clock: class Arrow a => ArrowApply (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class Arrow a => ArrowApply (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.Clock: class Arrow a => ArrowChoice (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class Arrow a => ArrowChoice (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.Clock: class Arrow a => ArrowLoop (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class Arrow a => ArrowLoop (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.Clock: class ArrowZero a => ArrowPlus (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class ArrowZero a => ArrowPlus (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)
- FRP.Rhine.Clock: class Arrow a => ArrowZero (a :: Type -> Type -> Type)
+ FRP.Rhine.Clock: class Arrow a => ArrowZero (a :: TYPE LiftedRep -> TYPE LiftedRep -> Type)

Files

ChangeLog.md view
@@ -4,6 +4,11 @@ Since `rhine` reexports modules from `dunai`, every major version in `dunai` triggers a major version in `rhine`. +## 0.8.1++* Support for GHC 9.2.4+* Added `FirstResampling` and `Feedback` constructors to `SN`+ ## 0.8.0.0  * Documentation improvements
rhine.cabal view
@@ -1,6 +1,6 @@ name:                rhine -version:             0.8.0.1+version:             0.8.1  synopsis: Functional Reactive Programming with type-level clocks @@ -41,12 +41,12 @@  source-repository head   type:     git-  location: git@github.com:turion/rhine.git+  location: https://github.com/turion/rhine.git  source-repository this   type:     git-  location: git@github.com:turion/rhine.git-  tag:      v0.8.0.1+  location: https://github.com/turion/rhine.git+  tag:      v0.8.1   library@@ -99,7 +99,7 @@   -- other-extensions:    -- Other library packages from which modules are imported.-  build-depends:       base         >= 4.13 && < 4.16+  build-depends:       base         >= 4.13 && < 4.17                      , dunai        >= 0.8                      , transformers >= 0.5                      , time         >= 1.8@@ -109,7 +109,8 @@                      , deepseq      >= 1.4                      , random       >= 1.1                      , MonadRandom  >= 0.5-                     , simple-affine-space+                     -- Remove version pin when https://github.com/ivanperez-keera/dunai/issues/298 is resolved:+                     , simple-affine-space == 0.1.1                      , time-domain    -- Directories containing source files.
src/FRP/Rhine/Clock.hs view
@@ -7,7 +7,6 @@ and certain general constructions of 'Clock's, such as clocks lifted along monad morphisms or time rescalings. -}-{-# LANGUAGE Arrows #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}
src/FRP/Rhine/Clock/Periodic.hs view
@@ -8,12 +8,10 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-} module FRP.Rhine.Clock.Periodic (Periodic (Periodic)) where  -- base@@ -45,7 +43,7 @@   type Time (Periodic v) = Integer   type Tag  (Periodic v) = ()   initClock cl = return-    ( cycleS (theList cl) >>> withSideEffect wait >>> (accumulateWith (+) 0) &&& arr (const ())+    ( cycleS (theList cl) >>> withSideEffect wait >>> accumulateWith (+) 0 &&& arr (const ())     , 0     ) 
src/FRP/Rhine/Clock/Realtime/Audio.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE Arrows #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} 
src/FRP/Rhine/Clock/Realtime/Event.hs view
@@ -22,7 +22,6 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-} module FRP.Rhine.Clock.Realtime.Event   ( module FRP.Rhine.Clock.Realtime.Event   , module Control.Monad.IO.Class@@ -74,7 +73,7 @@ -} runEventChanT :: MonadIO m => EventChanT event m a -> m a runEventChanT a = do-  chan <- liftIO $ newChan+  chan <- liftIO newChan   runReaderT a chan  {- | Remove ("run") an 'EventChanT' layer from the monad stack@@ -156,7 +155,7 @@       ( constM $ do           chan  <- ask           event <- liftIO $ readChan chan-          time  <- liftIO $ getCurrentTime+          time  <- liftIO getCurrentTime           return (time, event)       , initialTime       )
src/FRP/Rhine/Clock/Realtime/Millisecond.hs view
@@ -2,9 +2,7 @@ Provides a clock that ticks at every multiple of a fixed number of milliseconds. -} -{-# LANGUAGE Arrows #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}@@ -56,12 +54,12 @@  --   Note that this clock internally uses 'threadDelay' which can block --   for quite a lot longer than the requested time, which can cause---   the clock to miss one or more ticks when using low values of 'n'. ---   When using 'threadDelay', the difference between the real wait time ---   and the requested wait time will be larger when using +--   the clock to miss one or more ticks when using low values of 'n'.+--   When using 'threadDelay', the difference between the real wait time+--   and the requested wait time will be larger when using --   the '-threaded' ghc option (around 800 microseconds) than when not using --   this option (around 100 microseconds). For low values of @n@ it is recommended---   that '-threaded' not be used in order to miss less ticks. The clock will adjust +--   that '-threaded' not be used in order to miss less ticks. The clock will adjust --   the wait time, up to no wait time at all, to catch up when a tick is missed.  waitClock :: KnownNat n => Millisecond n
src/FRP/Rhine/Reactimation.hs view
@@ -3,9 +3,7 @@ as main loops. -} -{-# LANGUAGE Arrows #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE RecordWildCards #-} module FRP.Rhine.Reactimation where  -- dunai
src/FRP/Rhine/Reactimation/ClockErasure.hs view
@@ -7,7 +7,6 @@ {-# LANGUAGE Arrows #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TupleSections #-} module FRP.Rhine.Reactimation.ClockErasure where @@ -71,7 +70,7 @@       maybeB <- eraseClockSN initialTime sn1 -< (time, tagL, maybeA)       returnA -< Left <$> ((time, , ) <$> outTag proxy1 tagL <*> maybeB)     Right tagR -> do-      returnA -< Right <$> (time, ) <$> inTag proxy2 tagR+      returnA -< Right . (time, ) <$> inTag proxy2 tagR   maybeC <- mapMaybeS $ eraseClockResBuf (outProxy proxy1) (inProxy proxy2) initialTime resBuf -< resBufIn   case tag of     Left  _    -> do@@ -97,6 +96,39 @@   in proc (time, tag, aMaybe) -> do   bMaybe <- mapMaybeS $ eraseClockClSF (inProxy proxy) initialTime clsf -< (time, , ) <$> inTag proxy tag <*> aMaybe   eraseClockSN initialTime sn -< (time, tag, bMaybe)++eraseClockSN initialTime (Feedback buf0 sn) =+  let+    proxy = toClockProxy sn+  in feedback buf0 $ proc ((time, tag, aMaybe), buf) -> do+  (cMaybe, buf') <- case inTag proxy tag of+    Nothing -> do+      returnA -< (Nothing, buf)+    Just tagIn -> do+      timeInfo <- genTimeInfo (inProxy proxy) initialTime -< (time, tagIn)+      (c, buf') <- arrM $ uncurry get -< (buf, timeInfo)+      returnA -< (Just c, buf')+  bdMaybe <- eraseClockSN initialTime sn -< (time, tag, (, ) <$> aMaybe <*> cMaybe)+  case (, ) <$> outTag proxy tag <*> bdMaybe of+    Nothing -> do+      returnA -< (Nothing, buf')+    Just (tagOut, (b, d)) -> do+      timeInfo <- genTimeInfo (outProxy proxy) initialTime -< (time, tagOut)+      buf'' <- arrM $ uncurry $ uncurry put -< ((buf', timeInfo), d)+      returnA -< (Just b, buf'')++eraseClockSN initialTime (FirstResampling sn buf) =+  let+    proxy = toClockProxy sn+  in proc (time, tag, acMaybe) -> do+    bMaybe <- eraseClockSN initialTime sn -< (time, tag, fst <$> acMaybe)+    let+      resBufInput = case (inTag proxy tag, outTag proxy tag, snd <$> acMaybe) of+        (Just tagIn, _, Just c) -> Just $ Left (time, tagIn, c)+        (_, Just tagOut, _) -> Just $ Right (time, tagOut)+        _ -> Nothing+    dMaybe <- mapMaybeS $ eraseClockResBuf (inProxy proxy) (outProxy proxy) initialTime buf -< resBufInput+    returnA -< (,) <$> bMaybe <*> join dMaybe  -- | Translate a resampling buffer into a monadic stream function. --
src/FRP/Rhine/SN.hs view
@@ -69,6 +69,15 @@     => SN m                  cl1      a b     -> SN m                      cl2  a b     -> SN m (ParallelClock m cl1 cl2) a b+  -- | Bypass the signal network by forwarding data in parallel through a 'ResamplingBuffer'.+  FirstResampling+    :: ( Clock m (In cl), Clock m (Out cl)+       , Time cl ~ Time (Out cl)+       , Time cl ~ Time (In cl)+       )+    => SN               m cl               a      b+    -> ResamplingBuffer m (In cl) (Out cl)    c      d+    -> SN               m cl              (a, c) (b, d)   -- | A 'ClSF' can always be postcomposed onto an 'SN' if the clocks match on the output.   Postcompose     :: ( Clock m (Out cl)@@ -85,6 +94,16 @@     => ClSF m (In cl) a b     -> SN   m     cl    b c     -> SN   m     cl  a   c+  -- | Data can be looped back to the beginning of an 'SN',+  --   but it must be resampled since the 'Out' and 'In' clocks are generally different.+  Feedback+    :: ( Clock m (In cl),  Clock m (Out cl)+       , Time (In cl) ~ Time cl+       , Time (Out cl) ~ Time cl+       )+    => ResBuf m (Out cl) (In cl) d c+    -> SN     m cl (a, c) (b, d)+    -> SN     m cl  a      b  instance GetClockProxy cl => ToClockProxy (SN m cl a b) where   type Cl (SN m cl a b) = cl
src/FRP/Rhine/SN/Combinators.hs view
@@ -26,6 +26,8 @@ Parallel   sn1    sn2 >>>^ f = Parallel  (sn1 >>>^ f) (sn2 >>>^ f) Postcompose sn clsf >>>^ f = Postcompose sn $ clsf >>^ f Precompose clsf sn >>>^ f = Precompose clsf $ sn >>>^ f+Feedback buf sn >>>^ f = Feedback buf $ sn >>>^ first f+firstResampling@(FirstResampling _ _) >>>^ f = Postcompose firstResampling $ arr f  -- | Precompose a signal network with a pure function. (^>>>)@@ -38,6 +40,8 @@ f ^>>> Parallel   sn1    sn2 = Parallel   (f ^>>> sn1) (f ^>>> sn2) f ^>>> Postcompose sn clsf = Postcompose (f ^>>> sn) clsf f ^>>> Precompose clsf sn = Precompose (f ^>> clsf) sn+f ^>>> Feedback buf sn = Feedback buf $ first f ^>>> sn+f ^>>> firstResampling@(FirstResampling _ _) = Precompose (arr f) firstResampling  -- | Postcompose a signal network with a 'ClSF'. (>--^)@@ -74,9 +78,24 @@     rb  = rb1 *-* rb2 Parallel sn11 sn12 **** Parallel sn21 sn22   = Parallel (sn11 **** sn21) (sn12 **** sn22)++Precompose clsf sn1 **** sn2 = Precompose (first clsf) $ sn1 **** sn2+sn1 **** Precompose clsf sn2 = Precompose (second clsf) $ sn1 **** sn2+Postcompose sn1 clsf **** sn2 = Postcompose (sn1 **** sn2) (first clsf)+sn1 **** Postcompose sn2 clsf = Postcompose (sn1 **** sn2) (second clsf)++Feedback buf sn1 **** sn2 = Feedback buf $ (\((a, c), c1) -> ((a, c1), c)) ^>>> (sn1 **** sn2) >>>^ (\((b, d1), d) -> ((b, d), d1))+sn1 **** Feedback buf sn2 = Feedback buf $ (\((a, c), c1) -> (a, (c, c1))) ^>>> (sn1 **** sn2) >>>^ (\(b, (d, d1)) -> ((b, d), d1))++FirstResampling sn1 buf **** sn2 = (\((a1, c1), c) -> ((a1, c), c1)) ^>>> FirstResampling (sn1 **** sn2) buf >>>^ (\((b1, d), d1) -> ((b1, d1), d))+sn1 **** FirstResampling sn2 buf = (\(a, (a1, c1)) -> ((a, a1), c1)) ^>>> FirstResampling (sn1 **** sn2) buf >>>^ (\((b, b1), d1) -> (b, (b1, d1)))+ -- Note that the patterns above are the only ones that can occur. -- This is ensured by the clock constraints in the SF constructors.-_ **** _ = error "Impossible pattern in ****"+Synchronous _ **** Parallel _ _ = error "Impossible pattern: Synchronous _ **** Parallel _ _"+Parallel _ _ **** Synchronous _ = error "Impossible pattern: Parallel _ _ **** Synchronous _"+Synchronous _ **** Sequential {} = error "Impossible pattern: Synchronous _ **** Sequential {}"+Sequential {} **** Synchronous _ = error "Impossible pattern: Sequential {} **** Synchronous _"  -- | Compose two signal networks on different clocks in clock-parallel. --   At one tick of @ParClock m cl1 cl2@, one of the networks is stepped,
src/FRP/Rhine/Schedule.hs view
@@ -81,7 +81,7 @@   :: Monad m   => Schedule m cl1 cl2   -> Schedule m (RescaledClock cl1 time) (RescaledClock cl2 time)-rescaledSchedule schedule = Schedule $ initSchedule'+rescaledSchedule schedule = Schedule initSchedule'   where     initSchedule' cl1 cl2 = initSchedule (rescaledScheduleS schedule) (rescaledClockToS cl1) (rescaledClockToS cl2) 
src/FRP/Rhine/Type.hs view
@@ -6,6 +6,8 @@ {-# LANGUAGE Arrows #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE FlexibleContexts #-} module FRP.Rhine.Type where  -- dunai@@ -16,6 +18,8 @@ import FRP.Rhine.Clock import FRP.Rhine.Clock.Proxy import FRP.Rhine.SN+import FRP.Rhine.ResamplingBuffer (ResamplingBuffer)+import FRP.Rhine.Schedule (Out, In)  {- | A 'Rhine' consists of a 'SN' together with a clock of matching type 'cl'.@@ -55,3 +59,22 @@   return $ proc a -> do     (time, tag) <- runningClock -< ()     eraseClockSN initTime sn -< (time, tag, a <$ inTag (toClockProxy sn) tag)++{- |+Loop back data from the output to the input.++Since output and input will generally tick at different clocks,+the data needs to be resampled.+-}+feedbackRhine+  :: ( Clock m (In cl),  Clock m (Out cl)+     , Time (In cl) ~ Time cl+     , Time (Out cl) ~ Time cl+     )+  => ResamplingBuffer m (Out cl) (In cl) d c+  -> Rhine            m cl (a, c) (b, d)+  -> Rhine            m cl  a      b+feedbackRhine buf Rhine { .. } = Rhine+  { sn = Feedback buf sn+  , clock+  }