module Data.EventList.Absolute.TimeBodyPrivate where
import qualified Data.AlternatingList.List.Disparate as Disp
import qualified Control.Monad as Monad
import qualified Data.Foldable as Fold
import qualified Data.Traversable as Trav
import qualified Control.Applicative as App
import Control.Applicative (Applicative, )
import Data.Monoid (Monoid, mempty, mappend, mconcat, )
import Data.Semigroup (Semigroup, (<>), )
import Test.QuickCheck (Arbitrary(arbitrary, shrink))
import Prelude hiding (concat, cycle)
newtype T time body = Cons {decons :: Disp.T time body}
deriving (Eq, Ord, Show)
instance (Arbitrary time, Arbitrary body) =>
Arbitrary (T time body) where
arbitrary = Monad.liftM Cons arbitrary
shrink = liftM shrink
instance (Num time, Ord time) => Semigroup (T time body) where
(<>) = append
instance (Num time, Ord time) => Monoid (T time body) where
mempty = Cons Disp.empty
mappend = append
mconcat = concat
instance Functor (T time) where
fmap f (Cons x) = Cons (Disp.mapSecond f x)
instance Fold.Foldable (T time) where
foldMap = Trav.foldMapDefault
instance Trav.Traversable (T time) where
traverse f =
App.liftA Cons . Disp.traverse App.pure f . decons
infixl 5 $~
($~) :: (Disp.T time body -> a) -> (T time body -> a)
($~) f = f . decons
lift ::
(Disp.T time0 body0 -> Disp.T time1 body1) ->
(T time0 body0 -> T time1 body1)
lift f = Cons . f . decons
liftA :: Applicative m =>
(Disp.T time0 body0 -> m (Disp.T time1 body1)) ->
(T time0 body0 -> m (T time1 body1))
liftA f = App.liftA Cons . f . decons
liftM :: Monad m =>
(Disp.T time0 body0 -> m (Disp.T time1 body1)) ->
(T time0 body0 -> m (T time1 body1))
liftM f = Monad.liftM Cons . f . decons
switchL :: c -> ((time, body) -> T time body -> c) -> T time body -> c
switchL f g = Disp.switchL f (\ t b -> g (t,b) . Cons) . decons
switchR :: c -> (T time body -> (time, body) -> c) -> T time body -> c
switchR f g = Disp.switchR f (\xs t b -> g (Cons xs) (t,b)) . decons
mapBody :: (body0 -> body1) -> T time body0 -> T time body1
mapBody f = lift (Disp.mapSecond f)
mapTime :: (time0 -> time1) -> T time0 body -> T time1 body
mapTime f = lift (Disp.mapFirst f)
duration :: Num time => T time body -> time
duration = switchR 0 (const fst)
delay :: (Ord time, Num time) =>
time -> T time body -> T time body
delay dif =
if dif>=0
then mapTime (dif+)
else error "delay: negative delay"
append :: (Ord time, Num time) =>
T time body -> T time body -> T time body
append xs = lift (Disp.append $~ xs) . delay (duration xs)
concat :: (Ord time, Num time) =>
[T time body] -> T time body
concat xs =
let ts = scanl (+) 0 (map duration xs)
in Cons $ Disp.concat $ map decons $ zipWith delay ts xs
cycle :: (Ord time, Num time) =>
T time body -> T time body
cycle = concat . repeat