AcommoninstanceofMusic.T.Itrepresentsrhythmicmusic,thatismelodiesplusdrums.Thetypesformelodyinstrumentsanddrumscanbechosenfreely.Theymaybeplainstrings,enumerationsorparametrizedinstrumentdescriptions.\begin{haskelllisting}>moduleHaskore.Music.Rhythmic>(T,Note(..),NoteBody(..),>maybeInstrument,>noteFromAttrs,noteFromStdMelodyNote,noteFromMelodyNote,>fromStdMelody,fromMelodyNullAttr,fromMelody,>>bn,wn,hn,qn,en,sn,tn,sfn,>dwn,dhn,dqn,den,dsn,dtn,>ddhn,ddqn,dden,>bnr,wnr,hnr,qnr,enr,snr,tnr,sfnr,>dwnr,dhnr,dqnr,denr,dsnr,dtnr,>ddhnr,ddqnr,ddenr,>line,chord,changeTempo,transpose,phrase,>(Music.+:+),(Music.=:=),Dur,>>PhraseAttribute(..),Dynamic(..),>Tempo(..),Articulation(..),Ornament(..),NoteHead(..),>accent,crescendo,diminuendo,loudness1,>ritardando,accelerando,staccato,legato,>defltLegato,defltStaccato,>defltAccent,bigAccent)where>importqualifiedHaskore.Basic.PitchasPitch>importHaskore.Basic.Durationhiding(T)>importHaskore.Musichiding(T,partitionMaybe)>importqualifiedHaskore.MusicasMusic>importqualifiedHaskore.MelodyasMelody>importqualifiedHaskore.Melody.StandardasStdMelody>importqualifiedData.Accessor.BasicasAccessor>importqualifiedData.Record.HTasRecord>importData.Ord.HT(comparing,)>dataNotedruminstr=>Note{velocity::Rational,>body::NoteBodydruminstr}>deriving(Show,Eq)\end{haskelllisting}Anoteofarhythmicmusiccanbeeitheratoneofamelodyinstrumentoradrum.Everyeffect,whichhasnopitch,isconsideredasadrum.Naturally\code{Tone}sareaffectedbytranspositionwhereas\code{Drum}sarenot.\begin{haskelllisting}>dataNoteBodydruminstr=>Tone{instrument::instr,>pitch::Pitch.T}>|Drum{drum::drum}>deriving(Show,Eq,Ord)>-- this order is just for the old test cases which rely on it>instance(Ordinstr,Orddrum)=>Ord(Notedruminstr)where>compare=>Record.compare>[comparingbody,>comparingvelocity]>typeTdruminstr=Music.T(Notedruminstr)>maybeInstrument::NoteBodydruminstr->Maybeinstr>maybeInstrument(Toneinstr_)=Justinstr>maybeInstrument(Drum_)=Nothing\end{haskelllisting}Arhythmicmusiccanbecreatedbyassigninganinstrumenttoamelody.Thefunction\function{fromStdMelody}doesthiswhilepreservingcommonnoteattributes,andthefunction\function{fromMelodyNullAttr}ignoresthenoteattributes.Thisisusefulincasenoadditionalattributesareneeded.Inthiscasethe\type{attr}typevariablecanbethenulltype\type{()}.\begin{haskelllisting}>noteFromAttrs::StdMelody.NoteAttributes->>NoteBodydruminstr->Notedruminstr>noteFromAttrsnas=>Note(Accessor.getStdMelody.velocity1nas)>noteFromStdMelodyNote::instr->StdMelody.Note->Notedruminstr>noteFromStdMelodyNoteinstr(Melody.Notenasp)=>noteFromAttrsnas(Toneinstrp)>noteFromMelodyNote::>(attr->(Rational,instr))->>Melody.Noteattr->Notedruminstr>noteFromMelodyNoteattrToInstr(Melody.Notexp)=>let(vel,instr)=attrToInstrx>inNotevel(Toneinstrp)>fromStdMelody::instr->StdMelody.T->Tdruminstr>fromStdMelodyinstr=Music.mapNote(noteFromStdMelodyNoteinstr)>-- | ignores the note attributes>fromMelodyNullAttr::instr->Melody.T()->Tdruminstr>fromMelodyNullAttrinstr=>fromStdMelodyinstr.StdMelody.fromMelodyNullAttr>-- fromMelody (const (1,instr))>fromMelody::>(attr->(Rational,instr))->Melody.Tattr->Tdruminstr>fromMelodyattrToInstr=>Music.mapNote(noteFromMelodyNoteattrToInstr)\end{haskelllisting}