diff --git a/music-parts.cabal b/music-parts.cabal
--- a/music-parts.cabal
+++ b/music-parts.cabal
@@ -1,11 +1,11 @@
 
 name:                   music-parts
-version:                1.7.1
+version:                1.7.2
 author:                 Hans Hoglund
 maintainer:             Hans Hoglund
 license:                BSD3
 license-file:           COPYING
-synopsis:               To be written.
+synopsis:               Musical instruments, parts and playing techniques.
 category:               Music
 tested-with:            GHC
 build-type:             Simple
@@ -23,20 +23,51 @@
 library                    
     build-depends:      base                    >= 4 &&   < 5,
                         aeson                   >= 0.7.0.6 && < 1,
-                        lens				            >= 4.3 && < 4.4,
+                        lens				            >= 4.3.3 && < 4.4,
                         semigroups              >= 0.13.0.1 && < 1,
-                        time,
-                        random,
                         semigroupoids,
                         data-default,
                         adjunctions             >= 4.1 && < 5,
-                        roman-numerals
-    exposed-modules:    Music.Parts
+                        roman-numerals,
+                        music-pitch             == 1.7.2
+    exposed-modules:    Data.Semigroup.Option.Instances
+                        
+                        Music.Parts
+                        
+                        Music.Parts.Basic
+                        
+                        -- -- TODO choral voicings etc
+                        -- -- TODO use single type or many? How to do "subtyping"
+                        -- -- Prisms, TFs, something else?
+                        -- 
+                        -- -- TODO require pitch dep
+                        -- Music.Parts.Range
+
+                        Music.Parts.Division
+                        Music.Parts.Subpart
+                        Music.Parts.Solo
+                        
+                        -- TODO "ensembles", essentially echoing the instrument hierarchy but in plural, i.e. (flute :: Instrument, flutes :: Part)
+                        -- TODO write something nice about how division works, why we don't usually export flute1 etc.
                         -- Music.Parts.Strings
                         -- Music.Parts.Woodwind
                         -- Music.Parts.Brass
                         -- Music.Parts.Percussion
                         -- Music.Parts.Rhythm
                         -- Music.Parts.Other
+                        
+                        Music.Parts.Instrument
+                        -- Music.Parts.Instrument.Strings
+                        -- Music.Parts.Instrument.Woodwind
+                        -- Music.Parts.Instrument.Brass
+                        -- Music.Parts.Instrument.Percussion
+                        -- Music.Parts.Instrument.Rhythm
+                        -- Music.Parts.Instrument.Other
+                        
+                        -- TODO a way to classify parts
+                        -- so we know what goes on which staff, what kind of bracket to generate etc
+                        
+                        -- TODO some sub-subdivision (not for player allocation, but hand/finger)
+                        
     hs-source-dirs:     src
     default-language:   Haskell2010
diff --git a/src/Data/Semigroup/Option/Instances.hs b/src/Data/Semigroup/Option/Instances.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Semigroup/Option/Instances.hs
@@ -0,0 +1,49 @@
+
+module Data.Semigroup.Option.Instances 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.Traversable        (traverse)
+import           Data.Typeable
+import           Text.Numeral.Roman      (toRoman)
+
+-- TODO move
+
+instance Num a => Num (Option a) where
+  (+)       = liftA2 (+)
+  (-)       = liftA2 (-)
+  (*)       = liftA2 (*)
+  abs       = fmap abs
+  signum    = fmap signum
+  fromInteger = pure . fromInteger
+instance Integral a => Integral (Option a) where
+  quotRem x y = unzipR $ liftA2 quotRem x y
+  toInteger = toInteger . get where get = (head.toListOf traverse)
+instance Real a => Real (Option a) where
+  toRational = toRational . get where get = (head.toListOf traverse)
+instance Enum a => Enum (Option a) where
+  fromEnum = fromEnum . get where get = (head.toListOf traverse)
+  toEnum = pure . toEnum
+
+-- TODO move
+
+instance Num a => Num (First a) where
+  (+)       = liftA2 (+)
+  (-)       = liftA2 (-)
+  (*)       = liftA2 (*)
+  abs       = fmap abs
+  signum    = fmap signum
+  fromInteger = pure . fromInteger
+instance Integral a => Integral (First a) where
+  quotRem x y = unzipR $ liftA2 quotRem x y
+  toInteger = toInteger . get where get = (head.toListOf traverse)
+instance Real a => Real (First a) where
+  toRational = toRational . get where get = (head.toListOf traverse)
+-- instance Enum a => Enum (First a) where
+  -- toEnum = toEnum . get where get = (head.toListOf traverse)
+  -- fromEnum = pure . fromEnum
diff --git a/src/Music/Parts.hs b/src/Music/Parts.hs
--- a/src/Music/Parts.hs
+++ b/src/Music/Parts.hs
@@ -1,12 +1,11 @@
 
-{-# LANGUAGE
-    GeneralizedNewtypeDeriving,
-    DeriveDataTypeable,
-    TypeFamilies #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeFamilies               #-}
 
 ------------------------------------------------------------------------------------
 -- |
--- Copyright   : (c) Hans Hoglund 2012
+-- Copyright   : (c) Hans Hoglund 2012-2015
 --
 -- License     : BSD-style
 --
@@ -14,7 +13,7 @@
 -- Stability   : experimental
 -- Portability : non-portable (TF,GNTD)
 --
--- Part representation.
+-- Provides various representaitons of musical instruments, subdivisions and parts.
 --
 -------------------------------------------------------------------------------------
 
@@ -22,36 +21,34 @@
         -- * Terminology
         -- $terminology
 
-        
+
         -- * Subparts
-        Division,
-        divisions,
-        getDivision,
-        Subpart,
+        module Music.Parts.Division,
+        module Music.Parts.Subpart,
 
+        -- * Solo vs. tutti
+        module Music.Parts.Solo,
+        
         -- * Instruments
-        Instrument(..),
-        -- TODO hide impl
+        module Music.Parts.Instrument,
 
         -- * Parts
-        Solo(..),
         Part(..),
         divide,
         containsPart,
-        containsSubpart,
         solo,
         tutti,
-        
+
         -- ** Instruments etc
         piccoloFlute,
         flute,
         altoFlute,
         bassFlute,
-        
+
         oboe,
         corAnglais,
         heckelphone,
-        
+
         ebClarinet,
         clarinet,
         aClarinet,
@@ -61,10 +58,10 @@
         altoSax,
         tenorSax,
         baritoneSax,
-        
+
         bassoon,
         contraBassoon,
-        
+
         horn,
         piccoloTrumpet,
         trumpet,
@@ -74,10 +71,10 @@
         trombone,
         bassTrombone,
         tuba,
-        
+
         timpani,
         piano,
-        
+
         celesta,
         glockenspiel,
         vibraphone,
@@ -86,10 +83,10 @@
         xylorimba,
         tubularBells,
         dulcimer,
-        
+
         accordion,
         harmonica,
-        
+
         violin,
         viola,
         cello,
@@ -116,7 +113,7 @@
         trombones,
         trumpets1,
         trumpets2,
-        trombones1, 
+        trombones1,
         trombones2,
         tubas,
 
@@ -137,22 +134,28 @@
 
 
         -- * Basic
-        -- TODO move
-        BasicPart,
+        module Music.Parts.Basic
 
   ) where
 
-import Data.Default
-import Data.Semigroup
-import Data.Typeable
-import Data.Maybe
-import Data.Traversable (traverse)
-import Control.Lens (toListOf)
-import Data.Functor.Adjunction (unzipR)
-import Control.Applicative
-import Text.Numeral.Roman (toRoman)
+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.Basic
+import           Music.Parts.Subpart
+import           Music.Parts.Division
+import           Music.Parts.Solo
+import           Music.Parts.Instrument
+
 {- $terminology
 
 Parts represent a subset of a group of performers. It is mainly used for instrumental and
@@ -170,92 +173,11 @@
     separately, so i.e. /Violin solo II/ (as in a double concerto) is distinct from /Violin II/.
 
 -}
-    
 
 
-{-
-    For each part we want to know:
-        - Classification:
-            - Type: (i.e. woodwind)
-            - Family: (i.e. saxophone)
-            - Range: (i.e. tenor)            
-        - Range (i.e. [c_:e'])
-        - Transposition:
-            sounding = written .+^ transp 
-        - Suggested clefs
--}
 
--- |
--- A division represents a subset of a finite group of performers.
---
--- For example a group may be divided into three equal divisions,
--- designated @(0, 3)@, @(1, 3)@ and @(2, 3)@ respectively.
---
-newtype Division = Division { getDivision :: (Int, Int) }
-    deriving (Eq, Ord, Show)
-instance Default Division where
-    def = Division (0,1)
 
-showDivisionR :: Division -> String
-showDivisionR = toRoman . succ . fst . getDivision
 
-showDivision :: Division -> String
-showDivision  = show . succ . fst . getDivision
-
--- | Get all possible divisions for a given divisor in ascending order.
-divisions :: Int -> [Division]
-divisions n = [Division (x,n) | x <- [0..n-1]]
-
--- | Divide a part into @n@ subparts.
-divide :: Int -> Part -> [Part]
-divide n (Part solo instr subp) = fmap (\x -> Part solo instr (subp <> Subpart [x])) $ divisions n
-
--- |
--- 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 'def') 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
-
--- | An 'Instrument' represents the set of all instruments of a given type.
-data Instrument 
-    = StdInstrument Int
-    | OtherInstrument String
-    deriving (Eq)
-
-instance Show Instrument where      
-    show (StdInstrument x) = fromMaybe "(unknown)" $ gmInstrName x
-    show (OtherInstrument str) = str
-instance Enum Instrument where
-    toEnum = StdInstrument
-    fromEnum (StdInstrument x) = x
-    fromEnum (OtherInstrument _) = error "Instrument.fromEnum used on unknown instrument"
-
-instance Ord Instrument where
-    StdInstrument x `compare` StdInstrument y = gmScoreOrder x `compare` gmScoreOrder y
-
--- | This instance is quite arbitrary but very handy.
-instance Default Instrument where
-    def = StdInstrument 0
-
-data Solo
-    = Solo
-    | Tutti
-    deriving (Eq, Show, Ord, Enum)
-
-instance Default Solo where
-    def = Tutti 
-
-
 -- | A part is a subdivided group of instruments of a given type.
 --
 data Part = Part Solo Instrument Subpart
@@ -285,17 +207,18 @@
 instance Default Part where
   def = Part def def def
 
--- | 
--- @a \`containsPart\` b@ holds if the set of players represented by a is an improper subset of the 
+-- |
+-- @a \`containsPart\` b@ holds if the set of players represented by a is an improper subset of the
 -- set of players represented by b.
 containsPart :: Part -> Part -> Bool
-Part solo1 instr1 subp1 `containsPart` Part solo2 instr2 subp2 = 
-        solo1 == solo2 
+Part solo1 instr1 subp1 `containsPart` Part solo2 instr2 subp2 =
+        solo1 == solo2
         && instr1 == instr2
         && subp1 `containsSubpart` subp2
 
-containsSubpart :: Subpart -> Subpart -> Bool
-Subpart x `containsSubpart` Subpart y = y `Data.List.isPrefixOf` x
+-- | Divide a part into @n@ subparts.
+divide :: Int -> Part -> [Part]
+divide n (Part solo instr subp) = fmap (\x -> Part solo instr (subp <> Subpart [x])) $ divisions n
 
 solo instr      = Part Solo instr def
 tutti instr     = Part Tutti instr def
@@ -398,8 +321,8 @@
 {-
     Score order:
         Woodwinds:      1
-        Brass:          2 
-        Timpani:        3 
+        Brass:          2
+        Timpani:        3
         Percussion:     4
         Keyboard/Harp   5
         Singers         6
@@ -408,7 +331,8 @@
 -}
 gmInstrs :: [(Int, (Int, Double, Int, String))]
 gmInstrs = [
-    (0, (0,  5.0, 0,  "Acoustic Grand Piano")),
+    -- (0, (0,  5.0, 0,  "Acoustic Grand Piano")),
+    (0, (0,  5.0, 0,  "Piano")),
     (1, (0,  5.0, 0,  "Bright Acoustic Piano")),
     (2, (0,  5.0, 0,  "Electric Grand Piano")),
     (3, (0,  5.0, 0,  "Honky-tonk Piano")),
@@ -612,7 +536,7 @@
 
 
 
--- 
+--
 -- data Section
 --     = Woodwind
 --     | Brass
@@ -620,16 +544,16 @@
 --     | Keyboard
 --     | Voices
 --     | Strings
--- 
+--
 -- data VoicePart
 --     = Soprano
 --     | MezzoSoprano
---     | Alto
+--     | Alto
 --     | Tenor
 --     | Baritone
 --     | Bass
--- 
--- 
+--
+--
 -- data GMInstrumentType
 --     = GMPiano
 --     | GMChromaticPercussion
@@ -644,22 +568,22 @@
 --     | GMSynthLead
 --     | GMSynthPad
 --     | GMSynthEffects
---     | GMEthnic
+--     | GMEthnic
 --     | GMPercussive
---     | GMSoundEffects   
+--     | GMSoundEffects
 
 
-    
+
 {-
     ## Terminology: Voice vs Part
-    
+
     A voice is a container of notes (non-overlapping)
-    
+
     A part is an identifier for a set of singers/musicians AND all the notes in a score
     designated for this set of performers. Part extraction has the type
-    
+
         extractParts :: HasPart a => Score a -> [Score a]
-    
+
     I.e. in a score for piano and ensemble, certain notes may be *in the piano part*, i.e.
     designated for the piano. Typically, a part is monophonic or polyphonic. A monophonic
     part is a voice, i.e.
@@ -669,10 +593,10 @@
 
         -- | Fails for polyphonic scores.
         scoreToVoice :: Score a -> Voice (Maybe a)
-    
+
     A polyphonic score contains several voices, i.e.
 
-        scoreToVoices :: Score a -> [Voice (Maybe a)]  
+        scoreToVoices :: Score a -> [Voice (Maybe a)]
 
 
     A part is any type a that satisfies (Ord a, Show a).
@@ -681,8 +605,8 @@
         class HasPartName a where
             partName :: a -> String
             partAbbr :: a -> String
-    
-    
+
+
     These contraints are used when printing scores (to get the order of the parts and their name).
 
         Vln1, Vln2 etc.
@@ -709,57 +633,48 @@
 
     partGroup :: (Part -> [Group] -> a) -> Group -> a
     tree :: (a -> [Tree a] -> b) -> Tree a -> b
-    
-    
+
+
     data MyPart
         = Fl
-        | Sop
+        | Sop
         | Vl1
-        | Vl2
+        | Vl2
         | Pno
 
 -}
 -- TODO move
-instance Num a => Num (Option a) where
-  (+)       = liftA2 (+)
-  (-)       = liftA2 (-)
-  (*)       = liftA2 (*)
-  abs       = fmap abs
-  signum    = fmap signum
-  fromInteger = pure . fromInteger
-instance Integral a => Integral (Option a) where
-  quotRem x y = unzipR $ liftA2 quotRem x y
-  toInteger = toInteger . get where get = (head.toListOf traverse)
-instance Real a => Real (Option a) where
-  toRational = toRational . get where get = (head.toListOf traverse)
-instance Enum a => Enum (Option a) where
-  fromEnum = fromEnum . get where get = (head.toListOf traverse)
-  toEnum = pure . toEnum
-
-instance Num a => Num (First a) where
-  (+)       = liftA2 (+)
-  (-)       = liftA2 (-)
-  (*)       = liftA2 (*)
-  abs       = fmap abs
-  signum    = fmap signum
-  fromInteger = pure . fromInteger
-instance Integral a => Integral (First a) where
-  quotRem x y = unzipR $ liftA2 quotRem x y
-  toInteger = toInteger . get where get = (head.toListOf traverse)
-instance Real a => Real (First a) where
-  toRational = toRational . get where get = (head.toListOf traverse)
--- instance Enum a => Enum (First a) where
-  -- toEnum = toEnum . get where get = (head.toListOf traverse)
-  -- fromEnum = pure . fromEnum
-
-newtype BasicPart = BasicPart { getBasicPart :: Option (First Integer) }
-    deriving (Eq, Ord, Num, Integral, Real, Enum, Typeable, Semigroup, Monoid)
-
-instance Default BasicPart where
-  def = mempty
-
-instance Show BasicPart where
-    show _ = ""
+-- instance Num a => Num (Option a) where
+--   (+)       = liftA2 (+)
+--   (-)       = liftA2 (-)
+--   (*)       = liftA2 (*)
+--   abs       = fmap abs
+--   signum    = fmap signum
+--   fromInteger = pure . fromInteger
+-- instance Integral a => Integral (Option a) where
+--   quotRem x y = unzipR $ liftA2 quotRem x y
+--   toInteger = toInteger . get where get = (head.toListOf traverse)
+-- instance Real a => Real (Option a) where
+--   toRational = toRational . get where get = (head.toListOf traverse)
+-- instance Enum a => Enum (Option a) where
+--   fromEnum = fromEnum . get where get = (head.toListOf traverse)
+--   toEnum = pure . toEnum
+--
+-- instance Num a => Num (First a) where
+--   (+)       = liftA2 (+)
+--   (-)       = liftA2 (-)
+--   (*)       = liftA2 (*)
+--   abs       = fmap abs
+--   signum    = fmap signum
+--   fromInteger = pure . fromInteger
+-- instance Integral a => Integral (First a) where
+--   quotRem x y = unzipR $ liftA2 quotRem x y
+--   toInteger = toInteger . get where get = (head.toListOf traverse)
+-- instance Real a => Real (First a) where
+--   toRational = toRational . get where get = (head.toListOf traverse)
+-- -- instance Enum a => Enum (First a) where
+--   -- toEnum = toEnum . get where get = (head.toListOf traverse)
+--   -- fromEnum = pure . fromEnum
 
 
 piccoloFlutes = tutti piccoloFlute
@@ -1680,4 +1595,4 @@
   <sound id="wood.tonetang"/>
   <sound id="wood.wood-block"/>
 -}
- 
+
diff --git a/src/Music/Parts/Basic.hs b/src/Music/Parts/Basic.hs
new file mode 100644
--- /dev/null
+++ b/src/Music/Parts/Basic.hs
@@ -0,0 +1,44 @@
+
+{-# 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)
+--
+-- Provides various representaitons of musical instruments, subdivisions and parts.
+--
+-------------------------------------------------------------------------------------
+
+module Music.Parts.Basic (
+        BasicPart
+  ) 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.Traversable        (traverse)
+import           Data.Typeable
+import           Text.Numeral.Roman      (toRoman)
+import           Data.Semigroup.Option.Instances
+
+newtype BasicPart = BasicPart { getBasicPart :: Option (First Integer) }
+    deriving (Eq, Ord, Num, Integral, Real, Enum, Typeable, Semigroup, Monoid)
+
+instance Default BasicPart where
+  def = mempty
+
+instance Show BasicPart where
+    show _ = ""
+
diff --git a/src/Music/Parts/Division.hs b/src/Music/Parts/Division.hs
new file mode 100644
--- /dev/null
+++ b/src/Music/Parts/Division.hs
@@ -0,0 +1,75 @@
+
+{-# 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.Division (
+        Division,
+        divisions,
+        getDivision,
+        showDivision,
+        showDivisionR,
+  ) 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)
+
+
+
+{-
+    For each part we want to know:
+        - Classification:
+            - Type: (i.e. woodwind)
+            - Family: (i.e. saxophone)
+            - Range: (i.e. tenor)
+        - Range (i.e. [c_:e'])
+        - Transposition:
+            sounding = written .+^ transp
+        - Suggested clefs
+-}
+
+-- |
+-- A division represents a subset of a finite group of performers.
+--
+-- For example a group may be divided into three equal divisions,
+-- designated @(0, 3)@, @(1, 3)@ and @(2, 3)@ respectively.
+--
+newtype Division = Division { getDivision :: (Int, Int) }
+    deriving (Eq, Ord, Show)
+
+instance Default Division where
+    def = Division (0,1)
+
+-- | Show division in roman numerals.
+showDivisionR :: Division -> String
+showDivisionR = toRoman . succ . fst . getDivision
+
+-- | Show division in ordinary numerals.
+showDivision :: Division -> String
+showDivision  = show . succ . fst . getDivision
+
+-- | Get all possible divisions for a given divisor in ascending order.
+divisions :: Int -> [Division]
+divisions n = [Division (x,n) | x <- [0..n-1]]
+
diff --git a/src/Music/Parts/Instrument.hs b/src/Music/Parts/Instrument.hs
new file mode 100644
--- /dev/null
+++ b/src/Music/Parts/Instrument.hs
@@ -0,0 +1,293 @@
+
+{-# 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.Instrument 
+(
+Instrument(..),
+-- TODO hide impl
+)
+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)
+
+-- | An 'Instrument' represents the set of all instruments of a given type.
+data Instrument
+    = StdInstrument Int
+    | OtherInstrument String
+    deriving (Eq)
+
+instance Show Instrument where
+    show (StdInstrument x) = fromMaybe "(unknown)" $ gmInstrName x
+    show (OtherInstrument str) = str
+instance Enum Instrument where
+    toEnum = StdInstrument
+    fromEnum (StdInstrument x) = x
+    fromEnum (OtherInstrument _) = error "Instrument.fromEnum used on unknown instrument"
+
+instance Ord Instrument where
+    StdInstrument x `compare` StdInstrument y = gmScoreOrder x `compare` gmScoreOrder y
+
+-- | This instance is quite arbitrary but very handy.
+instance Default Instrument where
+    def = StdInstrument 0
+
+
+-- TODO consolidate
+
+gmClef :: Int -> Int
+gmMidiChannel :: Int -> Int
+gmScoreOrder :: Int -> Double
+
+gmMidiChannel = fromMaybe 0 . fmap get . (`lookup` gmInstrs)
+    where get (x,_,_,_) = x
+
+gmScoreOrder = fromMaybe 0 . fmap get . (`lookup` gmInstrs)
+    where get (_,x,_,_) = x
+
+gmClef = fromMaybe 0 . fmap get . (`lookup` gmInstrs)
+    where get (_,_,x,_) = x
+
+
+gmInstrName :: Int -> Maybe String
+gmInstrName = fmap get . (`lookup` gmInstrs)
+    where get (_,_,_,x) = x
+
+-- (midi program, (def midi ch, score order, def clef 0=g/1=c/2=f, name))
+{-
+    Score order:
+        Woodwinds:      1
+        Brass:          2
+        Timpani:        3
+        Percussion:     4
+        Keyboard/Harp   5
+        Singers         6
+        Strings:        7
+        Bass:           8
+-}
+gmInstrs :: [(Int, (Int, Double, Int, String))]
+gmInstrs = [
+    -- (0, (0,  5.0, 0,  "Acoustic Grand Piano")),
+    (0, (0,  5.0, 0,  "Piano")),
+    (1, (0,  5.0, 0,  "Bright Acoustic Piano")),
+    (2, (0,  5.0, 0,  "Electric Grand Piano")),
+    (3, (0,  5.0, 0,  "Honky-tonk Piano")),
+    (4, (0,  5.0, 0,  "Electric Piano 1")),
+    (5, (0,  5.0, 0,  "Electric Piano 2")),
+    (6, (0,  5.0, 0,  "Harpsichord")),
+    (7, (0,  5.0, 0,  "Clavinet")),
+
+    (8, (0,  5.0, 0,  "Celesta")),
+    (9, (0,  5.0, 0,  "Glockenspiel")),
+    (9, (0,  5.0, 0,  "Music Box")),
+    (11, (0,  4.0, 0,  "Vibraphone")),
+    (12, (0,  4.0, 0,  "Marimba")),
+    (13, (0,  4.0, 0,  "Xylophone")),
+    (14, (0,  4.0, 0,  "Tubular Bells")),
+    (15, (0,  4.0, 0,  "Dulcimer")),
+
+    (16, (0,  5.0, 0,  "Drawbar Organ")),
+    (17, (0,  5.0, 0,  "Percussive Organ")),
+    (18, (0,  5.0, 0,  "Rock Organ")),
+    (19, (0,  5.0, 0,  "Church Organ")),
+    (20, (0,  5.0, 0,  "Reed Organ")),
+    (21, (0,  5.0, 0,  "Accordion")),
+    (22, (0,  5.0, 0,  "Harmonica")),
+    (23, (0,  5.0, 0,  "Tango Accordion")),
+
+    (24, (0,  5.0, 0,  "Acoustic Guitar (nylon)")),
+    (25, (0,  5.0, 0,  "Acoustic Guitar (steel)")),
+    (26, (0,  5.0, 0,  "Electric Guitar (jazz)")),
+    (27, (0,  5.0, 0,  "Electric Guitar (clean)")),
+    (28, (0,  5.0, 0,  "Electric Guitar (muted)")),
+    (29, (0,  5.0, 0,  "Overdriven Guitar")),
+    (30, (0,  5.0, 0,  "Distortion Guitar")),
+    (31, (0,  5.0, 0,  "Guitar Harmonics")),
+
+    (32, (0,  8.0, 2,  "Acoustic Bass")),
+    (33, (0,  8.0, 2,  "Electric Bass (finger)")),
+    (34, (0,  8.0, 2,  "Electric Bass (pick)")),
+    (35, (0,  8.0, 2,  "Fretless Bass")),
+    (36, (0,  8.0, 2,  "Slap Bass 1")),
+    (37, (0,  8.0, 2,  "Slap Bass 2")),
+    (38, (0,  8.0, 2,  "Synth Bass 1")),
+    (39, (0,  8.0, 2,  "Synth Bass 2")),
+
+    (40, (12,  7.1, 0,  "Violin")),
+    (41, (13,  7.2, 1,  "Viola")),
+    -- (42, (0,  1.0, 0,  "Cello")),
+    (42, (14,  7.3, 2,  "Violoncello")),
+    (43, (15,  7.4, 2,  "Contrabass")),
+    (44, (0,  7.0, 0,  "Tremolo Strings")),
+    (45, (0,  7.0, 0,  "Pizzicato Strings")),
+    (46, (11,  5.9, 0,  "Orchestral Harp")),
+
+    (47, (8,  2.5, 2,  "Timpani")),
+
+    (48, (0,  7.0, 0,  "String Ensemble 1")),
+    (49, (0,  7.0, 0,  "String Ensemble 2")),
+    (50, (0,  7.0, 0,  "Synth Strings 1")),
+    (51, (0,  7.0, 0,  "Synth Strings 2")),
+
+    (52, (0,  1.0, 0,  "Choir Aahs")),
+    (53, (0,  1.0, 0,  "Voice Oohs")),
+    (54, (0,  1.0, 0,  "Synth Choir")),
+    (55, (0,  1.0, 0,  "Orchestra Hit")),
+
+    (56, (5,  2.2, 0,  "Trumpet in Bb")),
+    (57, (6,  2.3, 2,  "Trombone")),
+    (58, (7,  2.4, 2,  "Tuba")),
+    (59, (0,  2.2, 0,  "Muted Trumpet")),
+    -- (60, (4,  2.1, 0,  "French Horn")),
+    (60, (4,  2.1, 0,  "Horn in F")),
+    (61, (0,  2.0, 0,  "Brass Section")),
+    (62, (0,  2.0, 0,  "Synth Brass 1")),
+    (63, (0,  2.0, 0,  "Synth Brass 2")),
+
+    (64, (0,  1.51, 0,  "Soprano Sax")),
+    (65, (0,  1.52, 0,  "Alto Sax")),
+    (66, (0,  1.53, 0,  "Tenor Sax")),
+    (67, (0,  1.54, 0,  "Baritone Sax")),
+    (68, (1,  1.3, 0,  "Oboe")),
+    (69, (1,  1.4, 0,  "English Horn")),
+    (70, (3,  1.7, 2,  "Bassoon")),
+    (71, (2,  1.6, 0,  "Clarinet in Bb")),
+
+    (72, (0,  1.1, 0,  "Piccolo")),
+    (73, (0,  1.2, 0,  "Flute")),
+    (74, (0,  1.0, 0,  "Recorder")),
+    (75, (0,  1.0, 0,  "Pan Flute")),
+    (76, (0,  1.0, 0,  "Blown bottle")),
+    (77, (0,  1.0, 0,  "Shakuhachi")),
+    (78, (0,  1.0, 0,  "Whistle")),
+    (79, (0,  1.0, 0,  "Ocarina")),
+
+    (80, (0,  1.0, 0,  "Lead 1 (square)")),
+    (81, (0,  1.0, 0,  "Lead 2 (sawtooth)")),
+    (82, (0,  1.0, 0,  "Lead 3 (calliope)")),
+    (83, (0,  1.0, 0,  "Lead 4 (chiff)")),
+    (84, (0,  1.0, 0,  "Lead 5 (charang)")),
+    (85, (0,  1.0, 0,  "Lead 6 (voice)")),
+    (86, (0,  1.0, 0,  "Lead 7 (fifths)")),
+    (87, (0,  1.0, 0,  "Lead 8 (bass + lead)")),
+
+    (88, (0,  1.0, 0,  "Pad 1 (new age)")),
+    (89, (0,  1.0, 0,  "Pad 2 (warm)")),
+    (90, (0,  1.0, 0,  "Pad 3 (polysynth)")),
+    (91, (0,  1.0, 0,  "Pad 4 (choir)")),
+    (92, (0,  1.0, 0,  "Pad 5 (bowed)")),
+    (93, (0,  1.0, 0,  "Pad 6 (metallic)")),
+    (94, (0,  1.0, 0,  "Pad 7 (halo)")),
+    (95, (0,  1.0, 0,  "Pad 8 (sweep)")),
+
+    (96, (0,  1.0, 0,  "FX 1 (rain)")),
+    (97, (0,  1.0, 0,  "FX 2 (soundtrack)")),
+    (98, (0,  1.0, 0,  "FX 3 (crystal)")),
+    (99, (0,  1.0, 0,  "FX 4 (atmosphere)")),
+    (100, (0,  1.0, 0,  "FX 5 (brightness)")),
+    (101, (0,  1.0, 0,  "FX 6 (goblins)")),
+    (102, (0,  1.0, 0,  "FX 7 (echoes)")),
+    (103, (0,  1.0, 0,  "FX 8 (sci-fi)")),
+
+    (104, (0,  1.0, 0,  "Sitar")),
+    (105, (0,  1.0, 0,  "Banjo")),
+    (106, (0,  1.0, 0,  "Shamisen")),
+    (107, (0,  1.0, 0,  "Koto")),
+    (108, (0,  1.0, 0,  "Kalimba")),
+    (109, (0,  1.0, 0,  "Bagpipe")),
+    (110, (0,  1.0, 0,  "Fiddle")),
+    (111, (0,  1.0, 0,  "Shanai")),
+
+    (112, (0,  1.0, 0,  "Tinkle Bell")),
+    (113, (0,  1.0, 0,  "Agogo")),
+    (114, (0,  1.0, 0,  "Steel Drums")),
+    (115, (0,  1.0, 0,  "Woodblock")),
+    (116, (0,  1.0, 0,  "Taiko Drum")),
+    (117, (0,  1.0, 0,  "Melodic Tom")),
+    (118, (0,  1.0, 0,  "Synth Drum")),
+    (119, (0,  1.0, 0,  "Reverse Cymbal")),
+
+    (120, (0,  1.0, 0,  "Guitar Fret Noise")),
+    (121, (0,  1.0, 0,  "Breath Noise")),
+    (122, (0,  1.0, 0,  "Seashore")),
+    (123, (0,  1.0, 0,  "Bird Tweet")),
+    (124, (0,  1.0, 0,  "Telephone Ring")),
+    (125, (0,  1.0, 0,  "Helicopter")),
+    (126, (0,  1.0, 0,  "Applause")),
+    (127, (0,  1.0, 0,  "Gunshot"))
+    ]
+
+gmPerc :: [(Int, String)]
+gmPerc = [
+    (35, "Bass Drum 2"),
+    (36, "Bass Drum 1"),
+    (37, "Side Stick/Rimshot"),
+    (38, "Snare Drum 1"),
+    (39, "Hand Clap"),
+    (40, "Snare Drum 2"),
+    (41, "Low Tom 2"),
+    (42, "Closed Hi-hat"),
+    (43, "Low Tom 1"),
+    (44, "Pedal Hi-hat"),
+    (45, "Mid Tom 2"),
+    (46, "Open Hi-hat"),
+    (47, "Mid Tom 1"),
+    (48, "High Tom 2"),
+    (49, "Crash Cymbal 1"),
+    (50, "High Tom 1"),
+    (51, "Ride Cymbal 1"),
+    (52, "Chinese Cymbal"),
+    (53, "Ride Bell"),
+    (54, "Tambourine"),
+    (55, "Splash Cymbal"),
+    (56, "Cowbell"),
+    (57, "Crash Cymbal 2"),
+    (58, "Vibra Slap"),
+    (59, "Ride Cymbal 2"),
+    (60, "High Bongo"),
+    (61, "Low Bongo"),
+    (62, "Mute High Conga"),
+    (63, "Open High Conga"),
+    (64, "Low Conga"),
+    (65, "High Timbale"),
+    (66, "Low Timbale"),
+    (67, "High Agogô"),
+    (68, "Low Agogô"),
+    (69, "Cabasa"),
+    (70, "Maracas"),
+    (71, "Short Whistle"),
+    (72, "Long Whistle"),
+    (73, "Short Güiro"),
+    (74, "Long Güiro"),
+    (75, "Claves"),
+    (76, "High Wood Block"),
+    (77, "Low Wood Block"),
+    (78, "Mute Cuíca"),
+    (79, "Open Cuíca"),
+    (80, "Mute Triangle"),
+    (81, "Open Triangle")
+    ]
+             
diff --git a/src/Music/Parts/Solo.hs b/src/Music/Parts/Solo.hs
new file mode 100644
--- /dev/null
+++ b/src/Music/Parts/Solo.hs
@@ -0,0 +1,41 @@
+
+{-# 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.Solo (
+          Solo(..),
+  ) 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)
+
+data Solo
+    = Solo
+    | Tutti
+    deriving (Eq, Show, Ord, Enum)
+
+instance Default Solo where
+    def = Tutti
+
diff --git a/src/Music/Parts/Subpart.hs b/src/Music/Parts/Subpart.hs
new file mode 100644
--- /dev/null
+++ b/src/Music/Parts/Subpart.hs
@@ -0,0 +1,55 @@
+
+{-# 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,
+  ) 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
+Subpart x `containsSubpart` Subpart y = y `Data.List.isPrefixOf` x
+
