-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Use a time unit class, but hold a concrete time type. -- @package time-interval @version 0.1.0.0 -- | Suppose you have a program which periodically reloads state and saves -- some logs, and you'd like the intervals for these periodic actions to -- be expressed using time units, and abstract away the internal -- representation until the site of actual use. Your code may look like -- this: -- --
-- data AppState tr ts = AppState
-- { userName :: String
-- , newMessages :: [String]
-- , reloadInterval :: tr
-- , saveInterval :: ts
-- }
--
-- type App tr ts = StateT (AppState tr ts) IO
--
-- setReloadInterval :: TimeUnit t => t -> App ()
-- setReloadInterval new = modify $ \ s -> s { reloadInterval = new }
--
-- syncStateWithFiles :: (TimeUnit tr, TimeUnit ts) => App tr ts ()
-- syncStateWithFiles = do
-- reloadMicrosec <- liftM toMicroseconds $ gets reloadInterval
-- saveMicrosec <- liftM toMicroseconds $ gets saveInterval
-- {- ... use the values ... -}
--
--
-- And usage looks like this:
--
-- -- setReloadInterval (5 :: Second) ---- -- So every time you add, change or remove a time field, all your type -- signatures need to be updated and all your App actions, even -- unrelated to those times, are stuck with time type parameters in their -- type signatures. -- -- An easy and common approach to avoid all the mess is to store the time -- as an integer, i.e. applying toMicroseconds when setting the -- value rather than when using it. That makes things much easier, but -- then your type (and your API) expose the time directly as a number of -- microseconds, and people end up writing things like 1000 * 1000 * -- 60 * 5 to say "5 minuts". It's also an internal technical detail -- there's no reason to expose, and should be possible to change without -- breaking anything - e.g. what if your scheduling tool one day moves to -- a higher precision than microseconds? Your high-level API would -- ideally not let that change float all the way up. -- -- Here's how things can work when using this library. -- --
-- data AppState = AppState
-- { userName :: String
-- , newMessages :: [String]
-- , reloadInterval :: TimeInterval
-- , saveInterval :: TimeInterval
-- }
--
-- type App = StateT AppState IO
--
-- setReloadInterval :: TimeUnit t => t -> App ()
-- setReloadInterval new = modify $ \ s -> s { reloadInterval = time new }
--
-- syncStateWithFiles :: App ()
-- syncStateWithFiles = do
-- reloadMicrosec <- liftM microseconds $ gets reloadInterval
-- saveMicrosec <- liftM microseconds $ gets saveInterval
-- {- ... use the values ... -}
--
--
-- And usage looks the same:
--
-- -- setReloadInterval (5 :: Second) ---- -- Also, even if you let the user use the time function in their -- code, e.g. like this: -- --
-- setReloadInterval $ time (5 :: Second) ---- -- ... you stil get the advantages from both worlds. module Data.Time.Interval -- | A time duration. data TimeInterval -- | Convert a time value expressed in a some time unit into a -- TimeInterval. time :: TimeUnit t => t -> TimeInterval -- | Express a TimeInterval in microseconds. microseconds :: TimeInterval -> Integer instance Eq TimeInterval instance Ord TimeInterval instance Show TimeInterval