time-domain-1.6: src/Data/TimeDomain.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{- |
This module defines the 'TimeDomain' class.
Its instances model time,
simulated and realtime.
Several instances such as 'UTCTime', 'Double' and 'Integer' are supplied here.
-}
module Data.TimeDomain (
module Data.TimeDomain,
UTCTime,
)
where
-- time
import Data.Time.Clock (UTCTime, addUTCTime, 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.
Expected laws:
* @(t1 `diffTime` t3) `difference` (t1 `diffTime` t2) = t2 `diffTime` t3@
* @(t `addTime` dt) `diffTime` t = dt@
* @(t `addTime` dt1) `addTime` dt2 = t `addTime` (dt1 `add` dt2)@
-}
class (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@.
diffTime :: time -> time -> Diff time
-- | Add a time difference to a timestamp.
addTime :: time -> Diff time -> time
{- | A type of durations, or differences betweens time stamps.
Expected laws:
* `add` is commutative and associative
* @(dt1 `difference` dt2) `add` dt2 = dt1@
-}
class TimeDifference d where
-- | Calculate the difference between two durations,
-- compatibly with 'diffTime'.
difference :: d -> d -> d
-- | Add two time differences.
add :: d -> d -> d
-- | Differences between 'UTCTime's are measured in seconds.
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 = (+)
instance TimeDifference Integer where
difference = (-)
add = (+)
instance TimeDomain Integer where
type Diff Integer = Integer
diffTime = (-)
addTime = (+)
instance TimeDifference () where
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)
instance (Num a) => TimeDifference (NumTimeDomain a) where
difference = (-)
add = (+)
instance (Num a) => TimeDomain (NumTimeDomain a) where
type Diff (NumTimeDomain a) = NumTimeDomain a
diffTime = (-)
addTime = (+)