{- |
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 :: UTCTime -> UTCTime -> Diff UTCTime
diffTime UTCTime
t1 UTCTime
t2 = NominalDiffTime -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (NominalDiffTime -> Double) -> NominalDiffTime -> Double
forall a b. (a -> b) -> a -> b
$ UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime UTCTime
t1 UTCTime
t2

instance TimeDomain Double where
  type Diff Double = Double
  diffTime :: Double -> Double -> Diff Double
diffTime = (-)

instance TimeDomain Float where
  type Diff Float = Float
  diffTime :: Float -> Float -> Diff Float
diffTime = (-)

instance TimeDomain Integer where
  type Diff Integer = Integer
  diffTime :: Integer -> Integer -> Diff Integer
diffTime          = (-)

instance TimeDomain () where
  type Diff () = ()
  diffTime :: () -> () -> Diff ()
diffTime ()
_ ()
_ = ()

-- | Any 'Num' can be wrapped to form a 'TimeDomain'.
newtype NumTimeDomain a = NumTimeDomain { NumTimeDomain a -> a
fromNumTimeDomain :: a }
  deriving Integer -> NumTimeDomain a
NumTimeDomain a -> NumTimeDomain a
NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
(NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a)
-> (NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a)
-> (NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a)
-> (NumTimeDomain a -> NumTimeDomain a)
-> (NumTimeDomain a -> NumTimeDomain a)
-> (NumTimeDomain a -> NumTimeDomain a)
-> (Integer -> NumTimeDomain a)
-> Num (NumTimeDomain a)
forall a. Num a => Integer -> NumTimeDomain a
forall a. Num a => NumTimeDomain a -> NumTimeDomain a
forall a.
Num a =>
NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> NumTimeDomain a
$cfromInteger :: forall a. Num a => Integer -> NumTimeDomain a
signum :: NumTimeDomain a -> NumTimeDomain a
$csignum :: forall a. Num a => NumTimeDomain a -> NumTimeDomain a
abs :: NumTimeDomain a -> NumTimeDomain a
$cabs :: forall a. Num a => NumTimeDomain a -> NumTimeDomain a
negate :: NumTimeDomain a -> NumTimeDomain a
$cnegate :: forall a. Num a => NumTimeDomain a -> NumTimeDomain a
* :: NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
$c* :: forall a.
Num a =>
NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
- :: NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
$c- :: forall a.
Num a =>
NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
+ :: NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
$c+ :: forall a.
Num a =>
NumTimeDomain a -> NumTimeDomain a -> NumTimeDomain a
Num

instance Num a => TimeDomain (NumTimeDomain a) where
  type Diff (NumTimeDomain a) = NumTimeDomain a
  diffTime :: NumTimeDomain a -> NumTimeDomain a -> Diff (NumTimeDomain a)
diffTime = (-)