music-parts-1.8: src/Music/Parts/Subpart.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
------------------------------------------------------------------------------------
-- |
-- Copyright : (c) Hans Hoglund 2012-2015
--
-- License : BSD-style
--
-- Maintainer : hans@hanshoglund.se
-- Stability : experimental
-- Portability : non-portable (TF,GNTD)
--
-------------------------------------------------------------------------------------
module Music.Parts.Subpart (
Subpart(..),
containsSubpart,
properlyContainsSubpart,
isSubpartOf,
isProperSubpartOf,
) where
import Control.Applicative
import Control.Lens (toListOf)
import Data.Default
import Data.Functor.Adjunction (unzipR)
import qualified Data.List
import Data.Maybe
import Data.Semigroup
import Data.Semigroup.Option.Instances
import Data.Traversable (traverse)
import Data.Typeable
import Text.Numeral.Roman (toRoman)
import Music.Parts.Division
-- |
-- A subpart is a potentially infinite sequence of divisions, each typically
-- designated using a new index type, i.e. @I.1.2@.
--
-- The empty subpart (also known as 'mempty') represents all the players of the group,
-- or in the context of 'Part', all players of the given instrument.
--
newtype Subpart = Subpart [Division]
deriving (Eq, Ord, Default, Semigroup, Monoid)
instance Show Subpart where
show (Subpart ps) = Data.List.intercalate "." $ mapFR showDivisionR showDivision $ ps
where
mapFR f g [] = []
mapFR f g (x:xs) = f x : fmap g xs
containsSubpart :: Subpart -> Subpart -> Bool
containsSubpart = flip isSubpartOf
properlyContainsSubpart :: Subpart -> Subpart -> Bool
properlyContainsSubpart = flip isProperSubpartOf
isSubpartOf :: Subpart -> Subpart -> Bool
Subpart x `isSubpartOf` Subpart y = y `Data.List.isPrefixOf` x
x `isProperSubpartOf` y =
x `isSubpartOf` y && x /= y