module Control.Wire.Session
(
HasTime(..),
Session(..),
Timed(..),
clockSession,
clockSession_,
countSession,
countSession_
)
where
import Control.Applicative
import Control.Monad.IO.Class
import Data.Data
import Data.Foldable (Foldable)
import Data.Monoid
import Data.Time.Clock
import Data.Traversable (Traversable)
class (Monoid s, Real t) => HasTime t s | s -> t where
dtime :: s -> t
newtype Session m s =
Session {
stepSession :: m (s, Session m s)
}
deriving (Functor)
instance (Applicative m) => Applicative (Session m) where
pure x = let s = Session (pure (x, s)) in s
Session ff <*> Session fx =
Session $ liftA2 (\(f, sf) (x, sx) -> (f x, sf <*> sx)) ff fx
data Timed t s = Timed t s
deriving (Data, Eq, Foldable, Functor,
Ord, Read, Show, Traversable, Typeable)
instance (Monoid s, Real t) => HasTime t (Timed t s) where
dtime (Timed dt _) = dt
instance (Monoid s, Num t) => Monoid (Timed t s) where
mempty = Timed 0 mempty
mappend (Timed dt1 ds1) (Timed dt2 ds2) =
let dt = dt1 + dt2
ds = ds1 <> ds2
in dt `seq` ds `seq` Timed dt ds
clockSession :: (MonadIO m) => Session m (s -> Timed NominalDiffTime s)
clockSession =
Session $ do
t0 <- liftIO getCurrentTime
return (Timed 0, loop t0)
where
loop t' =
Session $ do
t <- liftIO getCurrentTime
let dt = diffUTCTime t t'
dt `seq` return (Timed dt, loop t)
clockSession_ :: (Applicative m, MonadIO m) => Session m (Timed NominalDiffTime ())
clockSession_ = clockSession <*> pure ()
countSession ::
(Applicative m)
=> t
-> Session m (s -> Timed t s)
countSession dt =
let loop = Session (pure (Timed dt, loop))
in loop
countSession_ :: (Applicative m, MonadIO m) => t -> Session m (Timed t ())
countSession_ dt = countSession dt <*> pure ()