module Music.Score.Part (
Part,
SetPart,
HasParts(..),
HasPart(..),
HasPart',
HasParts',
part',
parts',
allParts,
extracted,
extractedWithInfo,
extractPart,
extractParts,
extractPartsWithInfo,
PartT(..),
(</>),
rcat,
) where
import Control.Applicative
import Control.Comonad
import Control.Lens hiding (parts, transform)
import Control.Monad.Plus
import Data.Foldable
import Data.Functor.Couple
import qualified Data.List as List
import qualified Data.List as List
import Data.Ord (comparing)
import Data.PairMonad
import Data.Ratio
import Data.Semigroup
import Data.Traversable
import Data.Typeable
import Music.Dynamics.Literal
import Music.Pitch.Literal
import Music.Score.Ties
import Music.Score.Internal.Util (through)
import Music.Time
import Music.Time.Internal.Transform
type family Part (s :: *) :: *
type family SetPart (b :: *) (s :: *) :: *
class (HasParts s t) => HasPart s t where
part :: Lens s t (Part s) (Part t)
class (Transformable (Part s),
Transformable (Part t)
) => HasParts s t where
parts :: Traversal s t (Part s) (Part t)
type HasPart' a = HasPart a a
type HasParts' a = HasParts a a
part' :: (HasPart s t, s ~ t) => Lens' s (Part s)
part' = part
parts' :: (HasParts s t, s ~ t) => Traversal' s (Part s)
parts' = parts
type instance Part Bool = Bool
type instance SetPart a Bool = a
instance (b ~ Part b, Transformable b) => HasPart Bool b where
part = ($)
instance (b ~ Part b, Transformable b) => HasParts Bool b where
parts = ($)
type instance Part Ordering = Ordering
type instance SetPart a Ordering = a
instance (b ~ Part b, Transformable b) => HasPart Ordering b where
part = ($)
instance (b ~ Part b, Transformable b) => HasParts Ordering b where
parts = ($)
type instance Part () = ()
type instance SetPart a () = a
instance (b ~ Part b, Transformable b) => HasPart () b where
part = ($)
instance (b ~ Part b, Transformable b) => HasParts () b where
parts = ($)
type instance Part Int = Int
type instance SetPart a Int = a
instance HasPart Int Int where
part = ($)
instance HasParts Int Int where
parts = ($)
type instance Part Integer = Integer
type instance SetPart a Integer = a
instance HasPart Integer Integer where
part = ($)
instance HasParts Integer Integer where
parts = ($)
type instance Part Float = Float
type instance SetPart a Float = a
instance HasPart Float Float where
part = ($)
instance HasParts Float Float where
parts = ($)
type instance Part (c,a) = Part a
type instance SetPart b (c,a) = (c,SetPart b a)
type instance Part [a] = Part a
type instance SetPart b [a] = [SetPart b a]
type instance Part (Maybe a) = Part a
type instance SetPart b (Maybe a) = Maybe (SetPart b a)
type instance Part (Either c a) = Part a
type instance SetPart b (Either c a) = Either c (SetPart b a)
type instance Part (Aligned a) = Part a
type instance SetPart b (Aligned a) = Aligned (SetPart b a)
instance HasParts a b => HasParts (Aligned a) (Aligned b) where
parts = _Wrapped . parts
instance HasPart a b => HasPart (c, a) (c, b) where
part = _2 . part
instance HasParts a b => HasParts (c, a) (c, b) where
parts = traverse . parts
instance HasParts a b => HasParts [a] [b] where
parts = traverse . parts
instance HasParts a b => HasParts (Maybe a) (Maybe b) where
parts = traverse . parts
instance HasParts a b => HasParts (Either c a) (Either c b) where
parts = traverse . parts
type instance Part (Event a) = Part a
type instance SetPart g (Event a) = Event (SetPart g a)
instance (HasPart a b) => HasPart (Event a) (Event b) where
part = from event . whilstL part
instance (HasParts a b) => HasParts (Event a) (Event b) where
parts = from event . whilstL parts
type instance Part (Note a) = Part a
type instance SetPart g (Note a) = Note (SetPart g a)
instance (HasPart a b) => HasPart (Note a) (Note b) where
part = from note . whilstLD part
instance (HasParts a b) => HasParts (Note a) (Note b) where
parts = from note . whilstLD parts
allParts :: (Ord (Part a), HasParts' a) => a -> [Part a]
allParts = List.nub . List.sort . toListOf parts
extractPart :: (Eq (Part a), HasPart' a) => Part a -> Score a -> Score a
extractPart = extractPartG
extractPartG :: (Eq (Part a), MonadPlus f, HasPart' a) => Part a -> f a -> f a
extractPartG p x = head $ (\p s -> filterPart (== p) s) <$> [p] <*> return x
extractParts :: (Ord (Part a), HasPart' a) => Score a -> [Score a]
extractParts = extractPartsG
extractPartsG :: (
MonadPlus f, HasParts' (f a), HasPart' a,
Part (f a) ~ Part a, Ord (Part a)
) => f a -> [f a]
extractPartsG x = (\p s -> filterPart (== p) s) <$> allParts x <*> return x
filterPart :: (MonadPlus f, HasPart a a) => (Part a -> Bool) -> f a -> f a
filterPart p = mfilter (\x -> p (x ^. part))
extractPartsWithInfo :: (Ord (Part a), HasPart' a) => Score a -> [(Part a, Score a)]
extractPartsWithInfo x = zip (allParts x) (extractParts x)
extracted :: (Ord (Part a), HasPart' a) => Iso (Score a) (Score b) [Score a] [Score b]
extracted = iso extractParts mconcat
extractedWithInfo :: (Ord (Part a), Ord (Part b), HasPart' a, HasPart' b) => Iso (Score a) (Score b) [(Part a, Score a)] [(Part b, Score b)]
extractedWithInfo = iso extractPartsWithInfo $ mconcat . fmap (uncurry $ set parts')
newtype PartT n a = PartT { getPartT :: (n, a) }
deriving (Eq, Ord, Show, Typeable, Functor,
Applicative, Comonad, Monad, Transformable)
instance Wrapped (PartT p a) where
type Unwrapped (PartT p a) = (p, a)
_Wrapped' = iso getPartT PartT
instance Rewrapped (PartT p a) (PartT p' b)
type instance Part (PartT p a) = p
type instance SetPart p' (PartT p a) = PartT p' a
instance (Transformable p, Transformable p') => HasPart (PartT p a) (PartT p' a) where
part = _Wrapped . _1
instance (Transformable p, Transformable p') => HasParts (PartT p a) (PartT p' a) where
parts = _Wrapped . _1
instance (IsPitch a, Enum n) => IsPitch (PartT n a) where
fromPitch l = PartT (toEnum 0, fromPitch l)
instance (IsDynamics a, Enum n) => IsDynamics (PartT n a) where
fromDynamics l = PartT (toEnum 0, fromDynamics l)
instance Reversible a => Reversible (PartT p a) where
rev = fmap rev
instance Tiable a => Tiable (PartT n a) where
isTieEndBeginning (PartT (_,a)) = isTieEndBeginning a
toTied (PartT (v,a)) = (PartT (v,b), PartT (v,c)) where (b,c) = toTied a
type instance Part (Behavior a) = Behavior (Part a)
type instance SetPart (Behavior g) (Behavior a) = Behavior (SetPart g a)
instance (HasPart a a, HasPart a b) => HasParts (Behavior a) (Behavior b) where
parts = through part part
instance (HasPart a a, HasPart a b) => HasPart (Behavior a) (Behavior b) where
part = through part part
type instance Part (Score a) = Part a
type instance SetPart g (Score a) = Score (SetPart g a)
instance (HasParts a b) => HasParts (Score a) (Score b) where
parts =
_Wrapped . _2
. _Wrapped
. traverse
. from event
. whilstL parts
type instance Part (Voice a) = Part a
type instance SetPart g (Voice a) = Voice (SetPart g a)
instance (HasParts a b) => HasParts (Voice a) (Voice b) where
parts =
_Wrapped
. traverse
. _Wrapped
. whilstLD parts
infixr 6 </>
rcat :: (HasParts' a, Enum (Part a)) => [Score a] -> Score a
rcat = List.foldr (</>) mempty
(</>) :: (HasParts' a, Enum (Part a)) => Score a -> Score a -> Score a
a </> b = a <> moveParts offset b
where
offset = succ $ maximum' 0 $ fmap fromEnum $ toListOf parts a
moveParts :: (Integral b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a
moveParts x = parts %~ (successor x)
moveToPart :: (Enum b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a
moveToPart v = moveParts (fromEnum v)
iterating :: (a -> a) -> (a -> a) -> Int -> a -> a
iterating f g n
| n < 0 = f . iterating f g (n + 1)
| n == 0 = id
| n > 0 = g . iterating f g (n 1)
successor :: (Integral b, Enum a) => b -> a -> a
successor n = iterating pred succ (fromIntegral n)
maximum' :: (Ord a, Foldable t) => a -> t a -> a
maximum' z = option z getMax . foldMap (Option . Just . Max)