-- | -- Module: Control.Wire.Trans.Clock -- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez -- -- Supplying clocks to wires. module Control.Wire.Trans.Clock ( -- * Time deltas WWithDT(..), -- * Global time WWithSysTime(..), -- * Local time WWithTime(..) ) where import Control.Arrow import Control.Monad.Fix import Control.Wire.Classes import Control.Wire.Types import Data.AdditiveGroup -- | Passes time deltas to the given wire with respect to the clock -- represented by the underlying arrow. Using this wire transformer you -- can program in the more traditional AFRP way using time deltas -- instead of time offsets. Note: The first time delta is 0. -- -- * Depends: Like argument wire. -- -- * Inhibits: When argument wire inhibits. class Arrow (>~) => WWithDT t (>~) | (>~) -> t where -- | Simplified variant without additional input. passDT :: Wire e (>~) t b -> Wire e (>~) a b -- | Full variant. withDT :: Wire e (>~) (a, t) b -> Wire e (>~) a b instance (AdditiveGroup t, MonadClock t m) => WWithDT t (Kleisli m) where passDT w' = WmGen $ \_ -> do t <- getTime (mx, w) <- toGenM w' zeroV return (mx, withDT' t w) where withDT' :: t -> Wire e (Kleisli m) t b -> Wire e (Kleisli m) a b withDT' t' w' = WmGen $ \_ -> do t <- getTime let dt = t ^-^ t' (mx, w) <- toGenM w' dt return (mx, withDT' t w) withDT w' = WmGen $ \x' -> do t <- getTime (mx, w) <- toGenM w' (x', zeroV) return (mx, withDT' t w) where withDT' :: t -> Wire e (Kleisli m) (a, t) b -> Wire e (Kleisli m) a b withDT' t' w' = WmGen $ \x' -> do t <- getTime let dt = t ^-^ t' (mx, w) <- toGenM w' (x', dt) return (mx, withDT' t w) -- | Passes the time passed since the first instant to the given wire. -- -- * Depends: Like argument wire. -- -- * Inhibits: When argument wire inhibits. class Arrow (>~) => WWithTime t (>~) | (>~) -> t where -- | Simplified variant without additional input. passTime :: Wire e (>~) t b -> Wire e (>~) a b -- | Full variant. withTime :: Wire e (>~) (a, t) b -> Wire e (>~) a b instance (AdditiveGroup t, MonadClock t m) => WWithTime t (Kleisli m) where passTime = withTime . mapInputM snd withTime w' = WmGen $ \x' -> do t0 <- getTime (mx, w) <- toGenM w' (x', zeroV) return (mx, withTime' t0 w) where withTime' :: t -> Wire e (Kleisli m) (a, t) b -> Wire e (Kleisli m) a b withTime' t0 = fix $ \again w' -> WmGen $ \x' -> do t <- getTime (mx, w) <- toGenM w' (x', t ^-^ t0) return (mx, again w) -- | Passes the system time to the given wire. -- -- * Depends: Like argument wire. -- -- * Inhibits: When argument wire inhibits. class Arrow (>~) => WWithSysTime t (>~) | (>~) -> t where -- | Simplified variant without additional input. passSysTime :: Wire e (>~) t b -> Wire e (>~) a b -- | Full variant. withSysTime :: Wire e (>~) (a, t) b -> Wire e (>~) a b instance MonadClock t m => WWithSysTime t (Kleisli m) where passSysTime = withSysTime . mapInputM snd withSysTime w' = WmGen $ \x' -> do t <- getTime (mx, w) <- toGenM w' (x', t) return (mx, withSysTime w)