music-score-1.6: src/Music/Time/Reverse.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-------------------------------------------------------------------------------------
-- |
-- Copyright : (c) Hans Hoglund 2012
--
-- License : BSD-style
--
-- Maintainer : hans@hanshoglund.se
-- Stability : experimental
-- Portability : non-portable (TF,GNTD)
--
-- Provides reversible values.
--
-------------------------------------------------------------------------------------
module Music.Time.Reverse (
-- * Reversible class
Reversible(..),
-- ** Utility
NoRev(..),
WithRev(..),
withRev,
fromWithRev,
) where
import Data.AffineSpace
import Data.AffineSpace.Point
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Ratio
import Data.Semigroup
import Data.Set (Set)
import qualified Data.Set as Set
import Data.VectorSpace
import Music.Time.Delayable
import Music.Time.Juxtapose
import Music.Time.Onset
import Music.Time.Stretchable
import Music.Time.Time
-- |
-- Reversible values.
--
-- For instances of 'Reversible' and 'HasOnset', the following laws should hold:
--
-- > onset a = onset (rev a)
-- > duration a = duration (rev a)
--
-- For structural types, 'rev' is applied recursively, hence the constraint on
-- the 'Score' instance. 'rev' is id by default, so for a trivial type @T@ it
-- suffices to write
--
-- > instance Reversible T
--
-- For instances 'U' of 'HasOnset' and 'Transformable', a suitable instance
-- is
--
-- > instance Reversible T where
-- > rev = withSameOnset (stretch (-1))
--
--
class Reversible a where
-- |
-- Reverse a value.
--
-- Reverse is an involution, meaning that:
--
-- > rev (rev a) = a
--
rev :: a -> a
rev = id
-- instance Reversible Time where
-- rev t = mirror t
instance Reversible Double
instance Reversible Float
instance Reversible Int
instance Reversible Integer
instance Reversible ()
instance Reversible (Ratio a)
instance Reversible a => Reversible [a] where
rev = fmap rev
instance (Ord a, Reversible a) => Reversible (Set a) where
rev = Set.map rev
instance Reversible a => Reversible (Map k a) where
rev = fmap rev
newtype NoRev a = NoRev { getNoRev :: a }
deriving (Eq, Ord, Enum, Show, Semigroup, Monoid,
Delayable, Stretchable, HasOnset, HasOffset, HasDuration)
instance Reversible (NoRev a) where
rev = id
newtype WithRev a = WithRev (a,a)
deriving (Eq, Ord, Semigroup, Monoid)
withRev :: Reversible a => a -> WithRev a
withRev x = WithRev (rev x, x)
fromWithRev :: Reversible a => WithRev a -> a
fromWithRev (WithRev (_,x)) = x
instance Reversible a => Reversible (WithRev a) where
rev (WithRev (r,x)) = WithRev (x,r)