[Haskell-cafe] music-related problem

erik flister erik.flister at gmail.com
Sun Jul 4 20:15:28 EDT 2010

> That's what I want to do. I'm asking about a good way to write the
> algorithm that traverses the notes and reconstructs the document with the
> correct duration in each note.

why isn't this as simple as foldr'ing something like this over the xml notes
(assuming monophony and that they are listed in order of start time)?

readNote xmlNote nl | null nl      = mkNote : []
                    | (n:ns) <- nl =
 if not $ followedByTie xmlNote then mkNote : nl
                                else n {dur = dur n `durPlus` xdur} : ns
 where xdur   = getDur xmlNote
       mkNote = Note {dur = xdur}

durPlus would be fun to implement for the NoteDur class...  is polyphony the
crux of the problem?  if so, then the simple list data structure shown here
won't work, you need a graph, as mentioned by serguey.  but the idea is the

> Actually, I don't want to lose information about the original form of the
> document, so I have separate fields for the duration of the graphical single
> note, and the duration of the tied chain.

i think that's asking for trouble -- i would recompute the ties myself --
it's a matter of engraving style what the rules about ties are anyway.  if
you insist on being faithful to the input's ties, i would add some sort of
reference to the note tiedTo (and maybe the note tiedFrom) to the Note
record, but that means giving each note some sort of name or key or index.

> Actually, it is better to speak of the end time than the duration, because
> what units do you put duration in? Beats?

see my EDSL.  duration is in units like (Dotted $ Triplet Half), which is
the natural musician's (and engraver's) unit.  the time signature specifies
the number of beats per quarter.  if you store end location instead, you'll
need to have some (start -> end -> duration) which has to know how to cross
measure boundaries, which is unnecessarily complex, especially with changing
time signatures.

> The time signature could be changing measure to measure.

yeah i don't deal with changing time signatures or tempos.  but it's easy to
see how to handle time signature changes, since that can only change at a
measure boundary:

data Measure = Measure {
    notes :: [Note]
  , timeSig :: TimeSig

tempo changes are trickier (esp if allowed mid-measure?), but only matters
if you need to resolve onsets/durations/offsets to real-world time.  still
looks straightforward...

> I use Rational so there is no worry about precision of Floats.

forall x. (Real x, Fractional x) => x if you're picky.  Rationals are not
locally compact and are not a complete metric -- almost all Reals are
irrational.  :)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20100704/93cc6cef/attachment.html

More information about the Haskell-Cafe mailing list