On Tue, Jul 16, 2013 at 5:20 PM, Richard A. O'Keefe <o...@cs.otago.ac.nz> wrote: > Brian Marick sent me a couple of his stickers. > The one I have on my door reads "to be less wrong than yesterday". > The other one I keep free to bring out and wave around: > > "An example would be handy about now."
Just by coincidence, I recently wrote this: midi_to_pitch :: TheoryFormat.Format -> Maybe Pitch.Key -> Pitch.NoteNumber -> Maybe Theory.Pitch midi_to_pitch fmt key nn = either (const Nothing) Just $ TheoryFormat.fmt_to_absolute fmt key pitch where -- TODO if I support frac I can use this for twelve too (semis, _frac) = properFraction (Pitch.nn_to_double nn) Theory.Pitch oct (Theory.Note pc accs) = Theory.semis_to_pitch_sharps TheoryFormat.piano_layout (Theory.nn_to_semis semis) (oct1, pc1) = adjust_octave (TheoryFormat.fmt_pc_per_octave fmt) 7 oct pc pitch = Theory.Pitch oct1 (Theory.Note pc1 accs) kbd_to_pitch :: Theory.PitchClass -> Pitch.Octave -> Theory.PitchClass -> Theory.Accidentals -> Theory.Pitch kbd_to_pitch pc_per_octave oct pc accidentals = Theory.Pitch (add_oct + oct1) (Theory.Note pc2 accidentals) where (oct1, pc1) = adjust_octave pc_per_octave 10 oct pc -- If the scale is shorter than the kbd, go up to the next octave on the -- same row. (add_oct, pc2) = pc1 `divMod` pc_per_octave adjust_octave :: Theory.PitchClass -> Theory.PitchClass -> Pitch.Octave -> Theory.PitchClass -> (Pitch.Octave, Theory.PitchClass) adjust_octave pc_per_octave kbd_per_octave oct pc = (oct2, pc2) where rows = ceiling $ fromIntegral pc_per_octave / fromIntegral kbd_per_octave (oct2, offset) = oct `divMod` rows pc2 = offset * kbd_per_octave + pc Also, fragments like this are fairly common: Right pitch_ -> let pitch = pitch_ { Theory.pitch_note = (Theory.pitch_note pitch_) { Theory.note_accidentals = 0 } } accs = Theory.pitch_accidentals pitch_ in Just $ ScaleDegree.scale_degree_just (smap_named_intervals smap) (smap_accidental_interval smap ^^ accs) (pitch_nn smap pitch) (pitch_note fmt pitch) My convention is when I have a a series of transformations that have to be named for whatever reason, I suffix with numbers. When I have a function argument (or case-bound variable as in this case) that has to be "cooked" before it can be used, I suffix it with _. That way code inside the function is not likely to accidentally use the un-cooked version (this has happened when I left the uncooked version normal and suffixed the cooked version with a 1 or something). In monadic style, I use 'x <- return $ f x' a fair amount. I'm just sending this to point out that it actually is a real issue. And on the odd chance that someone wants to tell me that I'm doing it wrong and here's a better idea :) I'm not about to import Monad.State and wrap the whole expression in a state call just to replace one or two variables, both the syntactic overhead and the "conversion" overhead make it not worth it. However, I'm also not agitating for a non-recursive let, I think that ship has sailed. Besides, if it were added people would start wondering about non-recursive where, and it would introduce an exception to haskell's pretty consistently order-independent declaration style. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe