-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimedmonad.hs
56 lines (43 loc) · 1.79 KB
/
timedmonad.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
module TimedMonad where
import Control.Monad
newtype Time d = Time d deriving (Eq, Ord)
duration :: Num d => Time d -> Time d -> d
duration (Time d1) (Time d2) = d1-d2
shift :: Num d => Time d -> d-> Time d
shift (Time d1) d2 = Time (d1 + d2)
class (Ord d, Num d, Monad m, Monad t) => TimedMonad m d t | t->m, t->d where
now :: t (Time d)
drift :: t d
delay :: d-> t ()
lift :: m a -> t a
run :: t a -> m a
class (Ord d, Num d, Monad m) => HasTimer m d where
getRealTime :: m (Time d)
waitUntil :: Time d -> m ()
getDrift :: Time d -> m d
getDrift t = do {r <- getRealTime; return (duration r t)}
newtype Micro = Micro Int deriving (Show, Eq, Ord, Num)
getSystemTime :: IO (Time Micro)
getSystemTime = return (Time (Micro 10))
instance HasTimer IO Micro where
getRealTime = getSystemTime
waitUntil (Time d) = return ()
data TA m d a = TA (Time d -> m (Time d, a))
instance (Monad m, HasTimer m d, Applicative (TA m d)) => Monad (TA m d) where
return a = TA (\s -> return (s,a))
TA m >>= f = TA ( \s -> m s >>= \(s1,a) -> let (TA m1) = f a in m1 s1)
instance (Monad m, HasTimer m d, Applicative (TA m d)) => TimedMonad m d (TA m d) where
now = TA (\s -> return (s,s))
drift = TA $ \s -> getDrift s >>= \d -> return (s,d)
delay d | d <= 0 = return ()
delay d | d > 0 = TA $ \s -> do
{dr <- getDrift s; waitUntil (shift s (d - dr)); return (shift s d, ())}
lift m = TA $ \s -> m >>= \a -> return (s,a)
run (TA m) = getRealTime >>= m >>= \ (_,a) -> return a