
I'm wondering if the following problem might reveal a use for Functor or Applicative, or just generally something cooler than I'm doing now. I have a music document as type MusDoc. It has [Part]. Part has [Note]. I have defined them using field names because I am deliberating allowing for this to get more complicated later. The question is about mapping functions over the individual parts. I often find myself wanting to alter or filter all the parts. In the following example I define filterDoc with a couple of helper functions. What I would like to know: is there a cooler way to do this using instances of Functor or something? Defining operators? import Map(Map) import qualified Map as M type PartId = String -- identification of a part in a music document data PartInfo = .. -- ancillary information about a part -- the notes, markings, etc in a part -- It is conceivable other fields could be added later. data Part = Part { partNotes :: [Note] } -- Main music document, consisting of parts. data MusDoc = MusDoc { docParts :: Map PartId (PartInfo,Part) } -- Helper function to map over parts mapParts :: (Part -> Part) -> MusDoc -> MusDoc mapParts g (MusDoc parts) = MusDoc $ M.map (second g) parts -- Filter notes that meet a predicate filterDoc :: (Note -> Bool) -> MusDoc -> MusDoc filterDoc pred doc = mapParts (filterPart pred) doc -- Helper function to filterDoc. filterPart :: (Note -> Bool) -> Part -> Part filterPart pred (Part notes) = Part (filter pred notes)