packages feed

time-domain 1.6 → 1.7

raw patch · 3 files changed

+80/−51 lines, 3 filesdep +changesetdep +groups

Dependencies added: changeset, groups

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for time-domain +## 1.7++* Introduce `Seconds` time domain+* Base the `TimeDomain` class hierarchy on `Group` (from `monoid-extras`) and `RightAction` (from `changeset`)+* Extend the `TimeDifference` type class+ ## 0.1.0.5  * Support GHC 9.10
src/Data/TimeDomain.hs view
@@ -1,7 +1,12 @@+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DerivingVia #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}  {- | This module defines the 'TimeDomain' class.@@ -15,9 +20,18 @@ ) where +-- base+import Data.Monoid (Sum (..))+ -- time import Data.Time.Clock (UTCTime, addUTCTime, diffUTCTime) +-- groups+import Data.Group (Group (..))++-- changeset+import Data.Monoid.RightAction (RightAction (actRight), RightTorsor (differenceRight))+ {- | A time domain is an affine space representing a notion of time, such as real time, simulated time, steps, or a completely different notion.@@ -28,86 +42,93 @@ * @(t `addTime` dt) `diffTime` t = dt@ * @(t `addTime` dt1) `addTime` dt2 = t `addTime` (dt1 `add` dt2)@ -}-class (TimeDifference (Diff time)) => TimeDomain time where+class (RightAction (Diff time) time, RightTorsor (Diff time) time, TimeDifference (Diff time)) => TimeDomain time where   -- | The type of differences or durations between two timestamps   type Diff time -  -- | Compute the difference between two timestamps.-  ---  --   Mnemonic: 'diffTime' behaves like the '(-)' operator:-  ---  --   @'diffTime' earlier later = later `'diffTime'` earlier@ is the duration it takes from @earlier@ to @later@.+  {- | Compute the difference between two timestamps.++  Mnemonic: 'diffTime' behaves like the '(-)' operator:++  @'diffTime' earlier later = later `'diffTime'` earlier@ is the duration it takes from @earlier@ to @later@.+  -}   diffTime :: time -> time -> Diff time+  diffTime = differenceRight    -- | Add a time difference to a timestamp.   addTime :: time -> Diff time -> time+  addTime = actRight  {- | A type of durations, or differences betweens time stamps.  Expected laws: +* @dt `add` 'zero' = dt@ and @dt `difference` 'zero' = dt@ * `add` is commutative and associative * @(dt1 `difference` dt2) `add` dt2 = dt1@ -}-class TimeDifference d where-  -- | Calculate the difference between two durations,-  --   compatibly with 'diffTime'.+class (Group d) => TimeDifference d where+  {- | The zero duration, i.e. no time has passed.+  Additive identity for 'difference' and 'add'.+  -}+  zero :: d+  zero = mempty++  {- | Calculate the difference between two durations,+  compatibly with 'diffTime'.+  -}   difference :: d -> d -> d+  difference = (~~)    -- | Add two time differences.   add :: d -> d -> d+  add = (<>) --- | Differences between 'UTCTime's are measured in seconds.+-- | Differences between 'UTCTime's are measured in Secondss. instance TimeDomain UTCTime where-  type Diff UTCTime = Double-  diffTime t1 t2 = realToFrac $ diffUTCTime t1 t2-  addTime = flip $ addUTCTime . realToFrac--instance TimeDifference Double where-  difference = (-)-  add = (+)--instance TimeDomain Double where-  type Diff Double = Double-  diffTime = (-)-  addTime = (+)--instance TimeDifference Float where-  difference = (-)-  add = (+)--instance TimeDomain Float where-  type Diff Float = Float-  diffTime = (-)-  addTime = (+)+  type Diff UTCTime = Seconds Double -instance TimeDifference Integer where-  difference = (-)-  add = (+)+instance RightAction (Seconds Double) UTCTime where+  actRight = flip $ addUTCTime . realToFrac . getSeconds -instance TimeDomain Integer where-  type Diff Integer = Integer-  diffTime = (-)-  addTime = (+)+instance RightTorsor (Seconds Double) UTCTime where+  differenceRight t1 t2 = Seconds $ realToFrac $ diffUTCTime t1 t2  instance TimeDifference () where+  zero = ()   difference _ _ = ()   add _ _ = ()  instance TimeDomain () where   type Diff () = ()-  diffTime _ _ = ()-  addTime _ _ = () --- | Any 'Num' can be wrapped to form a 'TimeDomain'.-newtype NumTimeDomain a = NumTimeDomain {fromNumTimeDomain :: a}-  deriving (Num)+{- | Any 'Num' can be wrapped to form a 'TimeDomain'. -instance (Num a) => TimeDifference (NumTimeDomain a) where-  difference = (-)-  add = (+)+The number 1 is interpreted as one second.+-}+newtype Seconds a = Seconds {getSeconds :: a}+  deriving newtype (Show, Read, Eq, Ord, Num, Fractional, Floating, Real, RealFrac, RealFloat, Enum, Bounded, Integral)+  deriving stock (Functor, Foldable, Traversable) -instance (Num a) => TimeDomain (NumTimeDomain a) where-  type Diff (NumTimeDomain a) = NumTimeDomain a-  diffTime = (-)-  addTime = (+)+deriving via Sum (Seconds a) instance (Num a) => Semigroup (Seconds a)+deriving via Sum (Seconds a) instance (Num a) => Monoid (Seconds a)+deriving via Sum (Seconds a) instance (Num a) => Group (Seconds a)+instance (Num a) => TimeDifference (Seconds a)++-- I would have thought I shouldn't be needing this, but it seems to overlap with the Zip instance for some reason.+instance {-# OVERLAPPING #-} (Num a) => RightAction (Seconds a) (Seconds a) where+  actRight = (+)++instance (Num a) => RightTorsor (Seconds a) (Seconds a) where+  differenceRight = (-)++instance (Num a) => TimeDomain (Seconds a) where+  type Diff (Seconds a) = Seconds a++-- | Scale time differences by a factor.+instance (Num a) => RightAction a (Seconds a) where+  actRight seconds factor = fmap (* factor) seconds++-- | Compute the quotient of two time differences.+instance (Fractional a) => RightTorsor a (Seconds a) where+  differenceRight (Seconds secondsOrig) (Seconds secondsScaled) = secondsOrig / secondsScaled
time-domain.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: time-domain-version: 1.6+version: 1.7 license: MIT license-file: LICENSE author: Manuel Bärenz@@ -32,6 +32,8 @@   exposed-modules: Data.TimeDomain   build-depends:     base >=4.13.0 && <4.22,+    changeset ^>=0.2.1,+    groups ^>=0.5.3,     time >=1.11 && <1.16,    hs-source-dirs: src