content: Mode Space Implementation
  Donya Quick
  Last modified: 19-August-2014
  
  Based on mode space implementation for doctoral thesis.
  
  Major changes since last version:
  - Changed occurrences of AbsPitch to PitchNum to avoid conflict with Euterpea's AbsPitch
  
  > module Kulitta.ChordSpaces.ModeSpace where
  > import Kulitta.ChordSpaces.OPTIC
  > import Kulitta.QuotientSpaces
  > import Data.List
  > import System.Random
  
  > type AbsMode = [PitchNum]
  > type JChord = (AbsChord, AbsMode)
  
  > modeEq :: EqRel JChord
  > modeEq a b = normO(snd a) == normO(snd b)
  
  The set of all modes rooted at 0
  
  > allModes :: [AbsMode]
  > allModes = allRots [0,2,4,5,7,9,11] where
  >     allRots x = take 7 $ iterate doRot x
  >     doRot x = normO $ normT (tail x ++ [head x + 12])
  
  > allKModes = map (normO . uncurry t) [(k,m) | k<-[0..11], m<-allModes]
  
  > allJChords :: [JChord]
  > allJChords = 
  >     let masks = makeRange (take 7 $ repeat (0,1)) 
  >         applyMask (f, m) = (map snd $ filter ((>0).fst) $ zip f m, m)
  >     in  map applyMask [(f,m) | f<-masks, m<-allKModes]
  
  > modeSpace :: QSpace JChord
  > modeSpace = allJChords // modeEq
  
  This version allows more efficient specification of modal space 
  involving only chords fitting certain templates. 
  
  > modeSpace' :: [[Int]] -> QSpace JChord
  > modeSpace' temps = filter (f temps) allJChords // modeEq where
  >     f temps (c,m) = elem c $ map (toTemp m) temps
  >     toTemp m t = map (m!!) t
  
  For example, to get only triads with the root, third, and fifth,
  one would use: modeSpace' [[0,2,4]].
  
  
  
  
  
  
  