{- | Copyright : (c) Henning Thielemann 2007-2009 Maintainer : haskell@henning-thielemann.de Stability : stable Portability : Haskell 98 -} module Data.EventList.Absolute.TimeBodyPrivate where import qualified Data.AlternatingList.List.Disparate as Disp -- import qualified Data.AlternatingList.List.Uniform as Uniform -- import qualified Data.AlternatingList.List.Mixed as Mixed 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 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) => 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 {-# INLINE switchL #-} 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 {-# INLINE switchR #-} 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 of an empty event list is considered zero. However, I'm not sure if this is sound. -} duration :: Num time => T time body -> time duration = switchR 0 (const fst) {- Is it necessary to exclude negative delays? Even negative time stamps should not hurt absolutely timestamped lists. -} 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 {- Unfortunately in absolute lists we cannot use sharing as in List.cycle since the start times of the later lists are greater. -} cycle :: (Ord time, Num time) => T time body -> T time body cycle = concat . repeat