Hello Mike A pitch class set represents Z12 numbers so I'd define a Z12 number type then store it in a list (if you have need a multiset - duplicates) or Data.Set (if you need uniqueness).
Having a Z12 numeric type isn't the full story, some operations like finding prime form have easier algorithms if they are transitory - i.e. they go out of Z12 to the integers and back. You might want to look at Richard Bird's Sudoko solver for the other problem (slides and the code are a web search away) which takes a very elegant look at a matrix problem. Below is a Z12 modulo I made earlier - adding QuickCheck tests would have been wise (also I seem to remember there is a pitch class package on Hackage): -- Show instance is hand written to escape constructor noise -- It seemed useful to have mod12 as a shortcut - tastes may vary -- The Modulo12 coercion type class is a bit extraneous (fromInteger which suffice). -- I use it to allay coercion warnings in other modules module Z12 ( -- * Integers mod 12 Z12 -- * Integral coercion , Modulo12(..) , mod12 ) where -- Data types newtype Z12 = Z12 Int deriving (Eq,Ord) -------------------------------------------------------------------------------- class Modulo12 a where fromZ12 :: Z12 -> a toZ12 :: a -> Z12 instance Modulo12 Int where fromZ12 (Z12 i) = i toZ12 i = Z12 $ mod i 12 instance Modulo12 Integer where fromZ12 (Z12 i) = fromIntegral i toZ12 i = Z12 $ fromIntegral $ mod i 12 -------------------------------------------------------------------------------- instance Show Z12 where showsPrec p (Z12 i) = showsPrec p i -------------------------------------------------------------------------------- -- Num Instances liftUZ12 :: (Int -> Int) -> Z12 -> Z12 liftUZ12 op (Z12 a) = Z12 $ mod (op a) 12 liftBZ12 :: (Int -> Int -> Int) -> Z12 -> Z12 -> Z12 liftBZ12 op (Z12 a) (Z12 b) = Z12 $ mod (a `op` b) 12 instance Num Z12 where (+) = liftBZ12 (+) (-) = liftBZ12 (-) (*) = liftBZ12 (*) negate = liftUZ12 negate fromInteger i = Z12 $ (fromInteger i) `mod` 12 signum _ = error "Modular numbers are not signed" abs _ = error "Modular numbers are not signed" -------------------------------------------------------------------------------- mod12 :: Integral a => a -> a mod12 = (`mod` 12) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe