l3      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF G H I J K L M NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz { | } ~        !"#$%&'()*+,-./012  Haskell 98stablehaskell@henning-thielemann.de 3)A list of elements of alternating types, >where the type of the beginning and the end element is equal, namely b.  Example: 1 :> 'a' :  2 : 'b' :  3 : End 45)A list of elements of alternating types, Fwhere the types of the beginning and the end element are independent, namely a at the beginning, b at the end.  Example: 1 :> 'a' :  2 : 'b' :< End 6789:; 3456789:; 3445766789:; <>Given the time fraction that remains from the preceding event !and the current time difference, (evaluate an integer time difference and the remaining fractional part. .If we would simply map Time to integer values #with respect to the sampling rate, 'then rounding errors would accumulate. =>?@<=>?@<=>?@  Haskell 98stablehaskell@henning-thielemann.de8ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq3Currently it is not checked, whether n is too big. Don'#t rely on the current behaviour of  splitAt n x for  n > length x. rstuvwx/AHIJNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx/AHIJNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx Haskell 98stablehaskell@henning-thielemann.de.y,The constructor is only exported for use in Data.AlternatingList.List.Mixed. z{|}~,yz}~,yzz}~ Haskell 98stablehaskell@henning-thielemann.de Haskell 98stablehaskell@henning-thielemann.de Haskell 98stablehaskell@henning-thielemann.de+,+ Haskell 98stablehaskell@henning-thielemann.de    Haskell 98stablehaskell@henning-thielemann.de    Haskell 98stablehaskell@henning-thielemann.de          Haskell 98stablehaskell@henning-thielemann.de !"#$%&'()*+,-./0123456789:; !"#$%&'()*+,-./0123456789:;243 "!#$%&'()*+,-./0156789:; !"#$%&'()*+,-./0123456789:; Haskell 98stablehaskell@henning-thielemann.de<=>?@A4Duration of an empty event list is considered zero.  However, I'm not sure if this is sound. BCDE<=>?@ABCDE<=>?@ABCDE Haskell 98stablehaskell@henning-thielemann.deFGHIJKLMFGHIJKLMFGHIJKLM  Haskell 98stablehaskell@henning-thielemann.deGHIJKLMGHIJKLM Haskell 98stablehaskell@henning-thielemann.de,NOPQRSTUVWXYZ[\]^_`ab2Check whether time values are in ascending order. !The list is processed lazily and ?times that are smaller than there predecessors are replaced by . If you would remove the  times from the resulting list $the times may still not be ordered. E.g. consider the time list [0,3,1,2] cdefghij,Since we need it later for MIDI generation, Bwe will also define a slicing into equivalence classes of events. kQWe will also sometimes need a function which groups events by equal start times. KThis implementation is not so obvious since we work with time differences. AThe criterion is: Two neighbouring events start at the same time ,if the second one has zero time difference. lmWill fail on infinite lists. no4Apply a function to the lists of coincident events. p$ sorts a list of coinciding events, =that is all events but the first one have time difference 0. p' sorts all coinciding events in a list Athus yielding a canonical representation of a time ordered list. qr The first important function is r Awhich merges the events of two lists into a new time order list. s Note that r/ compares entire events rather than just start >times. This is to ensure that it is commutative, a desirable )condition for some of the proofs used in secref{equivalence}. 7It is also necessary to assert a unique representation 7of the performance independent of the structure of the ' Music.T note'. PThe same function for inserting into a time ordered list with a trailing pause. HThe strictness annotation is necessary for working with infinite lists. OHere are two other functions that are already known for non-padded time lists. tThe final critical function is insert, which inserts an event 1into an already time-ordered sequence of events. 1For instance it is used in MidiFiles to insert a NoteOff event into a list of NoteOn and NoteOff events. uv1Move events towards the front of the event list. =You must make sure, that no event is moved before time zero. "This works only for finite lists. wx?Here are some functions for discretizing the time information. 1When converting the precise relative event times $to the integer relative event times 4we have to prevent accumulation of rounding errors. 1We avoid this problem with a stateful conversion -which remembers each rounding error we make. :This rounding error is used to correct the next rounding. /Given the relative time and duration of a note  the function discretizeEventM creates a State *which computes the rounded relative time. -It is corrected by previous rounding errors. =The resulting event list may have differing time differences (which were equal before discretization, ;but the overall timing is uniformly close to the original. y6<=>?@ABCDENOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy6<NPOST=>QRUVXWA?@YZ[\]^_`arstuvwBehijcdfgpqknoCDExyblm,NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy  Haskell 98stablehaskell@henning-thielemann.de+z{|}~4Apply a function to the lists of coincident events. $ sorts a list of coinciding events, =that is all events but the first one have time difference 0. ' sorts all coinciding events in a list Athus yielding a canonical representation of a time ordered list. 1Move events towards the front of the event list. =You must make sure, that no event is moved before time zero. "This works only for finite lists. ,Fz{|}~,Fz{}|~+z{|}~ Haskell 98stablehaskell@henning-thielemann.de9IKeep only events that match a predicate while preserving absolute times. *Adds times in a left-associative fashion. ,Use this if the time is a strict data type.  Using a classification function Ewe splice the event list into lists, each containing the same class. $Absolute time stamps are preserved. )Group events that have equal start times !(that is zero time differences). Reverse to collectCoincident:  Turn each body into a separate event. * xs == flatten (collectCoincident xs) 4Apply a function to the lists of coincident events. $ sorts a list of coinciding events, =that is all events but the first one have time difference 0. ' sorts all coinciding events in a list Athus yielding a canonical representation of a time ordered list. DThis function merges the events of two lists into a new event list.  Note that 6 compares entire events rather than just start times. *This is to ensure that it is commutative, #one of the properties we test for.  is like , but does not simply use the methods of the  class )but allows a custom comparison function. 8 inserts an event into an event list at the given time. 1Move events towards the front of the event list. =You must make sure, that no event is moved before time zero. "This works only for finite lists.  We provide  and ( for discretizing the time information. 1When converting the precise relative event times $to the integer relative event times 4we have to prevent accumulation of rounding errors. 1We avoid this problem with a stateful conversion -which remembers each rounding error we make. :This rounding error is used to correct the next rounding. 1Given the relative time and duration of an event  the function  floorDiff creates a Control.Monad.State.State *which computes the rounded relative time. -It is corrected by previous rounding errors. =The resulting event list may have differing time differences (which were equal before discretization, ;but the overall timing is uniformly close to the original. We use  floorDiff rather than = ;in order to compute exclusively with non-negative numbers. DWe tried hard to compute everything with respect to relative times. 0However sometimes we need absolute time values. 998 Haskell 98stablehaskell@henning-thielemann.deASort coincident elements.  The first important function is  Awhich merges the events of two lists into a new time order list.  Note that / compares entire events rather than just start >times. This is to ensure that it is commutative, a desirable 0condition for some of the proofs used in Haskore/section equivalence. 7It is also necessary to assert a unique representation Bof the event list independent of the structure of the event type. PThe same function for inserting into a time ordered list with a trailing pause. 1Move events towards the front of the event list. =You must make sure, that no event is moved before time zero. "This works only for finite lists. Like $ but restricts the look-ahead time. For $moveForwardRestricted maxTimeDiff xs 6all time differences (aka the moveForward offsets) in xs must be at most  maxTimeDiff. 2With this restriction the function is lazy enough #for handling infinite event lists. However the larger  maxTimeDiff' the more memory and time is consumed. currently only for testing currently only for testing currently only for testing MMerge several event lists respecting the start time of the outer event list.  and  are essentially the same.  must use % in order to work on infinite lists, 'however if there are many empty lists, <summing of their durations will be done from right to left, which is inefficient. IThus we detect subsequent empty lists and merge them from left to right. Uses sharing. *If there is an event at the cutting time, +this event is returned in the suffix part. That is splitAtTime t0 (t0 . x . t1 ./ empty) ==  (pause t0, 0 . x . t1 ./ empty)      Analogously to the  /  pair we have to versions of , /where the clever implementation sums up pauses from the beginning to the end. *Adds times in a left-associative fashion. ,Use this if the time is a strict data type. +Adds times in a right-associative fashion. <Use this if the time is a data type like lazy Peano numbers or Numeric.NonNegative.Chunky. Cf.  ,Since we need it later for MIDI generation, Bwe will also define a slicing into equivalence classes of events. E      E       ?      Haskell 98stablehaskell@henning-thielemann.de  2  2    Haskell 98stablehaskell@henning-thielemann.de !"#$%&*This is not a good name, expect a change. '*This is not a good name, expect a change. ()*!"#$%&'()*!"#$%&'()* !"#$%&'()* Haskell 98stablehaskell@henning-thielemann.de+,-./012 +,-./012 +-,./012+,-./012 !"#$%&'()*+,-./0123456789:;<+=>?@ABCDEFGEF563-HIJK"#&'*>?@ABCD/012789:;<L+=MNOPQRSTU.VWXYZ[\]^_` a b 1 2 3 A B C E 5 6   7 8 9  : ; < + M N O P R S . V W X Y Z [ \ ]  H I ^ - _ `>?@ABCDEF/012356cde789:;<+=MNOPQRGS.VWXYZ[\]HI^-_`fgab123ABCEDF56cde789:;<WXYZ[h]ijklmnoHpIqrst^SVMNOuPQvRwx_`fgyz{|}JK~rstyz !$%      R     / 0   7 > @ ? A B C E D F + = w  H I x 7@AB+wxzyCDEFHI)\event-list-0.1 Data.EventList.Relative.BodyBody Data.EventList.Relative.TimeBody!Data.EventList.Relative.MixedBody Data.EventList.Relative.BodyTime Data.EventList.Relative.TimeTime!Data.EventList.Relative.MixedTime!Data.EventList.Relative.TimeMixed Data.EventList.Absolute.TimeBody Data.EventList.Absolute.TimeTime!Data.EventList.Absolute.TimeMixedData.AlternatingList.CustomData.EventList.Utility#Data.AlternatingList.List.Disparate!Data.AlternatingList.List.Uniform'Data.EventList.Relative.BodyBodyPrivateData.AlternatingList.List.Mixed'Data.EventList.Relative.TimeBodyPrivate'Data.EventList.Relative.BodyTimePrivate'Data.EventList.Relative.TimeTimePrivate'Data.EventList.Absolute.TimeBodyPrivate'Data.EventList.Absolute.TimeTimePrivateTconcatMapMonoidtraversemapMmapTimeL mapTimeHead mapTimeTailappendconsBodyconsTime viewTimeL viewBodyL viewTimeR viewBodyR switchTimeL switchBodyL switchTimeR switchBodyRmapTimeR mapTimeLast mapTimeInitfoldr forceTimeHeaddelayflatten fromPairList toPairList getBodiesgetTimesduration durationRmapBodymapTime traverse_ traverseBody traverseTimemapM_mapBodyMmapTimeM foldrPairemptynull singletonconssnocviewLviewRswitchLswitchRspanconcatcyclesnocBodysnocTime checkTimesfiltermapMaybe catMaybes partitionpartitionMaybeslicecollectCoincidentcollectCoincidentFoldrcollectCoincidentNonLazy mapCoincident normalize isNormalizedmergemergeByinsertinsertBy moveForward decreaseStart discretizeresamplepauseisPause zipWithBody zipWithTimeunziptoAbsoluteEventListfromAbsoluteEventListpad moveBackwardmoveForwardRestrictedmoveForwardRestrictedBymoveForwardRestrictedByStrictmoveForwardRestrictedByQueuearrange arrangeBy concatNaive cycleNaive splitAtTimetakeTimedropTime catMaybesRpartitionMaybeRfoldlreverse.//.mapBodyL mapBodyHead mapBodyTailmapBodyR mapBodyLast mapBodyInit appendBodyEndprependBodyEndUniform:< DisparateEnd:> mapDisparate mapUniformfoldrDisparate foldrUniform roundDiff' roundDiff floorDiffbeforeByConsdeconsPair pairFirst pairSecondformatlift mapPairFirst mapPairSecondmapmapFirst mapSecond zipWithFirst zipWithSecond concatMonoidsequence sequence_ traverseFirsttraverseSecond getFirsts getSecondslength genericLengthmapHeadmapLastsplitAttakedropgenericSplitAt genericTake genericDrop spanFirst spanSecond_leaddisp fromFirstListfromSecondListfromEitherList isSingleton mapSecondHeadforceSecondHead filterFirst filterSecondpartitionFirstpartitionSecondpartitionMaybeFirstpartitionMaybeSecondpartitionEitherFirstpartitionEitherSecondunzipEitherFirstunzipEitherSecondcatMaybesFirstcatMaybesSecond$**liftMunlift consFirst consSecond snocFirst snocSecond viewFirstL viewSecondL viewFirstR viewSecondR switchFirstL switchSecondL switchFirstR switchSecondR mapFirstL mapFirstHead mapFirstTail mapSecondL mapSecondTail mapFirstR mapFirstLast mapFirstInit mapSecondR mapSecondLast mapSecondInitreverseUniformreverseDisparateappendUniformUniformappendDisparateUniformappendUniformDisparateconcatDisparate concatUniformsplitAtDisparateUniformsplitAtUniformDisparatesplitAtUniformUniform takeDisparate takeUniform dropDisparate dropUniform$~*liftA$*~ appendAlt appendSwitch$~~$~$*baseGHC.Err undefined Data.Listsort partitionRec GHC.ClassesOrdltMaybesplitAtTimeAux