rhine 0.7.1 → 0.8.0.0
raw patch · 22 files changed
+131/−99 lines, 22 filesdep +time-domaindep ~basedep ~dunaiPVP ok
version bump matches the API change (PVP)
Dependencies added: time-domain
Dependency ranges changed: base, dunai
API changes (from Hackage documentation)
- FRP.Rhine: data Empty
- FRP.Rhine.ClSF.Except: data Empty
- FRP.Rhine.Clock: instance (GHC.Base.Monad m, FRP.Rhine.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClock cl time)
- FRP.Rhine.Clock: instance (GHC.Base.Monad m, FRP.Rhine.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClockM m cl time)
- FRP.Rhine.Clock: instance (GHC.Base.Monad m, FRP.Rhine.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClockS m cl time tag)
- FRP.Rhine.TimeDomain: NumTimeDomain :: a -> NumTimeDomain a
- FRP.Rhine.TimeDomain: [fromNumTimeDomain] :: NumTimeDomain a -> a
- FRP.Rhine.TimeDomain: class TimeDomain time where {
- FRP.Rhine.TimeDomain: data UTCTime
- FRP.Rhine.TimeDomain: diffTime :: TimeDomain time => time -> time -> Diff time
- FRP.Rhine.TimeDomain: instance FRP.Rhine.TimeDomain.TimeDomain ()
- FRP.Rhine.TimeDomain: instance FRP.Rhine.TimeDomain.TimeDomain Data.Time.Clock.Internal.UTCTime.UTCTime
- FRP.Rhine.TimeDomain: instance FRP.Rhine.TimeDomain.TimeDomain GHC.Integer.Type.Integer
- FRP.Rhine.TimeDomain: instance FRP.Rhine.TimeDomain.TimeDomain GHC.Types.Double
- FRP.Rhine.TimeDomain: instance FRP.Rhine.TimeDomain.TimeDomain GHC.Types.Float
- FRP.Rhine.TimeDomain: instance GHC.Num.Num a => FRP.Rhine.TimeDomain.TimeDomain (FRP.Rhine.TimeDomain.NumTimeDomain a)
- FRP.Rhine.TimeDomain: instance GHC.Num.Num a => GHC.Num.Num (FRP.Rhine.TimeDomain.NumTimeDomain a)
- FRP.Rhine.TimeDomain: newtype NumTimeDomain a
- FRP.Rhine.TimeDomain: type family Diff time;
- FRP.Rhine.TimeDomain: }
+ FRP.Rhine: (>--^) :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => SN m cl a b -> ClSF m (Out cl) b c -> SN m cl a c
+ FRP.Rhine: (@>-^) :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => Rhine m cl a b -> ClSF m (Out cl) b c -> Rhine m cl a c
+ FRP.Rhine: (@>>^) :: Monad m => Rhine m cl a b -> (b -> c) -> Rhine m cl a c
+ FRP.Rhine: (^-->) :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> SN m cl b c -> SN m cl a c
+ FRP.Rhine: (^->@) :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> Rhine m cl b c -> Rhine m cl a c
+ FRP.Rhine: (^>>@) :: Monad m => (a -> b) -> Rhine m cl b c -> Rhine m cl a c
+ FRP.Rhine: [Postcompose] :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => SN m cl a b -> ClSF m (Out cl) b c -> SN m cl a c
+ FRP.Rhine: [Precompose] :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> SN m cl b c -> SN m cl a c
+ FRP.Rhine: class TimeDifference d
+ FRP.Rhine: difference :: TimeDifference d => d -> d -> d
+ FRP.Rhine.ClSF.Core: class TimeDifference d
+ FRP.Rhine.ClSF.Core: difference :: TimeDifference d => d -> d -> d
+ FRP.Rhine.Clock: class TimeDifference d
+ FRP.Rhine.Clock: difference :: TimeDifference d => d -> d -> d
+ FRP.Rhine.Clock: instance (GHC.Base.Monad m, Data.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClock cl time)
+ FRP.Rhine.Clock: instance (GHC.Base.Monad m, Data.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClockM m cl time)
+ FRP.Rhine.Clock: instance (GHC.Base.Monad m, Data.TimeDomain.TimeDomain time, FRP.Rhine.Clock.Clock m cl) => FRP.Rhine.Clock.Clock m (FRP.Rhine.Clock.RescaledClockS m cl time tag)
+ FRP.Rhine.Clock.Select: instance (GHC.Base.Monoid cl, GHC.Base.Semigroup a) => GHC.Base.Monoid (FRP.Rhine.Clock.Select.SelectClock cl a)
+ FRP.Rhine.Clock.Select: instance (GHC.Base.Semigroup a, GHC.Base.Semigroup cl) => GHC.Base.Semigroup (FRP.Rhine.Clock.Select.SelectClock cl a)
+ FRP.Rhine.Reactimation.Combinators: (@>-^) :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => Rhine m cl a b -> ClSF m (Out cl) b c -> Rhine m cl a c
+ FRP.Rhine.Reactimation.Combinators: (@>>^) :: Monad m => Rhine m cl a b -> (b -> c) -> Rhine m cl a c
+ FRP.Rhine.Reactimation.Combinators: (^->@) :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> Rhine m cl b c -> Rhine m cl a c
+ FRP.Rhine.Reactimation.Combinators: (^>>@) :: Monad m => (a -> b) -> Rhine m cl b c -> Rhine m cl a c
+ FRP.Rhine.SN: [Postcompose] :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => SN m cl a b -> ClSF m (Out cl) b c -> SN m cl a c
+ FRP.Rhine.SN: [Precompose] :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> SN m cl b c -> SN m cl a c
+ FRP.Rhine.SN.Combinators: (>--^) :: (Clock m (Out cl), Time cl ~ Time (Out cl)) => SN m cl a b -> ClSF m (Out cl) b c -> SN m cl a c
+ FRP.Rhine.SN.Combinators: (^-->) :: (Clock m (In cl), Time cl ~ Time (In cl)) => ClSF m (In cl) a b -> SN m cl b c -> SN m cl a c
- FRP.Rhine: class TimeDomain time where {
+ FRP.Rhine: class TimeDifference Diff time => TimeDomain time where {
- FRP.Rhine: safely :: forall (m :: Type -> Type) a b. Monad m => MSFExcept m a b Empty -> MSF m a b
+ FRP.Rhine: safely :: forall (m :: Type -> Type) a b. Monad m => MSFExcept m a b Void -> MSF m a b
- FRP.Rhine.ClSF.Core: class TimeDomain time where {
+ FRP.Rhine.ClSF.Core: class TimeDifference Diff time => TimeDomain time where {
- FRP.Rhine.ClSF.Except: safely :: forall (m :: Type -> Type) a b. Monad m => MSFExcept m a b Empty -> MSF m a b
+ FRP.Rhine.ClSF.Except: safely :: forall (m :: Type -> Type) a b. Monad m => MSFExcept m a b Void -> MSF m a b
- FRP.Rhine.Clock: -- | Additional information that the clock may output at each tick, e.g. if
+ FRP.Rhine.Clock: -- | The type of differences or durations between two timestamps
- FRP.Rhine.Clock: class TimeDomain time where {
+ FRP.Rhine.Clock: class TimeDifference Diff time => TimeDomain time where {
Files
- ChangeLog.md +5/−1
- rhine.cabal +15/−8
- src/FRP/Rhine/ClSF/Core.hs +0/−1
- src/FRP/Rhine/ClSF/Except.hs +1/−1
- src/FRP/Rhine/ClSF/Random.hs +0/−3
- src/FRP/Rhine/ClSF/Upsample.hs +0/−4
- src/FRP/Rhine/ClSF/Util.hs +0/−1
- src/FRP/Rhine/Clock.hs +2/−2
- src/FRP/Rhine/Clock/Periodic.hs +0/−1
- src/FRP/Rhine/Clock/Proxy.hs +2/−2
- src/FRP/Rhine/Clock/Realtime/Event.hs +0/−1
- src/FRP/Rhine/Clock/Realtime/Stdin.hs +1/−3
- src/FRP/Rhine/Clock/Select.hs +12/−1
- src/FRP/Rhine/Clock/Util.hs +3/−1
- src/FRP/Rhine/Reactimation.hs +0/−7
- src/FRP/Rhine/Reactimation/ClockErasure.hs +14/−3
- src/FRP/Rhine/Reactimation/Combinators.hs +37/−0
- src/FRP/Rhine/ResamplingBuffer.hs +0/−3
- src/FRP/Rhine/SN.hs +16/−0
- src/FRP/Rhine/SN/Combinators.hs +23/−1
- src/FRP/Rhine/Schedule.hs +0/−3
- src/FRP/Rhine/TimeDomain.hs +0/−52
ChangeLog.md view
@@ -4,10 +4,14 @@ Since `rhine` reexports modules from `dunai`, every major version in `dunai` triggers a major version in `rhine`. -## 0.7.1+## 0.8.0.0 * Documentation improvements * Support for GHC 9.0.2+* Updated to `dunai-0.8`+* Added functions to pre-/post-compose SNs and Rhines with ClSFs+* Added flake & stack support on CI.+ Thank you, Miguel Negrão and Jun Matsuhita! ## 0.7.0
rhine.cabal view
@@ -1,6 +1,6 @@ name: rhine -version: 0.7.1+version: 0.8.0.0 synopsis: Functional Reactive Programming with type-level clocks @@ -46,7 +46,7 @@ source-repository this type: git location: git@github.com:turion/rhine.git- tag: v0.7.1+ tag: v0.8.0.0 library@@ -88,7 +88,6 @@ FRP.Rhine.Schedule.Trans FRP.Rhine.SN FRP.Rhine.SN.Combinators- FRP.Rhine.TimeDomain FRP.Rhine.Type other-modules:@@ -100,8 +99,8 @@ -- other-extensions: -- Other library packages from which modules are imported.- build-depends: base >= 4.11 && < 4.16- , dunai >= 0.6+ build-depends: base >= 4.13 && < 4.16+ , dunai >= 0.8 , transformers >= 0.5 , time >= 1.8 , free >= 5.1@@ -111,16 +110,24 @@ , random >= 1.1 , MonadRandom >= 0.5 , simple-affine-space+ , time-domain -- Directories containing source files. hs-source-dirs: src - ghc-options: -Wall- -Wno-unticked-promoted-constructors- -Wno-type-defaults+ ghc-options: -W+ -Wno-unticked-promoted-constructors + if flag(dev)+ ghc-options: -Werror+ if impl(ghc >= 8.6) default-extensions: NoStarIsType -- Base language which the package is written in. default-language: Haskell2010++flag dev+ description: Enable warnings as errors. Active on ci.+ default: False+ manual: True
src/FRP/Rhine/ClSF/Core.hs view
@@ -23,7 +23,6 @@ import Control.Monad.Trans.Reader (ReaderT, mapReaderT, withReaderT) -- dunai-import Data.MonadicStreamFunction (MSF, arrM, constM, morphS, liftTransS) import Data.MonadicStreamFunction as X hiding ((>>>^), (^>>>)) -- rhine
src/FRP/Rhine/ClSF/Except.hs view
@@ -12,7 +12,7 @@ module FRP.Rhine.ClSF.Except ( module FRP.Rhine.ClSF.Except , module X- , safe, safely, Empty, exceptS, runMSFExcept, currentInput+ , safe, safely, exceptS, runMSFExcept, currentInput ) where
src/FRP/Rhine/ClSF/Random.hs view
@@ -15,9 +15,6 @@ -- transformers import Control.Monad.IO.Class --- random-import System.Random (newStdGen)- -- MonadRandom import Control.Monad.Random
src/FRP/Rhine/ClSF/Upsample.hs view
@@ -6,12 +6,8 @@ module FRP.Rhine.ClSF.Upsample where --- base-import Data.Semigroup- -- dunai import Control.Monad.Trans.MSF.Reader---import Data.MonadicStreamFunction -- rhine import FRP.Rhine.ClSF.Core
src/FRP/Rhine/ClSF/Util.hs view
@@ -29,7 +29,6 @@ -- dunai import Control.Monad.Trans.MSF.Reader (readerS)-import Data.MonadicStreamFunction (constM, sumFrom, iPre, feedback) import Data.MonadicStreamFunction.Instances.VectorSpace () -- simple-affine-space
src/FRP/Rhine/Clock.hs view
@@ -31,8 +31,8 @@ -- dunai import Data.MonadicStreamFunction as X hiding ((>>>^), (^>>>)) --- rhine-import FRP.Rhine.TimeDomain as X+-- time-domain+import Data.TimeDomain as X -- * The 'Clock' type class
src/FRP/Rhine/Clock/Periodic.hs view
@@ -17,7 +17,6 @@ module FRP.Rhine.Clock.Periodic (Periodic (Periodic)) where -- base-import Control.Monad (forever) import Data.List.NonEmpty hiding (unfold) import Data.Maybe (fromMaybe) import GHC.TypeLits (Nat, KnownNat, natVal)
src/FRP/Rhine/Clock/Proxy.hs view
@@ -28,12 +28,12 @@ inProxy :: ClockProxy cl -> ClockProxy (In cl) inProxy LeafProxy = LeafProxy-inProxy (SequentialProxy p1 p2) = inProxy p1+inProxy (SequentialProxy p1 _) = inProxy p1 inProxy (ParallelProxy pL pR) = ParallelProxy (inProxy pL) (inProxy pR) outProxy :: ClockProxy cl -> ClockProxy (Out cl) outProxy LeafProxy = LeafProxy-outProxy (SequentialProxy p1 p2) = outProxy p2+outProxy (SequentialProxy _ p2) = outProxy p2 outProxy (ParallelProxy pL pR) = ParallelProxy (outProxy pL) (outProxy pR) -- | Return the incoming tag, assuming that the incoming clock is ticked,
src/FRP/Rhine/Clock/Realtime/Event.hs view
@@ -33,7 +33,6 @@ -- base import Control.Concurrent.Chan import Data.Time.Clock-import Data.Semigroup -- deepseq import Control.DeepSeq
src/FRP/Rhine/Clock/Realtime/Stdin.hs view
@@ -9,9 +9,8 @@ {-# LANGUAGE TypeFamilies #-} module FRP.Rhine.Clock.Realtime.Stdin where --- base+-- time import Data.Time.Clock-import Data.Semigroup -- transformers import Control.Monad.IO.Class@@ -19,7 +18,6 @@ -- rhine import FRP.Rhine.Clock import FRP.Rhine.Clock.Proxy-import Data.Semigroup {- | A clock that ticks for every line entered on the console,
src/FRP/Rhine/Clock/Select.hs view
@@ -24,7 +24,6 @@ -- base import Data.Maybe (catMaybes, maybeToList)-import Data.Semigroup -- | A clock that selects certain subevents of type 'a', -- from the tag of a main clock.@@ -38,6 +37,18 @@ -- or 'Just a' if the subclock should tick, with tag 'a'. , select :: Tag cl -> Maybe a }++instance (Semigroup a, Semigroup cl) => Semigroup (SelectClock cl a) where+ cl1 <> cl2 = SelectClock+ { mainClock = mainClock cl1 <> mainClock cl2+ , select = \tag -> select cl1 tag <> select cl2 tag+ }++instance (Monoid cl, Semigroup a) => Monoid (SelectClock cl a) where+ mempty = SelectClock+ { mainClock = mempty+ , select = const mempty+ } instance (Monad m, Clock m cl) => Clock m (SelectClock cl a) where
src/FRP/Rhine/Clock/Util.hs view
@@ -2,10 +2,12 @@ {-# LANGUAGE RecordWildCards #-} module FRP.Rhine.Clock.Util where +-- time-domain+import Data.TimeDomain+ -- rhine import FRP.Rhine.Clock import FRP.Rhine.Clock.Proxy-import FRP.Rhine.TimeDomain -- * Auxiliary definitions and utilities
src/FRP/Rhine/Reactimation.hs view
@@ -8,10 +8,6 @@ {-# LANGUAGE RecordWildCards #-} module FRP.Rhine.Reactimation where --- base-import Control.Monad ((>=>))-import Data.Functor (void)- -- dunai import Data.MonadicStreamFunction.InternalCore @@ -19,12 +15,9 @@ import FRP.Rhine.Clock import FRP.Rhine.Clock.Proxy import FRP.Rhine.ClSF.Core-import FRP.Rhine.Reactimation.ClockErasure import FRP.Rhine.Reactimation.Combinators import FRP.Rhine.Schedule import FRP.Rhine.Type-- -- * Running a Rhine
src/FRP/Rhine/Reactimation/ClockErasure.hs view
@@ -13,12 +13,10 @@ -- base import Control.Monad (join)-import Data.Maybe (fromJust, fromMaybe) -- dunai import Control.Monad.Trans.MSF.Reader import Data.MonadicStreamFunction-import Data.MonadicStreamFunction.InternalCore -- rhine import FRP.Rhine.Clock@@ -26,7 +24,6 @@ import FRP.Rhine.Clock.Util import FRP.Rhine.ClSF hiding (runReaderS) import FRP.Rhine.ResamplingBuffer-import FRP.Rhine.Schedule import FRP.Rhine.SN -- | Run a clocked signal function as a monadic stream function,@@ -86,6 +83,20 @@ case tag of Left tagL -> eraseClockSN initialTime snL -< (time, tagL, maybeA) Right tagR -> eraseClockSN initialTime snR -< (time, tagR, maybeA)++eraseClockSN initialTime (Postcompose sn clsf) =+ let+ proxy = toClockProxy sn+ in proc input@(time, tag, _) -> do+ bMaybe <- eraseClockSN initialTime sn -< input+ mapMaybeS $ eraseClockClSF (outProxy proxy) initialTime clsf -< (time, , ) <$> outTag proxy tag <*> bMaybe++eraseClockSN initialTime (Precompose clsf sn) =+ let+ proxy = toClockProxy sn+ in proc (time, tag, aMaybe) -> do+ bMaybe <- mapMaybeS $ eraseClockClSF (inProxy proxy) initialTime clsf -< (time, , ) <$> inTag proxy tag <*> aMaybe+ eraseClockSN initialTime sn -< (time, tag, bMaybe) -- | Translate a resampling buffer into a monadic stream function. --
src/FRP/Rhine/Reactimation/Combinators.hs view
@@ -191,3 +191,40 @@ -> Rhine m (ParallelClock m clL clR) a b RhineParallelAndSchedule (Rhine sn1 clL) schedule @|| (Rhine sn2 clR) = Rhine (sn1 |||| sn2) (ParallelClock clL clR schedule)+++-- | Postcompose a 'Rhine' with a pure function.+(@>>^)+ :: Monad m+ => Rhine m cl a b+ -> (b -> c)+ -> Rhine m cl a c+Rhine sn cl @>>^ f = Rhine (sn >>>^ f) cl++-- | Precompose a 'Rhine' with a pure function.+(^>>@)+ :: Monad m+ => (a -> b)+ -> Rhine m cl b c+ -> Rhine m cl a c+f ^>>@ Rhine sn cl = Rhine (f ^>>> sn) cl++-- | Postcompose a 'Rhine' with a 'ClSF'.+(@>-^)+ :: ( Clock m (Out cl)+ , Time cl ~ Time (Out cl)+ )+ => Rhine m cl a b+ -> ClSF m (Out cl) b c+ -> Rhine m cl a c+Rhine sn cl @>-^ clsf = Rhine (sn >--^ clsf) cl++-- | Precompose a 'Rhine' with a 'ClSF'.+(^->@)+ :: ( Clock m (In cl)+ , Time cl ~ Time (In cl)+ )+ => ClSF m (In cl) a b+ -> Rhine m cl b c+ -> Rhine m cl a c+clsf ^->@ Rhine sn cl = Rhine (clsf ^--> sn) cl
src/FRP/Rhine/ResamplingBuffer.hs view
@@ -18,9 +18,6 @@ -- rhine import FRP.Rhine.Clock --- base-import Control.Arrow (second)- -- A quick note on naming conventions, to whoever cares: -- . Call a single clock @cl@. -- . Call several clocks @cl1@, @cl2@ etc. in most situations.
src/FRP/Rhine/SN.hs view
@@ -69,6 +69,22 @@ => SN m cl1 a b -> SN m cl2 a b -> SN m (ParallelClock m cl1 cl2) a b+ -- | A 'ClSF' can always be postcomposed onto an 'SN' if the clocks match on the output.+ Postcompose+ :: ( Clock m (Out cl)+ , Time cl ~ Time (Out cl)+ )+ => SN m cl a b+ -> ClSF m (Out cl) b c+ -> SN m cl a c+ -- | A 'ClSF' can always be precomposed onto an 'SN' if the clocks match on the input.+ Precompose+ :: ( Clock m (In cl)+ , Time cl ~ Time (In cl)+ )+ => ClSF m (In cl) a b+ -> SN m cl b c+ -> SN m cl a c 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
@@ -24,7 +24,8 @@ Synchronous clsf >>>^ f = Synchronous $ clsf >>^ f Sequential sn1 rb sn2 >>>^ f = Sequential sn1 rb $ sn2 >>>^ f 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 -- | Precompose a signal network with a pure function. (^>>>)@@ -35,7 +36,28 @@ f ^>>> Synchronous clsf = Synchronous $ f ^>> clsf f ^>>> Sequential sn1 rb sn2 = Sequential (f ^>>> sn1) rb sn2 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 +-- | Postcompose a signal network with a 'ClSF'.+(>--^)+ :: ( Clock m (Out cl)+ , Time cl ~ Time (Out cl)+ )+ => SN m cl a b+ -> ClSF m (Out cl) b c+ -> SN m cl a c+(>--^) = Postcompose++-- | Precompose a signal network with a 'ClSF'.+(^-->)+ :: ( Clock m (In cl)+ , Time cl ~ Time (In cl)+ )+ => ClSF m (In cl) a b+ -> SN m cl b c+ -> SN m cl a c+(^-->) = Precompose -- | Compose two signal networks on the same clock in data-parallel. -- At one tick of @cl@, both networks are stepped.
src/FRP/Rhine/Schedule.hs view
@@ -21,9 +21,6 @@ module FRP.Rhine.Schedule where --- base-import Data.Semigroup- -- transformers import Control.Monad.Trans.Reader
− src/FRP/Rhine/TimeDomain.hs
@@ -1,52 +0,0 @@-{- |-This module defines the 'TimeDomain' class.-Its instances model time.-Several instances such as 'UTCTime', 'Double' and 'Integer' are supplied here.--}--{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeFamilies #-}-module FRP.Rhine.TimeDomain- ( module FRP.Rhine.TimeDomain- , UTCTime- )- where---- time-import Data.Time.Clock (UTCTime, diffUTCTime)---- | A time domain is an affine space representing a notion of time,--- such as real time, simulated time, steps, or a completely different notion.-class TimeDomain time where- type Diff time- diffTime :: time -> time -> Diff time---instance TimeDomain UTCTime where- type Diff UTCTime = Double- diffTime t1 t2 = realToFrac $ diffUTCTime t1 t2--instance TimeDomain Double where- type Diff Double = Double- diffTime = (-)--instance TimeDomain Float where- type Diff Float = Float- diffTime = (-)--instance TimeDomain Integer where- type Diff Integer = Integer- diffTime = (-)--instance TimeDomain () where- type Diff () = ()- diffTime _ _ = ()---- | Any 'Num' can be wrapped to form a 'TimeDomain'.-newtype NumTimeDomain a = NumTimeDomain { fromNumTimeDomain :: a }- deriving Num--instance Num a => TimeDomain (NumTimeDomain a) where- type Diff (NumTimeDomain a) = NumTimeDomain a- diffTime = (-)