moduleHarmTrace.Matching.HChord(HChord,Sim,toHChords)whereimportHarmTrace.Base.MusicRepimportHarmTrace.Models.ChordTokensimportHarmTrace.Matching.SimimportHarmTrace.HAnTree.HAnimportHarmTrace.HAnTree.Tree-- represents a very simple chord, only major and minor and a root scaledegreedataHChord=HChord{deg::!Int-- I = 0, IIb = 1 ... VII = 11,clss::!ClassType-- MajClass | MinClass | DomClass | ..,func::!HFunc,prep::!Prep,trns::!Trans}instanceSimHChordwhere{-# INLINE sim #-}sim(HChordrct_fcprtr)(HChordr2ct2_fc2pr2tr2)|r==r2&&ct==ct2=2+simprpr2+simtrtr2|otherwise=-1instanceShowHChordwhereshow(HChordrctfcprtr)=showfc++':':showpr++':':showtr++':':show(toScaleDegree(Key(NoteNothingC)MajMode)(toRootr))++showcttoHChords::TreeHAn->[HChord]toHChordst=getHAnundefinedHChordt-- getHAn also samples/replicates the chords based on their duration in beatsgetHAn::HChord->TreeHAn->[HChord]getHAnc(Nodeh@(HAnChordct)[]_)-- there might be inserted chords|null(chordsct)=[]-- ignore them in the matching process|otherwise=letc'=updatech-- ignore func when the chord is deletedc''=ifstatusct==Deletedthenc'{trns=NoTrans}elsec'inreplicate(durct)c''-- in replicate ((dur ct) `div1` 2) c''getHAnc(Nodehcs_)=letc'=updatechinconcatMap(getHAnc')csupdate::HChord->HAn->HChordupdatehc(HAn__)=hcupdatehc(HAnFuncf)=hc{func=f}updatehc(HAnTranst)=hc{trns=t}updatehc(HAnPrepp)=hc{prep=p}updatehc(HAnChordc)=hc{deg=toSemitone$rootc,clss=classTypec}undefinedHChord::HChordundefinedHChord=HChord(-1::Int)(MajClass::ClassType)(P::HFunc)NoPrepNoTrans