packages feed

rhine 0.1.1.0 → 0.2.0.0

raw patch · 9 files changed

+70/−108 lines, 9 filesdep ~basedep ~dunaiPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, dunai

API changes (from Hackage documentation)

- FRP.Rhine.Clock: instance (GHC.Base.Monad m1, GHC.Base.Monad m2, FRP.Rhine.Clock.Clock m1 a) => FRP.Rhine.Clock.Clock m2 (FRP.Rhine.Clock.HoistClock m1 m2 a)
- FRP.Rhine.Clock.Select: concatS :: Monad m => MStream m [b] -> MStream m b
- FRP.Rhine.Clock.Step: concatS :: Monad m => MSF m () [b] -> MSF m () b
- FRP.Rhine.SyncSF.Except: currentInput :: Monad m => SyncExcept m cl e b e
+ FRP.Rhine.Clock: instance (GHC.Base.Monad m1, GHC.Base.Monad m2, FRP.Rhine.Clock.Clock m1 cl) => FRP.Rhine.Clock.Clock m2 (FRP.Rhine.Clock.HoistClock m1 m2 cl)
+ FRP.Rhine.SyncSF: averageLin :: (Monad m, VectorSpace v, Groundfield v ~ Diff (TimeDomainOf cl)) => Diff (TimeDomainOf cl) -> SyncSF m cl v v
+ FRP.Rhine.SyncSF: averageLinFrom :: (Monad m, VectorSpace v, Groundfield v ~ Diff (TimeDomainOf cl)) => v -> Diff (TimeDomainOf cl) -> SyncSF m cl v v
+ FRP.Rhine.SyncSF: weightedAverageFrom :: (Monad m, VectorSpace v, Groundfield v ~ Diff (TimeDomainOf cl)) => v -> SyncSF m cl (v, Groundfield v) v
- FRP.Rhine.SyncSF: average :: (Monad m, VectorSpace v, Groundfield v ~ Diff (TimeDomainOf cl)) => Diff (TimeDomainOf cl) -> SyncSF m cl v v
+ FRP.Rhine.SyncSF: average :: (Monad m, VectorSpace v, Floating (Groundfield v), Groundfield v ~ Diff (TimeDomainOf cl)) => Diff (TimeDomainOf cl) -> SyncSF m cl v v
- FRP.Rhine.SyncSF: averageFrom :: (Monad m, VectorSpace v, Groundfield v ~ Diff (TimeDomainOf cl)) => v -> Diff (TimeDomainOf cl) -> SyncSF m cl v v
+ FRP.Rhine.SyncSF: averageFrom :: (Monad m, VectorSpace v, Floating (Groundfield v), Groundfield v ~ Diff (TimeDomainOf cl)) => v -> Diff (TimeDomainOf cl) -> SyncSF m cl v v

Files

README.md view
@@ -1,6 +1,8 @@ # README -------- +[![Build Status](https://travis-ci.org/turion/rhine.svg?branch=master)](https://travis-ci.org/turion/rhine)+ Rhine is a library for synchronous and asynchronous Functional Reactive Programming (FRP). It separates the aspects of clocking, scheduling and resampling from each other, and ensures clock-safety on the type level.
− examples/test/Test.hs
@@ -1,38 +0,0 @@-{-# LANGUAGE Arrows           #-}-{-# LANGUAGE DataKinds        #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies     #-}----- rhine-import FRP.Rhine-import FRP.Rhine.Clock.Realtime.Millisecond-import FRP.Rhine.Schedule.Concurrently---- | Calculates and prints the rounding errors that accumulate---   when calculating the time since the start of the simulation---   via an Euler integral.-showRoundingError-  :: Diff (TimeDomainOf cl) ~ Double-  => String -> SyncSF IO cl () ()-showRoundingError clName = proc () -> do-  correct   <- timeInfoOf sinceStart -< ()-  simulated <- arr_ 1 >>> integral   -< ()-  liftS putStrLn -<-    "Clock " ++ clName-    ++ " ticks at time "     ++ show correct-    ++ " and simulates "     ++ show simulated-    ++ " => rounding error " ++ show (correct - simulated)---- | Show the rounding error for the 1000 milliseconds clock.-showREMS1000 :: SyncSF IO (Millisecond 1000) () ()-showREMS1000 = showRoundingError "Millisecond 1000"---- | Show the rounding error for the 350 milliseconds clock.-showREMS350 :: SyncSF IO (Millisecond 350) () ()-showREMS350 = showRoundingError "Millisecond 350"---- | The main program runs both synchronous signal functions in parallel,---   using a concurrent (GHC threads) schedule.-main :: IO ()-main = flow $ showREMS350 @@ waitClock **@ concurrently @** showREMS1000 @@ waitClock
rhine.cabal view
@@ -1,6 +1,6 @@ name:                rhine -version:             0.1.1.0+version:             0.2.0.0  synopsis: Functional Reactive Programming with type-level clocks @@ -44,7 +44,7 @@ source-repository this   type:     git   location: git@github.com:turion/rhine.git-  tag:      v0.1.1.0+  tag:      v0.2.0.0   library@@ -84,7 +84,7 @@    -- Other library packages from which modules are imported.   build-depends:       base         >= 4.7   && < 5-                    ,  dunai        == 0.1.1.*+                    ,  dunai        == 0.2.0.*                     ,  transformers >= 0.4   && < 0.6                     ,  time         >= 1.6   && < 1.7                     ,  free         >= 4.12  && < 4.13@@ -98,19 +98,12 @@   -- Base language which the package is written in.   default-language:    Haskell2010 -executable test-  hs-source-dirs:      examples/test-  main-is:             Test.hs-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  build-depends:       base  >= 4.8     && <5-                     , rhine-  default-language:    Haskell2010  executable HelloWorld   hs-source-dirs:      examples   main-is:             HelloWorld.hs   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  build-depends:       base  >= 4.8     && <5+  build-depends:       base  >= 4.7     && <5                      , rhine   default-language:    Haskell2010 @@ -118,6 +111,6 @@   hs-source-dirs:      examples   main-is:             Demonstration.hs   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  build-depends:       base  >= 4.8     && <5+  build-depends:       base  >= 4.7     && <5                      , rhine   default-language:    Haskell2010
src/FRP/Rhine/Clock.hs view
@@ -130,8 +130,8 @@   , monadMorphism :: forall a . m1 a -> m2 a   } -instance (Monad m1, Monad m2, Clock m1 a)-      => Clock m2 (HoistClock m1 m2 a) where+instance (Monad m1, Monad m2, Clock m1 cl)+      => Clock m2 (HoistClock m1 m2 cl) where   type TimeDomainOf (HoistClock m1 m2 cl) = TimeDomainOf cl   type Tag          (HoistClock m1 m2 cl) = Tag          cl   startClock HoistClock {..} = do
src/FRP/Rhine/Clock/Realtime/Audio.hs view
@@ -22,14 +22,11 @@ import Data.Time.Clock  -- transformers--- TODO Delete as soon as dunai is updated-import Control.Monad.Trans.Class (lift) import Control.Monad.IO.Class   -- dunai import Control.Monad.Trans.MSF.Except-  hiding (once, once_) -- TODO Delete with dunai 0.1.2  -- rhine import FRP.Rhine@@ -155,11 +152,3 @@   { unscaledClock = PureAudioClock   , rescale       = double2Float }---- ** To be ported to @dunai@--once :: Monad m => (a -> m e) -> MSFExcept m a b e-once f = try $ arrM (lift . f) >>> throwS--- TODO Delete once dunai is updated-once_ :: Monad m => m e -> MSFExcept m a b e-once_ = once . const
src/FRP/Rhine/Clock/Select.hs view
@@ -10,8 +10,7 @@ import FRP.Rhine  -- dunai--- import Data.MonadicStreamFunction.Async (concatS)--- TODO dunai 0.1.2+import Data.MonadicStreamFunction.Async (concatS)  -- base import Data.Maybe (catMaybes, maybeToList)@@ -27,7 +26,7 @@   instance (Monad m, Clock m cl) => Clock m (SelectClock cl a) where-  type TimeDomainOf (SelectClock cl _) = TimeDomainOf cl+  type TimeDomainOf (SelectClock cl a) = TimeDomainOf cl   type Tag          (SelectClock cl a) = a   startClock SelectClock {..} = do     (runningClock, initialTime) <- startClock mainClock@@ -56,15 +55,8 @@             , (time, ) . Right <$> select subClock2 tag ]       return (runningSelectClocks, initialTime) --- ** To be ported to @dunai@ -concatS :: Monad m => MStream m [b] -> MStream m b-concatS msf = MSF $ \_ -> tick msf []-  where-    tick msf (b:bs) = return (b, MSF $ \_ -> tick msf bs)-    tick msf []     = do-      (bs, msf') <- unMSF msf ()-      tick msf' bs-+-- | Helper function that runs an 'MSF' with 'Maybe' output+--   until it returns a value. filterS :: Monad m => MSF m () (Maybe b) -> MSF m () b filterS = concatS . (>>> arr maybeToList)
src/FRP/Rhine/Clock/Step.hs view
@@ -11,6 +11,8 @@ -- base import GHC.TypeLits +-- dunai+import Data.MonadicStreamFunction.Async (concatS)  -- rhine import FRP.Rhine@@ -49,15 +51,3 @@         k <- arr (+1) <<< count -< ()         returnA                 -< [ (k, Left  ()) | k `mod` n1 == 0 ]                                 ++ [ (k, Right ()) | k `mod` n2 == 0 ]----- * To be ported to dunai---- TODO Will be in dunai-concatS :: Monad m => MSF m () [b] -> MSF m () b-concatS msf = MSF $ \_ -> tick msf []-  where-    tick msf (b:bs) = return (b, MSF $ \_ -> tick msf bs)-    tick msf []     = do-      (bs, msf') <- unMSF msf ()-      tick msf' bs
src/FRP/Rhine/SyncSF.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE Arrows          #-}-{-# LANGUAGE RankNTypes      #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeFamilies    #-}+{-# LANGUAGE Arrows           #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes       #-}+{-# LANGUAGE RecordWildCards  #-}+{-# LANGUAGE TypeFamilies     #-}  module FRP.Rhine.SyncSF where @@ -163,25 +164,69 @@   => SyncSF m cl v v derivative = derivativeFrom zeroVector +-- | A weighted moving average signal function.+--   The output is the average of the first input,+--   weighted by the second input+--   (which is assumed to be always between 0 and 1).+--   The weight is applied to the average of the last tick,+--   so a weight of 1 simply repeats the past value unchanged,+--   whereas a weight of 0 outputs the current value.+weightedAverageFrom+  :: ( Monad m, VectorSpace v+     , Groundfield v ~ Diff (TimeDomainOf cl))+  => v -- ^ The initial position+  -> SyncSF m cl (v, Groundfield v) v+weightedAverageFrom v0 = feedback v0 $ proc ((v, weight), vAvg) -> do+  let+    vAvg' = weight *^ vAvg ^+^ (1 - weight) *^ v+  returnA -< (vAvg', vAvg') --- | An average, or low pass. It will average out, or filter,+-- | An exponential moving average, or low pass.+--   It will average out, or filter, --   all features below a given time scale. averageFrom   :: ( Monad m, VectorSpace v+     , Floating (Groundfield v)      , Groundfield v ~ Diff (TimeDomainOf cl))   => v -- ^ The initial position   -> Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged   -> SyncSF m cl v v-averageFrom v0 t = feedback v0 $ proc (v, vAvg) -> do+averageFrom v0 t = proc v -> do   TimeInfo {..} <- timeInfo -< ()-  let vAvg' = (v ^* sinceTick ^+^ vAvg ^* t) ^/ (sinceTick + t)-  returnA                   -< (vAvg', vAvg')+  let+    weight = exp $ - (sinceTick / t)+  weightedAverageFrom v0    -< (v, weight)   -- | An average, or low pass, initialised to zero. average   :: ( Monad m, VectorSpace v+     , Floating (Groundfield v)      , Groundfield v ~ Diff (TimeDomainOf cl))   => Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged   -> SyncSF m cl v v average = averageFrom zeroVector++-- | A linearised version of 'averageFrom'.+--   It is more efficient, but only accurate+--   if the supplied time scale is much bigger+--   than the average time difference between two ticks.+averageLinFrom+  :: ( Monad m, VectorSpace v+     , Groundfield v ~ Diff (TimeDomainOf cl))+  => v -- ^ The initial position+  -> Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged+  -> SyncSF m cl v v+averageLinFrom v0 t = proc v -> do+  TimeInfo {..} <- timeInfo -< ()+  let+    weight = t / (sinceTick + t)+  weightedAverageFrom v0    -< (v, weight)++-- | Linearised version of 'average'.+averageLin+  :: ( Monad m, VectorSpace v+     , Groundfield v ~ Diff (TimeDomainOf cl))+  => Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged+  -> SyncSF m cl v v+averageLin = averageLinFrom zeroVector
src/FRP/Rhine/SyncSF/Except.hs view
@@ -34,8 +34,7 @@ -- | Within the same tick, perform a monadic action, --   and immediately throw the value as an exception. once :: Monad m => (a -> m e) -> SyncExcept m cl a b e--- once f = MSFE.once $ lift . f -- TODO dunai 0.1.2-once f = try $ arrMSync (lift . f) >>> throwS+once f = MSFE.once $ lift . f  -- | A variant of |once| without input. once_ :: Monad m => m e -> SyncExcept m cl a b e@@ -54,17 +53,7 @@ throwOn e = proc b -> throwOn' -< (b, e)  --- ** Will be in dunai-0.1.2- -- | Advances a single tick with the given Kleisli arrow, --   and then throws an exception. step :: Monad m => (a -> m (b, e)) -> SyncExcept m cl a b e-step f = try $ proc a -> do-  n      <- count               -< ()-  (b, e) <- arrMSync (lift . f) -< a-  _      <- throwOn'            -< (n > (1 :: Int), e)-  returnA                       -< b---- | Immediately throw the current input as an exception.-currentInput :: Monad m => SyncExcept m cl e b e-currentInput = try throwS+step f = MSFE.step $ lift . f