{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TypeFamilies #-} ------------------------------------------------------------------------------------- -- | -- Copyright : (c) Hans Hoglund 2012 -- -- License : BSD-style -- -- Maintainer : hans@hanshoglund.se -- Stability : experimental -- Portability : non-portable (TF,GNTD) -- ------------------------------------------------------------------------------------- module Music.Time.Time ( -- $convert -- * Time type Time(..), -- * Duration type Duration, -- * Behavior class HasBehavior(..), -- ** Identities start, stop, unit, -- ** Combinators -- TODO ) where import Data.AffineSpace import Data.AffineSpace.Point import Data.Semigroup import Data.VectorSpace import Music.Score.Util (showRatio) -- $convert -- -- Note that you should use '.-.' and '.+^' to convert between time and -- duration. To refer to time zero (the beginning of the music), use -- 'origin'. -- -- | -- This type represents relative time in seconds. -- newtype Duration = Duration { getDuration :: Rational } deriving (Eq, Ord, Num, Enum, Fractional, Real, RealFrac, AdditiveGroup) instance Show Duration where show = showRatio . getDuration instance VectorSpace Duration where type Scalar Duration = Duration (Duration x) *^ (Duration y) = Duration (x *^ y) -- | -- The unit duration. -- unit :: Duration unit = 1 -- TODO some overloaded unit value -- | -- This type represents absolute time in seconds since 'start'. Note that time can be -- negative, representing events occuring before the start time. -- -- Time forms an affine space with durations as the underlying vector space, -- that is, we can add a time to a duration to get a new time using '.+^', -- take the difference of two times to get a duration using '.-.'. -- type Time = Point Duration instance Num Time where (+) = relative2 origin (+) (*) = relative2 origin (*) negate = mirror abs = relative origin abs signum = relative origin signum fromInteger = (origin .+^) . fromInteger instance Fractional Time where recip = relative origin recip fromRational = (origin .+^) . fromRational -- | -- The global start time, which usually means the the beginning of the musical performance. -- -- This is a synonym for 'origin'. -- start :: Time start = origin -- | -- The global end time, defined as @start .+^ unit@. -- stop :: Time stop = origin .+^ unit class HasBehavior f where (?) :: f a -> Time -> a instance HasBehavior ((->) Time) where (?) = id