packages feed

interval-algebra 2.0.2 → 2.1.0

raw patch · 13 files changed

+2016/−485 lines, 13 filesdep ~timenew-component:exe:tutorialPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: time

API changes (from Hackage documentation)

- IntervalAlgebra.Core: enclose :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: instance GHC.Base.Functor IntervalAlgebra.Core.Interval
- IntervalAlgebra.Core: instance GHC.Classes.Ord a => IntervalAlgebra.Core.Intervallic IntervalAlgebra.Core.Interval a
- IntervalAlgebra.IntervalDiagram: instance GHC.Base.Functor IntervalAlgebra.IntervalDiagram.IntervalText
- IntervalAlgebra.IntervalDiagram: instance GHC.Classes.Ord a => IntervalAlgebra.Core.Intervallic IntervalAlgebra.IntervalDiagram.IntervalText a
- IntervalAlgebra.IntervalUtilities: filterEnclose :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: instance GHC.Classes.Ord a => GHC.Base.Semigroup (IntervalAlgebra.IntervalUtilities.Box (IntervalAlgebra.Core.Interval a))
- IntervalAlgebra.PairedInterval: instance Data.Bifunctor.Bifunctor IntervalAlgebra.PairedInterval.PairedInterval
- IntervalAlgebra.PairedInterval: instance GHC.Base.Functor (IntervalAlgebra.PairedInterval.PairedInterval b)
- IntervalAlgebra.PairedInterval: instance GHC.Classes.Ord a => IntervalAlgebra.Core.Intervallic (IntervalAlgebra.PairedInterval.PairedInterval b) a
- IntervalAlgebra.RelationProperties: prop_enclose_predicate :: (IntervalRelationProperties a b, Ord a) => Interval a -> Interval a -> Property
+ IntervalAlgebra.Core: encloses :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: fromEnumInterval :: (Enum a, Intervallic i) => i a -> i Int
+ IntervalAlgebra.Core: instance IntervalAlgebra.Core.Intervallic IntervalAlgebra.Core.Interval
+ IntervalAlgebra.Core: toEnumInterval :: (Enum a, Intervallic i) => i Int -> i a
+ IntervalAlgebra.IntervalDiagram: class Pretty a
+ IntervalAlgebra.IntervalDiagram: instance IntervalAlgebra.Core.Intervallic IntervalAlgebra.IntervalDiagram.IntervalText
+ IntervalAlgebra.IntervalDiagram: pretty :: Pretty a => a -> Doc ann
+ IntervalAlgebra.IntervalDiagram: prettyList :: Pretty a => [a] -> Doc ann
+ IntervalAlgebra.IntervalDiagram: standardExampleDiagram :: (Num a, Ord a, Enum b, IntervalSizeable a b) => [(Interval a, String)] -> [([Interval a], String)] -> Either IntervalDiagramParseError (IntervalDiagram a)
+ IntervalAlgebra.IntervalUtilities: combineIntervalsFromSorted :: (Applicative f, Ord a, Intervallic i, Monoid (f (Interval a)), Foldable f) => f (i a) -> f (Interval a)
+ IntervalAlgebra.IntervalUtilities: combineIntervalsFromSortedL :: forall a i. (Ord a, Intervallic i) => [i a] -> [Interval a]
+ IntervalAlgebra.IntervalUtilities: filterEncloses :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.PairedInterval: instance IntervalAlgebra.Core.Intervallic (IntervalAlgebra.PairedInterval.PairedInterval b)
+ IntervalAlgebra.RelationProperties: prop_encloses_predicate :: (IntervalRelationProperties a b, Ord a) => Interval a -> Interval a -> Property
- IntervalAlgebra.Arbitrary: arbitraryWithRelation :: forall i a b. (IntervalSizeable a b, Intervallic i a, Arbitrary (i a)) => i a -> Set IntervalRelation -> Gen (Maybe (i a))
+ IntervalAlgebra.Arbitrary: arbitraryWithRelation :: forall i a b. (IntervalSizeable a b, Intervallic i, Arbitrary (i a)) => i a -> Set IntervalRelation -> Gen (Maybe (i a))
- IntervalAlgebra.Core: (<|>) :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a) -> ComparativePredicateOf2 (i0 a) (i1 a) -> ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: (<|>) :: (Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a) -> ComparativePredicateOf2 (i0 a) (i1 a) -> ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: after :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: after :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: before :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: before :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: begin :: Intervallic i a => i a -> a
+ IntervalAlgebra.Core: begin :: Intervallic i => i a -> a
- IntervalAlgebra.Core: beginervalFromEnd :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> Interval a
+ IntervalAlgebra.Core: beginervalFromEnd :: (IntervalSizeable a b, Intervallic i) => b -> i a -> Interval a
- IntervalAlgebra.Core: class (Intervallic i a) => IntervalCombinable i a
+ IntervalAlgebra.Core: class (Ord a, Intervallic i) => IntervalCombinable i a
- IntervalAlgebra.Core: class (Ord a) => Intervallic i a
+ IntervalAlgebra.Core: class Intervallic i
- IntervalAlgebra.Core: concur :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: concur :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: contains :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: contains :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: disjoint :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: disjoint :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: duration :: (IntervalSizeable a b, Intervallic i a) => i a -> b
+ IntervalAlgebra.Core: duration :: (IntervalSizeable a b, Intervallic i) => i a -> b
- IntervalAlgebra.Core: during :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: during :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: enclosedBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: enclosedBy :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: end :: Intervallic i a => i a -> a
+ IntervalAlgebra.Core: end :: Intervallic i => i a -> a
- IntervalAlgebra.Core: endervalFromBegin :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> Interval a
+ IntervalAlgebra.Core: endervalFromBegin :: (IntervalSizeable a b, Intervallic i) => b -> i a -> Interval a
- IntervalAlgebra.Core: equals :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: equals :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: expand :: forall i a b. (IntervalSizeable a b, Intervallic i a) => b -> b -> i a -> i a
+ IntervalAlgebra.Core: expand :: forall i a b. (IntervalSizeable a b, Intervallic i) => b -> b -> i a -> i a
- IntervalAlgebra.Core: expandl :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> i a
+ IntervalAlgebra.Core: expandl :: (IntervalSizeable a b, Intervallic i) => b -> i a -> i a
- IntervalAlgebra.Core: expandr :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> i a
+ IntervalAlgebra.Core: expandr :: (IntervalSizeable a b, Intervallic i) => b -> i a -> i a
- IntervalAlgebra.Core: extenterval :: Intervallic i a => i a -> i a -> Interval a
+ IntervalAlgebra.Core: extenterval :: (Ord a, Intervallic i) => i a -> i a -> Interval a
- IntervalAlgebra.Core: finishedBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: finishedBy :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: finishes :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: finishes :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: getInterval :: Intervallic i a => i a -> Interval a
+ IntervalAlgebra.Core: getInterval :: Intervallic i => i a -> Interval a
- IntervalAlgebra.Core: meets :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: meets :: (Eq a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: metBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: metBy :: (Eq a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: momentize :: forall i a b. (IntervalSizeable a b, Intervallic i a) => i a -> i a
+ IntervalAlgebra.Core: momentize :: forall i a b. (IntervalSizeable a b, Intervallic i) => i a -> i a
- IntervalAlgebra.Core: notDisjoint :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: notDisjoint :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: overlappedBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: overlappedBy :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: overlaps :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: overlaps :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: precededBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: precededBy :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: precedes :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: precedes :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: predicate :: (Intervallic i0 a, Intervallic i1 a) => Set IntervalRelation -> ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: predicate :: (Ord a, Intervallic i0, Intervallic i1) => Set IntervalRelation -> ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: relate :: (Intervallic i0 a, Intervallic i1 a) => i0 a -> i1 a -> IntervalRelation
+ IntervalAlgebra.Core: relate :: (Ord a, Intervallic i0, Intervallic i1) => i0 a -> i1 a -> IntervalRelation
- IntervalAlgebra.Core: setInterval :: Intervallic i a => i a -> Interval a -> i a
+ IntervalAlgebra.Core: setInterval :: Intervallic i => i a -> Interval b -> i b
- IntervalAlgebra.Core: shiftFromBegin :: (IntervalSizeable a b, Functor i1, Intervallic i0 a) => i0 a -> i1 a -> i1 b
+ IntervalAlgebra.Core: shiftFromBegin :: (IntervalSizeable a b, Intervallic i1, Intervallic i0) => i0 a -> i1 a -> i1 b
- IntervalAlgebra.Core: shiftFromEnd :: (IntervalSizeable a b, Functor i1, Intervallic i0 a) => i0 a -> i1 a -> i1 b
+ IntervalAlgebra.Core: shiftFromEnd :: (IntervalSizeable a b, Intervallic i1, Intervallic i0) => i0 a -> i1 a -> i1 b
- IntervalAlgebra.Core: startedBy :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: startedBy :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: starts :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: starts :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.Core: within :: (Intervallic i0 a, Intervallic i1 a) => ComparativePredicateOf2 (i0 a) (i1 a)
+ IntervalAlgebra.Core: within :: (Ord a, Intervallic i0, Intervallic i1) => ComparativePredicateOf2 (i0 a) (i1 a)
- IntervalAlgebra.IntervalDiagram: simpleIntervalDiagram :: (Ord a, IntervalSizeable a b, Intervallic i a, Enum b) => i a -> [i a] -> Either IntervalDiagramParseError (IntervalDiagram a)
+ IntervalAlgebra.IntervalDiagram: simpleIntervalDiagram :: (Ord a, IntervalSizeable a b, Intervallic i, Enum b) => i a -> [i a] -> Either IntervalDiagramParseError (IntervalDiagram a)
- IntervalAlgebra.IntervalUtilities: allGapsWithinLessThanDuration :: (IntervalSizeable a b, Intervallic i0 a, IntervalCombinable i1 a, Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t) => b -> i0 a -> t (i1 a) -> Bool
+ IntervalAlgebra.IntervalUtilities: allGapsWithinLessThanDuration :: (IntervalSizeable a b, Intervallic i0, IntervalCombinable i1 a, Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t) => b -> i0 a -> t (i1 a) -> Bool
- IntervalAlgebra.IntervalUtilities: anyGapsWithinAtLeastDuration :: (IntervalSizeable a b, Intervallic i0 a, IntervalCombinable i1 a, Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t) => b -> i0 a -> t (i1 a) -> Bool
+ IntervalAlgebra.IntervalUtilities: anyGapsWithinAtLeastDuration :: (IntervalSizeable a b, Intervallic i0, IntervalCombinable i1 a, Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t) => b -> i0 a -> t (i1 a) -> Bool
- IntervalAlgebra.IntervalUtilities: clip :: (Intervallic i0 a, Intervallic i1 a, IntervalSizeable a b) => i0 a -> i1 a -> Maybe (Interval a)
+ IntervalAlgebra.IntervalUtilities: clip :: (Intervallic i0, Intervallic i1, IntervalSizeable a b) => i0 a -> i1 a -> Maybe (Interval a)
- IntervalAlgebra.IntervalUtilities: combineIntervals :: (Applicative f, Ord a, Intervallic i a, Monoid (f (Interval a)), Foldable f) => f (i a) -> f (Interval a)
+ IntervalAlgebra.IntervalUtilities: combineIntervals :: (Applicative f, Ord a, Intervallic i, Monoid (f (Interval a)), Foldable f) => f (i a) -> f (Interval a)
- IntervalAlgebra.IntervalUtilities: combineIntervalsL :: Intervallic i a => [i a] -> [Interval a]
+ IntervalAlgebra.IntervalUtilities: combineIntervalsL :: (Intervallic i, Ord a) => [i a] -> [Interval a]
- IntervalAlgebra.IntervalUtilities: durations :: (Functor f, Intervallic i a, IntervalSizeable a b) => f (i a) -> f b
+ IntervalAlgebra.IntervalUtilities: durations :: (Functor f, Intervallic i, IntervalSizeable a b) => f (i a) -> f b
- IntervalAlgebra.IntervalUtilities: filterAfter :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterAfter :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterBefore :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterBefore :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterConcur :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterConcur :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterContains :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterContains :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterDisjoint :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterDisjoint :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterDuring :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterDuring :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterEnclosedBy :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterEnclosedBy :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterEquals :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterEquals :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterFinishedBy :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterFinishedBy :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterFinishes :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterFinishes :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterMeets :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterMeets :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterMetBy :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterMetBy :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterNotDisjoint :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterNotDisjoint :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterOverlappedBy :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterOverlappedBy :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterOverlaps :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterOverlaps :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterStartedBy :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterStartedBy :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterStarts :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterStarts :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: filterWithin :: (Filterable f, Intervallic i0 a, Intervallic i1 a) => i0 a -> f (i1 a) -> f (i1 a)
+ IntervalAlgebra.IntervalUtilities: filterWithin :: (Filterable f, Ord a, Intervallic i0, Intervallic i1) => i0 a -> f (i1 a) -> f (i1 a)
- IntervalAlgebra.IntervalUtilities: gapsWithin :: (Applicative f, Witherable f, Monoid (f (Interval a)), Monoid (f (Maybe (Interval a))), IntervalSizeable a b, Intervallic i0 a, IntervalCombinable i1 a) => i0 a -> f (i1 a) -> Maybe (f (Interval a))
+ IntervalAlgebra.IntervalUtilities: gapsWithin :: (Applicative f, Witherable f, Monoid (f (Interval a)), Monoid (f (Maybe (Interval a))), IntervalSizeable a b, Intervallic i0, IntervalCombinable i1 a) => i0 a -> f (i1 a) -> Maybe (f (Interval a))
- IntervalAlgebra.IntervalUtilities: intersect :: (Intervallic i a, IntervalSizeable a b) => i a -> i a -> Maybe (Interval a)
+ IntervalAlgebra.IntervalUtilities: intersect :: (Intervallic i, IntervalSizeable a b) => i a -> i a -> Maybe (Interval a)
- IntervalAlgebra.IntervalUtilities: lookahead :: (Intervallic i a, IntervalSizeable a b) => b -> i a -> Interval a
+ IntervalAlgebra.IntervalUtilities: lookahead :: (Intervallic i, IntervalSizeable a b) => b -> i a -> Interval a
- IntervalAlgebra.IntervalUtilities: lookback :: (Intervallic i a, IntervalSizeable a b) => b -> i a -> Interval a
+ IntervalAlgebra.IntervalUtilities: lookback :: (Intervallic i, IntervalSizeable a b) => b -> i a -> Interval a
- IntervalAlgebra.IntervalUtilities: makeGapsWithinPredicate :: (Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t, IntervalSizeable a b, Intervallic i0 a, IntervalCombinable i1 a) => ((b -> Bool) -> t b -> Bool) -> (b -> b -> Bool) -> b -> i0 a -> t (i1 a) -> Bool
+ IntervalAlgebra.IntervalUtilities: makeGapsWithinPredicate :: (Monoid (t (Interval a)), Monoid (t (Maybe (Interval a))), Applicative t, Witherable t, IntervalSizeable a b, Intervallic i0, IntervalCombinable i1 a) => ((b -> Bool) -> t b -> Bool) -> (b -> b -> Bool) -> b -> i0 a -> t (i1 a) -> Bool
- IntervalAlgebra.IntervalUtilities: pairGaps :: (Intervallic i a, IntervalSizeable a b, IntervalCombinable i a) => [i a] -> [Maybe b]
+ IntervalAlgebra.IntervalUtilities: pairGaps :: (Intervallic i, IntervalSizeable a b, IntervalCombinable i a) => [i a] -> [Maybe b]
- IntervalAlgebra.IntervalUtilities: relations :: (Foldable f, Applicative m, Intervallic i a, Monoid (m IntervalRelation)) => f (i a) -> m IntervalRelation
+ IntervalAlgebra.IntervalUtilities: relations :: (Foldable f, Applicative m, Ord a, Intervallic i, Monoid (m IntervalRelation)) => f (i a) -> m IntervalRelation
- IntervalAlgebra.IntervalUtilities: relationsL :: (Foldable f, Intervallic i a) => f (i a) -> [IntervalRelation]
+ IntervalAlgebra.IntervalUtilities: relationsL :: (Foldable f, Ord a, Intervallic i) => f (i a) -> [IntervalRelation]

Files

ChangeLog.md view
@@ -1,5 +1,22 @@ # Changelog for interval-algebra +## 2.1.0++* Changes the type signature of the `Intervallic` typeclass.+* Adds a package component `tutorial` used to provide data for a tutorial document.+* Adds a tutorial document: _interval-algebra foundations_.+* Adds a function `standardExampleDiagram` to `IntervalAlgebra.IntervalDiagram` that can be concisely invoked in Haddock documentation examples.+* Renames `enclose` to `encloses` so tense is consistent with other relational predicates.+* Changes `combineIntervals` and `combineIntervalsL` to sort their inputs and adds new functions `combineIntervalsFromSorted` and `combineIntervalsFromSortedL` for cases when the input data already are sorted.+* Removes the unnecessary `Ord` constraint from `begin` and `end`, made possible by the changes to `Intervallic`.+* Removes `Functor Interval` instance and the `Functor`, `Bifunctor` instances of `PairedInterval`. It is not possible to write an instance that both satisfies the `Functor` laws and maintains the desired `Interval` property that the `begin` be strictly less than the `end`.+* Minor changes to the `IntervalAlgebra.IntervalDiagram` module, such as re-exporting `Pretty` and its methods.+* Deprecates `(<+>)`.++## 2.0.3++* Adds `labeledIntervalDiagram`, which creates interval diagrams with labels and a `rangeInterval` reference interval.+ ## 2.0.2  * Adds `rangeInterval`, which creates the smallest inverval containing all intervals in a `Foldable`.@@ -14,7 +31,7 @@  * Adds `Abitrary (Interval a)` instance generic over `Ord a, Arbitrary a`. * Removes the `moment'` function from the `IntervalSizeable` class.-Use type application with `moment` instead, as in `moment @Int`, `moment @Day`, etc.+* Use type application with `moment` instead, as in `moment @Int`, `moment @Day`, etc. * Adds the following utility functions: `lookback`, `lookahead`, `makeGapsWithinPredicate`, `pairGaps`, `anyGapsWithinAtLeastDuration`, `allGapsWithinLessThanDuration`
interval-algebra.cabal view
@@ -1,6 +1,6 @@ cabal-version:  2.2 name:           interval-algebra-version:        2.0.2+version:        2.1.0 synopsis:       An implementation of Allen's interval algebra for temporal logic description:    Please see the README on GitHub at <https://github.com/novisci/interval-algebra> category:       Algebra,Time@@ -32,7 +32,7 @@       IntervalAlgebra.Arbitrary   other-modules:       Paths_interval_algebra-  autogen-modules: +  autogen-modules:       Paths_interval_algebra   hs-source-dirs:       src@@ -53,46 +53,46 @@   default-language: Haskell2010  test-suite axioms-  type: exitcode-stdio-1.0  -  main-is: Main.hs -  other-modules: +  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:       AxiomsSpec   hs-source-dirs:       test-axioms   ghc-options: -threaded -rtsopts -with-rtsopts=-N   build-depends:       base >=4.7 && <5-    , hspec +    , hspec     , interval-algebra     , QuickCheck     , time   default-language: Haskell2010  test-suite relations-  type: exitcode-stdio-1.0  -  main-is: Main.hs -  other-modules: +  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:       RelationPropertiesSpec   hs-source-dirs:       test-relation-properties   ghc-options: -threaded -rtsopts -with-rtsopts=-N   build-depends:       base >=4.7 && <5-    , hspec +    , hspec     , interval-algebra-    , QuickCheck -    , time +    , QuickCheck+    , time   default-language: Haskell2010  test-suite interval-algebra-test-  type: exitcode-stdio-1.0  -  main-is: Spec.hs +  type: exitcode-stdio-1.0+  main-is: Spec.hs   other-modules:       IntervalAlgebraSpec       IntervalAlgebra.IntervalUtilitiesSpec       IntervalAlgebra.PairedIntervalSpec       Paths_interval_algebra-  autogen-modules: +  autogen-modules:       Paths_interval_algebra   hs-source-dirs:       test@@ -100,7 +100,7 @@   build-depends:       base >=4.7 && <5     , containers-    , hspec +    , hspec     , interval-algebra     , QuickCheck     , safe@@ -108,4 +108,16 @@     , witherable   build-tool-depends:       hspec-discover:hspec-discover >= 2.9.2+  default-language: Haskell2010++executable tutorial+  main-is: TutorialMain.hs+  hs-source-dirs: tutorial+  build-depends:+      base >=4.7 && <5+    , containers ^>= 0.6+    , interval-algebra+    , prettyprinter ^>= 1.7+    , time ^>= 1.9+    , witch ^>= 1.0   default-language: Haskell2010
src/IntervalAlgebra/Arbitrary.hs view
@@ -120,7 +120,7 @@ -- arbitraryWithRelation   :: forall i a b-   . (IntervalSizeable a b, Intervallic i a, Arbitrary (i a))+   . (IntervalSizeable a b, Intervallic i, Arbitrary (i a))   => i a -- ^ reference interval   -> Data.Set.Set IntervalRelation -- ^ set of `IntervalRelation`s, of which at least one will hold for the generated interval relative to the reference   -> Gen (Maybe (i a))
src/IntervalAlgebra/Core.hs view
@@ -5,15 +5,15 @@ License     : BSD3 Maintainer  : bsaul@novisci.com -The @IntervalAlgebra@ module provides data types and related classes for the +The @IntervalAlgebra@ module provides data types and related classes for the interval-based temporal logic described in [Allen (1983)](https://doi.org/10.1145/182.358434)-and axiomatized in [Allen and Hayes (1987)](https://doi.org/10.1111/j.1467-8640.1989.tb00329.x). +and axiomatized in [Allen and Hayes (1987)](https://doi.org/10.1111/j.1467-8640.1989.tb00329.x). A good primer on Allen's algebra can be [found here](https://thomasalspaugh.org/pub/fnd/allen.html).  = Design -The module is built around three typeclasses designed to separate concerns of -constructing, relating, and combining types that contain @'Interval'@s: +The module is built around three typeclasses designed to separate concerns of+constructing, relating, and combining types that contain @'Interval'@s:  1. @'Intervallic'@ provides an interface to the data structures which contain an    @'Interval'@.@@ -53,111 +53,27 @@   , safeInterval   , si -    -- ** Modify intervals  +    -- ** Modify intervals   , expand   , expandl   , expandr -    -- * Interval Algebra +    -- * Interval Algebra      -- ** Interval Relations and Predicates   , IntervalRelation(..)--    {- |-    === Meets, Metby--    > x `meets` y-    > y `metBy` x--    @ -    x: |-----|-    y:       |-----| -    @-    -}   , meets   , metBy--    {- |-    === Before, After--    > x `before` y-    > y `after` x--    @ -    x: |-----|  -    y:          |-----|-    @-    -}   , before   , after--    {- |-    === Overlaps, OverlappedBy--    > x `overlaps` y-    > y `overlappedBy` x--    @ -    x: |-----|-    y:     |-----|-    @-    -}   , overlaps   , overlappedBy--    {- |-    === Finishes, FinishedBy--    > x `finishes` y-    > y `finishedBy` x--    @ -    x:   |---| -    y: |-----|-    @-    -}   , finishedBy   , finishes--    {- |-    === During, Contains--    > x `during` y-    > y `contains` x--    @ -    x:   |-| -    y: |-----|-    @-    -}   , contains   , during--    {- |-    === Starts, StartedBy--    > x `starts` y-    > y `startedBy` x--    @ -    x: |---| -    y: |-----|-    @-    -}   , starts   , startedBy--    {- |-    === Equal--    > x `equal` y-    > y `equal` x--    @ -    x: |-----| -    y: |-----|-    @-    -}   , equals      -- ** Additional predicates and utilities@@ -167,7 +83,7 @@   , notDisjoint   , concur   , within-  , enclose+  , encloses   , enclosedBy   , (<|>)   , predicate@@ -184,6 +100,8 @@   , shiftFromBegin   , shiftFromEnd   , momentize+  , toEnumInterval+  , fromEnumInterval      -- ** Algebraic operations   , intervalRelations@@ -213,7 +131,6 @@                                                 , flip                                                 , id                                                 )-import           Data.Functor                   ( Functor(fmap) ) import           Data.Ord                       ( Ord(..)                                                 , Ordering(..)                                                 , max@@ -282,6 +199,10 @@                                                 , suchThat                                                 ) +{- $setup+>>> import IntervalAlgebra.IntervalDiagram+-}+ {- | An @'Interval' a@ is a pair \( (x, y) \text{ such that } x < y\). To create intervals use the @'parseInterval'@, @'beginerval'@, or @'enderval'@ functions. -}@@ -291,19 +212,20 @@ newtype ParseErrorInterval = ParseErrorInterval String     deriving (Eq, Show) --- | Helper defining what a valid relation is between begin and end of an--- Interval.+{- | Helper defining what a valid relation is between begin and end of an+Interval.+-} isValidBeginEnd :: (Ord a) => a -> a -> Bool isValidBeginEnd b e = b < e --- | Safely parse a pair of @a@s to create an @'Interval' a@.------ >>> parseInterval 0 1--- Right (0, 1)--- --- >>> parseInterval 1 0--- Left (ParseErrorInterval "0<=1")--- +{- | Safely parse a pair of @a@s to create an @'Interval' a@.++>>> parseInterval 0 1+Right (0, 1)++>>> parseInterval 1 0+Left (ParseErrorInterval "0<=1")+-} parseInterval   :: (Show a, Ord a) => a -> a -> Either ParseErrorInterval (Interval a) parseInterval x y@@ -313,25 +235,21 @@ prsi :: (Show a, Ord a) => a -> a -> Either ParseErrorInterval (Interval a) prsi = parseInterval -intervalBegin :: (Ord a) => Interval a -> a+intervalBegin :: Interval a -> a intervalBegin (Interval x) = fst x -intervalEnd :: (Ord a) => Interval a -> a+intervalEnd :: Interval a -> a intervalEnd (Interval x) = snd x -instance Functor Interval where-  fmap f (Interval (x, y)) = Interval (f x, f y)- instance (Show a, Ord a) => Show (Interval a) where   show x = "(" ++ show (begin x) ++ ", " ++ show (end x) ++ ")"  instance Binary a => Binary (Interval a) instance NFData a => NFData (Interval a) -{- | -The @'Intervallic'@ typeclass defines how to get and set the 'Interval' content-of a data structure. It also includes functions for getting the endpoints of the-'Interval' via @'begin'@ and @'end'@. +{- | The @'Intervallic'@ typeclass defines how to get and set the 'Interval'+content of a data structure. It also includes functions for getting the+endpoints of the 'Interval' via @'begin'@ and @'end'@.  >>> getInterval (Interval (0, 10)) (0, 10)@@ -342,23 +260,29 @@ >>> end (Interval (0, 10)) 10 -}-class (Ord a) => Intervallic i a where+class Intervallic i where      -- | Get the interval from an @i a@.     getInterval :: i a -> Interval a      -- | Set the interval in an @i a@.-    setInterval :: i a -> Interval a -> i a+    setInterval :: i a -> Interval b -> i b  -- | Access the endpoints of an @i a@ .-begin, end :: Intervallic i a => i a -> a+begin, end :: (Intervallic i) => i a -> a begin = intervalBegin . getInterval end = intervalEnd . getInterval -{- | -The 'IntervalRelation' type and the associated predicate functions enumerate+{- | This *unexported* function is an internal convenience function for cases in+which @f@ is known to be strictly monotone.+-}+imapStrictMonotone :: (Intervallic i) => (a -> b) -> i a -> i b+imapStrictMonotone f i = setInterval i (op f (getInterval i))+  where op f (Interval (b, e)) = Interval (f b, f e)++{- | The 'IntervalRelation' type and the associated predicate functions enumerate the thirteen possible ways that two @'Interval'@ objects may 'relate' according-to Allen's interval algebra. Constructors are shown with their corresponding +to Allen's interval algebra. Constructors are shown with their corresponding predicate function. -} data IntervalRelation =@@ -384,58 +308,236 @@ instance Ord IntervalRelation where   compare x y = compare (fromEnum x) (fromEnum y) --- | Does x `meets` y? Is x metBy y?++{- | Does x `meets` y? Is x `metBy` y?++Example data with corresponding diagram:++>>> x = bi 5 0+>>> y = bi 5 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+-----      <- [x]+     ----- <- [y]+==========++Examples:++>>> x `meets` y+True++>>> x `metBy` y+False++>>> y `meets` x+False++>>> y `metBy` x+True+-} meets, metBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Eq a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) meets x y = end x == begin y metBy = flip meets --- | Is x before y? Is x after y?++{- | Is x `before` y? Does x `precedes` y? Is x `after` y? Is x `precededBy` y?++Example data with corresponding diagram:++>>> x = bi 3 0+>>> y = bi 4 6+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+---        <- [x]+      ---- <- [y]+==========++Examples:++>>> x `before` y+True+>>> x `precedes` y+True++>>> x `after`y+False+>>> x `precededBy` y+False++>>> y `before` x+False+>>> y `precedes` x+False++>>> y `after` x+True+>>> y `precededBy` x+True+-} before, after, precedes, precededBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) before x y = end x < begin y after = flip before precedes = before precededBy = after--- | Does x overlap y? Is x overlapped by y?+++{- | Does x `overlaps` y? Is x `overlappedBy` y?++Example data with corresponding diagram:++>>> x = bi 6 0+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+------     <- [x]+    ------ <- [y]+==========++Examples:++>>> x `overlaps` y+True++>>> x `overlappedBy` y+False++>>> y `overlaps` x+False++>>> y `overlappedBy` x+True+-} overlaps, overlappedBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) overlaps x y = begin x < begin y && end x < end y && end x > begin y overlappedBy = flip overlaps --- | Does x start y? Is x started by y?++{-| Does x `starts` y? Is x `startedBy` y?++Example data with corresponding diagram:++>>> x = bi 3 4+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ---    <- [x]+    ------ <- [y]+==========++Examples:++>>> x `starts` y+True++>>> x `startedBy` y+False++>>> y `starts` x+False++>>> y `startedBy` x+True+-} starts, startedBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) starts x y = begin x == begin y && end x < end y startedBy = flip starts --- | Does x finish y? Is x finished by y?++{- | Does x `finishes` y? Is x `finishedBy` y?++Example data with corresponding diagram:++>>> x = bi 3 7+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+       --- <- [x]+    ------ <- [y]+==========++Examples:++>>> x `finishes` y+True++>>> x `finishedBy` y+False++>>> y `finishes` x+False++>>> y `finishedBy` x+True+-} finishes, finishedBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) finishes x y = begin x > begin y && end x == end y finishedBy = flip finishes --- | Is x during y? Does x contain y?++{-| Is x `during` y? Does x `contains` y?++Example data with corresponding diagram:++>>> x = bi 3 5+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+     ---   <- [x]+    ------ <- [y]+==========++Examples:++>>> x `during` y+True++>>> x `contains` y+False++>>> y `during` x+False++>>> y `contains` x+True+-} during, contains-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) during x y = begin x > begin y && end x < end y contains = flip during --- | Does x equal y?++{- | Does x `equals` y?++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+    ------ <- [y]+==========++Examples:++>>> x `equals` y+True++>>> y `equals` x+True+-} equals-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) equals x y = begin x == begin y && end x == end y  -- | Operator for composing the union of two predicates (<|>)-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a)   -> ComparativePredicateOf2 (i0 a) (i1 a)   -> ComparativePredicateOf2 (i0 a) (i1 a)@@ -453,33 +555,275 @@ strictWithinRelations :: Data.Set.Set IntervalRelation strictWithinRelations = Data.Set.difference withinRelations (toSet [Equals]) --- | Are x and y disjoint ('before', 'after', 'meets', or 'metBy')?++{- | Are x and y `disjoint` ('before', 'after', 'meets', or 'metBy')?++Example data with corresponding diagram:++>>> x = bi 3 0+>>> y = bi 3 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+---      <- [x]+     --- <- [y]+========++Examples:++>>> x `disjoint` y+True++>>> y `disjoint` x+True++Example data with corresponding diagram:++>>> x = bi 3 0+>>> y = bi 3 3+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+---    <- [x]+   --- <- [y]+======++Examples:++>>> x `disjoint` y+True++>>> y `disjoint` x+True++Example data with corresponding diagram:++>>> x = bi 6 0+>>> y = bi 3 3+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+------ <- [x]+   --- <- [y]+======++Examples:++>>> x `disjoint` y+False++>>> y `disjoint` x+False+-} disjoint-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) disjoint = predicate disjointRelations --- | Are x and y not disjoint (concur); i.e. do they share any support? This is---   the 'complement' of 'disjoint'.++{-| Does x `concur` with y? Is x `notDisjoint` with y?); This is+the 'complement' of 'disjoint'.++Example data with corresponding diagram:++>>> x = bi 3 0+>>> y = bi 3 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+---     <- [x]+    --- <- [y]+=======++Examples:++>>> x `notDisjoint` y+False+>>> y `concur` x+False++Example data with corresponding diagram:++>>> x = bi 3 0+>>> y = bi 3 3+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+---    <- [x]+   --- <- [y]+======++Examples:++>>> x `notDisjoint` y+False+>>> y `concur` x+False++Example data with corresponding diagram:++>>> x = bi 6 0+>>> y = bi 3 3+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+------ <- [x]+   --- <- [y]+======++Examples:++>>> x `notDisjoint` y+True+>>> y `concur` x+True+-} notDisjoint, concur-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) notDisjoint = predicate (complement disjointRelations) concur = notDisjoint --- | Is x entirely *within* (enclosed by) the endpoints of y? That is, 'during', ---   'starts', 'finishes', or 'equals'?++{- | Is x `within` (`enclosedBy`) y? That is, 'during', 'starts', 'finishes', or+'equals'?++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+    ------ <- [y]+==========++Examples:++>>> x `within` y+True++>>> y `enclosedBy` x+True++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 5 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+    -----  <- [y]+==========++Examples:++>>> x `within` y+False++>>> y `enclosedBy` x+True++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 4 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+     ----  <- [y]+==========++Examples:++>>> x `within` y+False+>>> y `enclosedBy` x+True++Example data with corresponding diagram:++>>> x = bi 2 7+>>> y = bi 1 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+       -- <- [x]+     -    <- [y]+=========++Examples:++>>> x `within` y+False++>>> y `enclosedBy` x+False+-} within, enclosedBy-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a) within = predicate withinRelations enclosedBy = within --- | Does x enclose y? That is, is y 'within' x?-enclose-  :: (Intervallic i0 a, Intervallic i1 a)++{- | Does x `encloses` y? That is, is y 'within' x?++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 6 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+    ------ <- [y]+==========++Examples:++>>> x `encloses` y+True++>>> y `encloses` x+True++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 5 4+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+    -----  <- [y]+==========++Examples:++>>> x `encloses` y+True++>>> y `encloses` x+False++Example data with corresponding diagram:++>>> x = bi 6 4+>>> y = bi 4 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+    ------ <- [x]+     ----  <- [y]+==========++Examples:++>>> x `encloses` y+True++>>> y `encloses` x+False++Example data with corresponding diagram:++>>> x = bi 2 7+>>> y = bi 1 5+>>> pretty $ standardExampleDiagram [(x, "x"), (y, "y")] []+       -- <- [x]+     -    <- [y]+=========++Examples:++>>> x `encloses` y+False++>>> y `encloses` x+False+-}+encloses+  :: (Ord a, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a)-enclose = flip enclosedBy+encloses = flip enclosedBy  -- | The 'Data.Set.Set' of all 'IntervalRelation's. intervalRelations :: Data.Set.Set IntervalRelation@@ -495,7 +839,7 @@ toSet = Data.Set.fromList  -- | Compose a list of interval relations with _or_ to create a new--- @'ComparativePredicateOf1' i a@. For example, +-- @'ComparativePredicateOf1' i a@. For example, -- @unionPredicates [before, meets]@ creates a predicate function determining -- if one interval is either before or meets another interval. unionPredicates :: [ComparativePredicateOf2 a b] -> ComparativePredicateOf2 a b@@ -503,7 +847,7 @@  -- | Maps an 'IntervalRelation' to its corresponding predicate function. toPredicate-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => IntervalRelation   -> ComparativePredicateOf2 (i0 a) (i1 a) toPredicate r = case r of@@ -521,17 +865,17 @@   MetBy        -> metBy   After        -> after --- | Given a set of 'IntervalRelation's return a list of 'predicate' functions +-- | Given a set of 'IntervalRelation's return a list of 'predicate' functions --   corresponding to each relation. predicates-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => Data.Set.Set IntervalRelation   -> [ComparativePredicateOf2 (i0 a) (i1 a)] predicates x = Prelude.map toPredicate (Data.Set.toList x)  -- | Forms a predicate function from the union of a set of 'IntervalRelation's. predicate-  :: (Intervallic i0 a, Intervallic i1 a)+  :: (Ord a, Intervallic i0, Intervallic i1)   => Data.Set.Set IntervalRelation   -> ComparativePredicateOf2 (i0 a) (i1 a) predicate = unionPredicates . predicates@@ -582,16 +926,16 @@   cncr  = o ++ f' ++ d' ++ s ++ e ++ s' ++ d ++ f ++ o'   full  = p ++ m ++ cncr ++ m' ++ p' --- | Compare two @i a@ to determine their 'IntervalRelation'.------ >>> relate (Interval (0::Int, 1)) (Interval (1, 2))--- Meets------ >>> relate (Interval (1::Int, 2)) (Interval (0, 1))--- MetBy--- +{- | Compare two @i a@ to determine their 'IntervalRelation'.++>>> relate (Interval (0::Int, 1)) (Interval (1, 2))+Meets++>>> relate (Interval (1::Int, 2)) (Interval (0, 1))+MetBy+-} relate-  :: (Intervallic i0 a, Intervallic i1 a) => i0 a -> i1 a -> IntervalRelation+  :: (Ord a, Intervallic i0, Intervallic i1) => i0 a -> i1 a -> IntervalRelation relate x y | x `before` y       = Before            | x `after` y        = After            | x `meets` y        = Meets@@ -606,9 +950,10 @@            | x `contains` y     = Contains            | otherwise          = Equals --- | Compose two interval relations according to the rules of the algebra.---   The rules are enumerated according to--- <https://thomasalspaugh.org/pub/fnd/allen.html#BasicCompositionsTable this table>.+{- | Compose two interval relations according to the rules of the algebra.+The rules are enumerated according to+<https://thomasalspaugh.org/pub/fnd/allen.html#BasicCompositionsTable this table>.+-} compose   :: IntervalRelation -> IntervalRelation -> Data.Set.Set IntervalRelation compose x y = toSet (composeRelationLookup !! fromEnum x !! fromEnum y)@@ -631,13 +976,12 @@   -> Data.Set.Set IntervalRelation union = Data.Set.union --- | Find the converse of a @'Data.Set.Set' 'IntervalRelation'@. +-- | Find the converse of a @'Data.Set.Set' 'IntervalRelation'@. converse :: Data.Set.Set IntervalRelation -> Data.Set.Set IntervalRelation converse = Data.Set.map converseRelation -{- |-The 'IntervalSizeable' typeclass provides functions to determine the size of an-'Intervallic' type and to resize an 'Interval a'.+{- | The 'IntervalSizeable' typeclass provides functions to determine the size of+an 'Intervallic' type and to resize an 'Interval a'. -} class (Ord a, Num b, Ord b) => IntervalSizeable a b | a -> b where @@ -646,29 +990,41 @@     moment = 1      -- | Determine the duration of an @'i a'@.-    duration :: Intervallic i a => i a -> b+    duration :: (Intervallic i) => i a -> b     duration x = diff (end x) (begin x) -    -- | Shifts an @a@. Most often, the @b@ will be the same type as @a@. +    -- | Shifts an @a@. Most often, the @b@ will be the same type as @a@.     --   But for example, if @a@ is 'Day' then @b@ could be 'Int'.     add :: b -> a -> a      -- | Takes the difference between two @a@ to return a @b@.     diff :: a -> a -> b --- | Resize an @i a@ to by expanding to "left" by @l@ and to the ---   "right" by @r@. In the case that @l@ or @r@ are less than a 'moment'---   the respective endpoints are unchanged. ------ >>> expand 0 0 (Interval (0::Int, 2::Int))--- (0, 2)------ >>> expand 1 1 (Interval (0::Int, 2::Int))--- (-1, 3)---+{- | Resize an @i a@ to by expanding to "left" by @l@ and to the "right" by @r@.+In the case that @l@ or @r@ are less than a 'moment' the respective endpoints+are unchanged.++>>> iv2to4 = safeInterval (2::Int, 4::Int)+>>> iv2to4' = expand 0 0 iv2to4+>>> iv1to5 = expand 1 1 iv2to4++>>> iv2to4+(2, 4)++>>> iv2to4'+(2, 4)++>>> iv1to5+(1, 5)++>>> pretty $ standardExampleDiagram [(iv2to4, "iv2to4"), (iv1to5, "iv1to5")] []+  --  <- [iv2to4]+ ---- <- [iv1to5]+=====+-} expand   :: forall i a b-   . (IntervalSizeable a b, Intervallic i a)+   . (IntervalSizeable a b, Intervallic i)   => b -- ^ duration to subtract from the 'begin'   -> b -- ^ duration to add to the 'end'   -> i a@@ -679,38 +1035,60 @@   e = if r < moment @a then 0 else r   i = Interval (add s $ begin p, add e $ end p) --- | Expands an @i a@ to "left".------ >>> expandl 2 (Interval (0::Int, 2::Int))--- (-2, 2)----expandl :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> i a+{- | Expands an @i a@ to the "left".++>>> iv2to4 = (safeInterval (2::Int, 4::Int))+>>> iv0to4 = expandl 2 iv2to4++>>> iv2to4+(2, 4)++>>> iv0to4+(0, 4)++>>> pretty $ standardExampleDiagram [(iv2to4, "iv2to4"), (iv0to4, "iv0to4")] []+  -- <- [iv2to4]+---- <- [iv0to4]+====+-}+expandl :: (IntervalSizeable a b, Intervallic i) => b -> i a -> i a expandl i = expand i 0 --- | Expands an @i a@ to "right".------ >>> expandr 2 (Interval (0::Int, 2::Int))--- (0, 4)----expandr :: (IntervalSizeable a b, Intervallic i a) => b -> i a -> i a+{- | Expands an @i a@ to the "right".++>>> iv2to4 = (safeInterval (2::Int, 4::Int))+>>> iv2to6 = expandr 2 iv2to4++>>> iv2to4+(2, 4)++>>> iv2to6+(2, 6)++>>> pretty $ standardExampleDiagram [(iv2to4, "iv2to4"), (iv2to6, "iv2to6")] []+  --   <- [iv2to4]+  ---- <- [iv2to6]+======+-}+expandr :: (IntervalSizeable a b, Intervallic i) => b -> i a -> i a expandr = expand 0 --- | Safely creates an 'Interval a' using @x@ as the 'begin' and adding ---   @max 'moment' dur@ to @x@ as the 'end'.------ >>> beginerval (0::Int) (0::Int)--- (0, 1)------ >>> beginerval (1::Int) (0::Int)--- (0, 1)------ >>> beginerval (2::Int) (0::Int)--- (0, 2)---+{- | Safely creates an 'Interval a' using @x@ as the 'begin' and adding @max+'moment' dur@ to @x@ as the 'end'.++>>> beginerval (0::Int) (0::Int)+(0, 1)++>>> beginerval (1::Int) (0::Int)+(0, 1)++>>> beginerval (2::Int) (0::Int)+(0, 2)+-} beginerval   :: forall a b    . (IntervalSizeable a b)-  => b -- ^ @dur@ation to add to the 'begin' +  => b -- ^ @dur@ation to add to the 'begin'   -> a -- ^ the 'begin' point of the 'Interval'   -> Interval a beginerval dur x = Interval (x, y)@@ -723,28 +1101,28 @@ -- | A synonym for `beginerval` bi   :: (IntervalSizeable a b)-  => b -- ^ @dur@ation to add to the 'begin' +  => b -- ^ @dur@ation to add to the 'begin'   -> a -- ^ the 'begin' point of the 'Interval'   -> Interval a bi = beginerval  --- | Safely creates an 'Interval a' using @x@ as the 'end' and adding---   @negate max 'moment' dur@ to @x@ as the 'begin'.------ >>> enderval (0::Int) (0::Int)--- (-1, 0)------ >>> enderval (1::Int) (0::Int)--- (-1, 0)------ >>> enderval (2::Int) (0::Int)--- (-2, 0)---+{- | Safely creates an 'Interval a' using @x@ as the 'end' and adding @negate max+'moment' dur@ to @x@ as the 'begin'.++>>> enderval (0::Int) (0::Int)+(-1, 0)++>>> enderval (1::Int) (0::Int)+(-1, 0)++>>> enderval (2::Int) (0::Int)+(-2, 0)+-} enderval   :: forall a b    . (IntervalSizeable a b)-  => b -- ^ @dur@ation to subtract from the 'end' +  => b -- ^ @dur@ation to subtract from the 'end'   -> a -- ^ the 'end' point of the 'Interval'   -> Interval a enderval dur x = Interval (add (negate $ max (moment @a) dur) x, x)@@ -754,14 +1132,14 @@ -- | A synonym for `enderval` ei   :: (IntervalSizeable a b)-  => b -- ^ @dur@ation to subtract from the 'end' +  => b -- ^ @dur@ation to subtract from the 'end'   -> a -- ^ the 'end' point of the 'Interval'   -> Interval a ei = enderval   -- | Safely creates an @'Interval'@ from a pair of endpoints.--- IMPORTANT: This function uses 'beginerval', +-- IMPORTANT: This function uses 'beginerval', -- thus if the second element of the pair is `<=` the first element, -- the duration will be an @"Interval"@ of 'moment' duration. --@@ -779,93 +1157,158 @@  -- | Creates a new Interval from the 'end' of an @i a@. beginervalFromEnd-  :: (IntervalSizeable a b, Intervallic i a)-  => b  -- ^ @dur@ation to add to the 'end' +  :: (IntervalSizeable a b, Intervallic i)+  => b  -- ^ @dur@ation to add to the 'end'   -> i a -- ^ the @i a@ from which to get the 'end'   -> Interval a beginervalFromEnd d i = beginerval d (end i)  -- | Creates a new Interval from the 'begin' of an @i a@. endervalFromBegin-  :: (IntervalSizeable a b, Intervallic i a)-  => b -- ^ @dur@ation to subtract from the 'begin'  +  :: (IntervalSizeable a b, Intervallic i)+  => b -- ^ @dur@ation to subtract from the 'begin'   -> i a -- ^ the @i a@ from which to get the 'begin'   -> Interval a endervalFromBegin d i = enderval d (begin i) --- | Safely creates a new @Interval@ with 'moment' length with 'begin' at @x@------ >>> beginervalMoment (10 :: Int)--- (10, 11)--- +{- | Safely creates a new @Interval@ with 'moment' length with 'begin' at @x@++>>> beginervalMoment (10 :: Int)+(10, 11)+-} beginervalMoment :: forall a b . (IntervalSizeable a b) => a -> Interval a beginervalMoment x = beginerval (moment @a) x where i = Interval (x, x) --- | Safely creates a new @Interval@ with 'moment' length with 'end' at @x@------ >>> endervalMoment (10 :: Int)--- (9, 10)--- +{- | Safely creates a new @Interval@ with 'moment' length with 'end' at @x@++>>> endervalMoment (10 :: Int)+(9, 10)+-} endervalMoment :: forall a b . (IntervalSizeable a b) => a -> Interval a endervalMoment x = enderval (moment @a) x where i = Interval (x, x) --- | Creates a new @Interval@ spanning the extent x and y.------ >>> extenterval (Interval (0, 1)) (Interval (9, 10))--- (0, 10)----extenterval :: Intervallic i a => i a -> i a -> Interval a+{- | Creates a new @Interval@ spanning the extent x and y.++>>> extenterval (Interval (0, 1)) (Interval (9, 10))+(0, 10)+-}+extenterval :: (Ord a, Intervallic i) => i a -> i a -> Interval a extenterval x y = Interval (s, e)  where   s = min (begin x) (begin y)   e = max (end x) (end y) --- | Modifies the endpoints of second argument's interval by taking the difference---   from the first's input's 'begin'. --- >>> shiftFromBegin (Interval ((5::Int), 6)) (Interval (10, 15))--- (5, 10)------ >>> shiftFromBegin (Interval ((1::Int), 2)) (Interval (3, 15))--- (2, 14)---+{- | Modifies the endpoints of second argument's interval by taking the difference+from the first's input's 'begin'.++Example data with corresponding diagram:++>>> a = bi 3 2 :: Interval Int+>>> a+(2, 5)+>>> x = bi 3 7 :: Interval Int+>>> x+(7, 10)+>>> y = bi 4 9 :: Interval Int+>>> y+(9, 13)+>>> pretty $ standardExampleDiagram [(a, "a"), (x, "x"), (y, "y")] []+  ---         <- [a]+       ---    <- [x]+         ---- <- [y]+=============++Examples:++>>> x' = shiftFromBegin a x+>>> x'+(5, 8)+>>> y' = shiftFromBegin a y+>>> y'+(7, 11)+>>> pretty $ standardExampleDiagram [(x', "x'"), (y', "y'")] []+     ---    <- [x']+       ---- <- [y']+===========+-} shiftFromBegin-  :: (IntervalSizeable a b, Functor i1, Intervallic i0 a)+  :: (IntervalSizeable a b, Intervallic i1, Intervallic i0)   => i0 a   -> i1 a   -> i1 b-shiftFromBegin i = fmap (`diff` begin i)+shiftFromBegin i = imapStrictMonotone (`diff` begin i) --- | Modifies the endpoints of second argument's interval by taking the difference---   from the first's input's 'end'.--- >>> shiftFromEnd (Interval ((5::Int), 6)) (Interval (10, 15))--- (4, 9)------ >>> shiftFromEnd (Interval ((1::Int), 2)) (Interval (3, 15))--- (1, 13)---+{- | Modifies the endpoints of second argument's interval by taking the difference+from the first's input's 'end'.++Example data with corresponding diagram:++>>> a = bi 3 2 :: Interval Int+>>> a+(2, 5)+>>> x = bi 3 7 :: Interval Int+>>> x+(7, 10)+>>> y = bi 4 9 :: Interval Int+>>> y+(9, 13)+>>> pretty $ standardExampleDiagram [(a, "a"), (x, "x"), (y, "y")] []+  ---         <- [a]+       ---    <- [x]+         ---- <- [y]+=============++Examples:++>>> x' = shiftFromEnd a x+>>> x'+(2, 5)+>>> y' = shiftFromEnd a y+>>> y'+(4, 8)+>>> pretty $ standardExampleDiagram [(x', "x'"), (y', "y'")] []+  ---    <- [x']+    ---- <- [y']+========+-} shiftFromEnd-  :: (IntervalSizeable a b, Functor i1, Intervallic i0 a)+  :: (IntervalSizeable a b, Intervallic i1, Intervallic i0)   => i0 a   -> i1 a   -> i1 b-shiftFromEnd i = fmap (`diff` end i)+shiftFromEnd i = imapStrictMonotone (`diff` end i) --- | Changes the duration of an 'Intervallic' value to a moment starting at the ---   'begin' of the interval.------ >>> momentize (Interval (6, 10))--- (6, 7)---+-- | Converts an @i a@ to an @i Int@ via @fromEnum@.  This assumes the provided+-- @fromEnum@ method is strictly monotone increasing: For @a@ types that are+-- @Ord@ with values @x, y@, then @x < y@ implies @fromEnum x < fromEnum y@, so+-- long as the latter is well-defined.+fromEnumInterval :: (Enum a, Intervallic i) => i a -> i Int+fromEnumInterval = imapStrictMonotone fromEnum++-- | Converts an @i Int@ to an @i a@ via @toEnum@.  This assumes the provided+-- @toEnum@ method is strictly monotone increasing: For @a@ types that are+-- @Ord@, then for @Int@ values @x, y@ it holds that @x < y@ implies @toEnum x+-- < toEnum y@.+toEnumInterval :: (Enum a, Intervallic i) => i Int -> i a+toEnumInterval = imapStrictMonotone toEnum++++{- | Changes the duration of an 'Intervallic' value to a moment starting at the+'begin' of the interval.++>>> momentize (Interval (6, 10))+(6, 7)+-} momentize-  :: forall i a b . (IntervalSizeable a b, Intervallic i a) => i a -> i a+  :: forall i a b . (IntervalSizeable a b, Intervallic i) => i a -> i a momentize i = setInterval i (beginerval (moment @a) (begin i)) -{- |-The @'IntervalCombinable'@ typeclass provides methods for (possibly) combining-two @i a@s to form a @'Maybe' i a@, or in case of @><@, a possibly different -@Intervallic@ type.+{- | The @'IntervalCombinable'@ typeclass provides methods for (possibly)+combining two @i a@s to form a @'Maybe' i a@, or in case of @><@, a possibly+different @Intervallic@ type. -}-class (Intervallic i a) => IntervalCombinable i a where+class (Ord a, Intervallic i) => IntervalCombinable i a where      -- | Maybe form a new @i a@ by the union of two @i a@s that 'meets'.     (.+.) ::  i a -> i a -> Maybe (i a)@@ -876,20 +1319,20 @@             e = end y     {-# INLINABLE (.+.) #-} -    -- | If @x@ is 'before' @y@, then form a new @Just Interval a@ from the +    -- | If @x@ is 'before' @y@, then form a new @Just Interval a@ from the     --   interval in the "gap" between @x@ and @y@ from the 'end' of @x@ to the     --   'begin' of @y@. Otherwise, 'Nothing'.     (><) :: i a -> i a -> Maybe (i a) -    -- | If @x@ is 'before' @y@, return @f x@ appended to @f y@. Otherwise, -    --   return 'extenterval' of @x@ and @y@ (wrapped in @f@). This is useful for -    --   (left) folding over an *ordered* container of @Interval@s and combining +    -- | If @x@ is 'before' @y@, return @f x@ appended to @f y@. Otherwise,+    --   return 'extenterval' of @x@ and @y@ (wrapped in @f@). This is useful for+    --   (left) folding over an *ordered* container of @Interval@s and combining     --   intervals when @x@ is *not* 'before' @y@.     (<+>):: ( Semigroup (f (i a)), Applicative f) =>                i a             -> i a             -> f (i a)-+{-# DEPRECATED (<+>) "A specialized function without clear use-cases." #-}  {- Misc@@ -905,7 +1348,7 @@ -- Instances -- -} --- | Imposes a total ordering on @'Interval' a@ based on first ordering the +-- | Imposes a total ordering on @'Interval' a@ based on first ordering the --   'begin's then the 'end's. instance (Ord a) => Ord (Interval a) where   (<=) x y | begin x < begin y  = True@@ -915,7 +1358,7 @@           | begin x == begin y = end x < end y           | otherwise          = False -instance (Ord a) => Intervallic Interval a where+instance Intervallic Interval where   getInterval = id   setInterval _ x = x 
src/IntervalAlgebra/IntervalDiagram.hs view
@@ -11,7 +11,6 @@                 ------         ============================== ->>> import Data.Time >>> let ref = bi 30 (fromGregorian 2022 5 6) >>> let ivs = [ bi 2 (fromGregorian 2022 5 6), bi 5 (fromGregorian 2022 5 10)] >>> pretty $ simpleIntervalDiagram ref ivs @@ -49,6 +48,7 @@   -}     parseIntervalDiagram   , simpleIntervalDiagram+  , standardExampleDiagram    -- * Diagram options   , IntervalDiagramOptions(..)@@ -64,6 +64,9 @@   , AxisParseError(..)   , IntervalDiagramOptionsError(..)   , IntervalDiagramParseError(..)++  -- * Re-exports+  , Prettyprinter.Pretty(..)   ) where  import           Data.Foldable                  ( Foldable(toList) )@@ -73,13 +76,26 @@ import           Data.Maybe                     ( fromMaybe                                                 , isNothing                                                 )-import           Data.Text                      ( Text )+import           Data.Text                      ( Text+                                                , pack+                                                ) import           IntervalAlgebra.Core+import           IntervalAlgebra.IntervalUtilities+                                                ( rangeInterval )+import           IntervalAlgebra.PairedInterval ( PairedInterval+                                                , getPairData+                                                , makePairedInterval+                                                ) import           Prettyprinter import           Witch                          ( From(..)                                                 , into                                                 ) +-- $setup+-- >>> :set -XTypeApplications -XFlexibleContexts -XOverloadedStrings+-- >>> import IntervalAlgebra.IntervalUtilities (gapsWithin)+-- >>> import Data.Time+ {- The key Type in this module is the IntervalDiagram, which has several components.@@ -103,36 +119,35 @@ Moreover, the type @b@ should be castable to @Int@, using its @'Witch.From' b Int@  instance. ->>> import Prettyprinter (pretty)->>> import IntervalAlgebra (beginerval)->>> pretty $ MkIntervalText '-' (beginerval 5 (0::Int))+>>> pretty $ makeIntervalText '-' (beginerval 5 (0::Int)) ------>>> pretty $ MkIntervalText '*' (beginerval 10 (0::Int))+>>> pretty $ makeIntervalText '*' (beginerval 10 (0::Int)) ********** -}--- NOTE: This type *could* be a PairedInterval,--- but I didn't do that in order to reduce depeendencies.-data IntervalText a = MkIntervalText Char (Interval a)-  deriving (Eq, Show) -instance (Ord a) => Intervallic IntervalText a where-  getInterval (MkIntervalText _ x) = x-  setInterval (MkIntervalText c _) = MkIntervalText c+newtype IntervalText a = MkIntervalText (PairedInterval Char a) deriving (Eq, Show) -instance Functor IntervalText where-  fmap f (MkIntervalText c i) = MkIntervalText c (fmap f i)+makeIntervalText :: Char -> Interval a -> IntervalText a+makeIntervalText c = MkIntervalText . makePairedInterval c +instance Intervallic IntervalText where+  getInterval (MkIntervalText x) = getInterval x+  setInterval (MkIntervalText x) i = MkIntervalText $ setInterval x i+ instance (Enum b, IntervalSizeable a b) => Pretty (IntervalText a) where-  pretty (MkIntervalText c i) = pretty $ replicate (fromEnum (duration i)) c+  pretty (MkIntervalText x) = pretty $ replicate (fromEnum (duration i)) c+   where+    c = getPairData x+    i = getInterval x  instance From (Char, Interval a) (IntervalText a) where-  from = uncurry MkIntervalText+  from = uncurry makeIntervalText  instance From (IntervalText a) Char where-  from (MkIntervalText c _) = c+  from (MkIntervalText x) = getPairData x  instance From (IntervalText a) (Interval a) where-  from (MkIntervalText _ i) = i+  from = getInterval  {-------------------------------------------------------------------------------   IntervalTextLine@@ -147,39 +162,39 @@ which checks that the inputs are parsed correctly to form intervals  that will be pretty-printed correctly. ->>> let i1 =  MkIntervalText '*' (beginerval 10 (5::Int))->>> let i2  = MkIntervalText '-' (beginerval 2 (1::Int))+>>> let i1 =  makeIntervalText '*' (beginerval 10 (5::Int))+>>> let i2  = makeIntervalText '-' (beginerval 2 (1::Int)) >>> let x = parseIntervalTextLine [] [i1, i2]  >>> pretty x UnsortedIntervals->>> let i1 =  MkIntervalText '*' (beginerval 10 (5::Int))->>> let i2  = MkIntervalText '-' (beginerval 2 (10::Int))+>>> let i1 =  makeIntervalText '*' (beginerval 10 (5::Int))+>>> let i2  = makeIntervalText '-' (beginerval 2 (10::Int)) >>> let x = parseIntervalTextLine [] [i1, i2]  >>> pretty x ConcurringIntervals->>> let i1 =  MkIntervalText '*' (beginerval 10 ((-1)::Int))->>> let i2  = MkIntervalText '-' (beginerval 2 (10::Int))+>>> let i1 =  makeIntervalText '*' (beginerval 10 ((-1)::Int))+>>> let i2  = makeIntervalText '-' (beginerval 2 (10::Int)) >>> let x = parseIntervalTextLine []  [i1, i2]  >>> pretty x BeginsLessThanZero->>> let i1 =  MkIntervalText '*' (beginerval  5 (0::Int))->>> let i2  = MkIntervalText '-' (beginerval 2 (10::Int))+>>> let i1 =  makeIntervalText '*' (beginerval  5 (0::Int))+>>> let i2  = makeIntervalText '-' (beginerval 2 (10::Int)) >>> let x = parseIntervalTextLine [] [i1, i2] >>> pretty x *****     --->>> let i1 =  MkIntervalText '*' (beginerval  5 (5::Int))->>> let i2  = MkIntervalText '-' (beginerval 2 (10::Int))+>>> let i1 =  makeIntervalText '*' (beginerval  5 (5::Int))+>>> let i2  = makeIntervalText '-' (beginerval 2 (10::Int)) >>> let x = parseIntervalTextLine [] [i1, i2] >>> pretty x      *****--->>> let i1 =  MkIntervalText '*' (beginerval  1 (5::Int))->>> let i2  = MkIntervalText '-' (beginerval 1 (7::Int))+>>> let i1 =  makeIntervalText '*' (beginerval  1 (5::Int))+>>> let i2  = makeIntervalText '-' (beginerval 1 (7::Int)) >>> let x = parseIntervalTextLine [] [i1, i2] >>> pretty x      * -->>> let i1 =  MkIntervalText '*' (beginerval  3 (5::Int))->>> let i2 = MkIntervalText '-' (beginerval 5 (10::Int))->>> let i3 = MkIntervalText '#' (beginerval 1 17)+>>> let i1 =  makeIntervalText '*' (beginerval  3 (5::Int))+>>> let i2 = makeIntervalText '-' (beginerval 5 (10::Int))+>>> let i3 = makeIntervalText '#' (beginerval 1 17) >>> pretty $ parseIntervalTextLine [] [i1, i2, i3]      ***  -----  # -}@@ -311,7 +326,7 @@  Use 'parseAxis' for construction. ->>> let ref = MkIntervalText '=' (beginerval 10 (0::Int))+>>> let ref = makeIntervalText '=' (beginerval 10 (0::Int))    >>> let b = parseAxis [] (Just Top) ref@@ -563,7 +578,6 @@ Here's a basic diagram that shows how to put more than one interval interval on a line: ->>> :set -XTypeApplications -XFlexibleContexts -XOverloadedStrings >>> let mkIntrvl c d b = into @(IntervalText Int) (c, bi d (b :: Int)) >>> let x = mkIntrvl  '=' 20 0 >>> let l1 = [ mkIntrvl '-' 1 4 ]@@ -575,6 +589,7 @@                   ## ==================== + We can put the axis on the top:  >>> pretty $ parseIntervalDiagram defaultIntervalDiagramOptions [] (Just Top) x [ (l1, []), (l2, []), (l3, []) ]@@ -584,7 +599,6 @@                   ##  - We can annotate the axis:  >>> pretty $ parseIntervalDiagram defaultIntervalDiagramOptions [(5, 'a')] (Just Bottom) x [ (l1, []), (l2, []), (l3, []) ]@@ -672,7 +686,7 @@     Shifts the endpoints of an interval to be referenced from another interval,     so that the 'begin' of the reference interval acts as the "zero" point.   -}-  rereference x = fmap (fromEnum . (`diff` begin x))+  rereference x = fromEnumInterval . shiftFromBegin x   rereferenceL x = fmap (rereference x)  {-|@@ -680,8 +694,6 @@ produces an 'IntervalDiagram' with one line per interval, using the 'defaultIntervalDiagramOptions'.  ->>> import Data.Maybe (fromMaybe)->>> import IntervalAlgebra.IntervalUtilities (gapsWithin) >>> pretty $ simpleIntervalDiagram (bi 10 (0 :: Int)) (fmap (bi 1) [0..9]) -  -@@ -711,7 +723,7 @@  -} simpleIntervalDiagram-  :: (Ord a, IntervalSizeable a b, Intervallic i a, Enum b)+  :: (Ord a, IntervalSizeable a b, Intervallic i, Enum b)   => i a -- ^ The axis interval   -> [i a] -- ^ List of intervals to be printed one per line   -> Either IntervalDiagramParseError (IntervalDiagram a)@@ -719,5 +731,66 @@   defaultIntervalDiagramOptions   []   (Just Bottom)-  (MkIntervalText '=' (getInterval ref))-  (fmap (\x -> (pure $ MkIntervalText '-' $ getInterval x, [])) ivs)+  (makeIntervalText '=' (getInterval ref))+  (fmap (\x -> (pure $ makeIntervalText '-' $ getInterval x, [])) ivs)++{- | Given various inputs containing intervals and their label, creates an+interval diagram with labels, along with a reference range that spans all of the+intervals and is extended to include 0 if necesary.++In more detail, an interval diagram is created with one row in the diagram for+each interval and label pair provided as the first input, and followed by a+sequence of additional rows with one row per list element in the second input+and such that each row displays each interval provided in the intervals list and+label pair.++>>> x1 = si (1, 5)+>>> x2 = si (7, 10)+>>> x3 = si (13, 15)+>>> ivs = [x1, x2, x3]+>>> gaps = [si (5, 7), si (10, 13)]+>>> :{+pretty $ standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) [(gaps, "gaps")]+:}+ ----           <- [x1]+       ---      <- [x2]+             -- <- [x3]+     --   ---   <- [gaps]+===============++>>> :{+pretty $ standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) []+:}+ ----           <- [x1]+       ---      <- [x2]+             -- <- [x3]+===============++>>> pretty $ standardExampleDiagram [] [(gaps, "gaps")]+     --   --- <- [gaps]+=============++>>> pretty $ standardExampleDiagram [] []+IntervalsExtendBeyondAxis+-}+standardExampleDiagram+  :: (Num a, Ord a, Enum b, IntervalSizeable a b)+  => [(Interval a, String)]+  -> [([Interval a], String)]+  -> Either IntervalDiagramParseError (IntervalDiagram a)+standardExampleDiagram ivs livs = op ref+ where+  op Nothing     = Left IntervalsExtendBeyondAxis+  op (Just ref') = parseIntervalDiagram defaultIntervalDiagramOptions+                                        []+                                        (Just Bottom)+                                        ref'+                                        combIvs+  range         = rangeInterval $ map fst ivs ++ concatMap fst livs+  anchoredRange = case range of+    Nothing  -> Nothing+    (Just x) -> Just $ safeInterval (min (begin x) 0, max (end x) 0)+  ref = fmap (makeIntervalText '=') anchoredRange+  f (iv, s) = ([iv], s)+  g (ivs, s) = (map (makeIntervalText '-') ivs, [pack s])+  combIvs = map (g . f) ivs ++ map g livs
src/IntervalAlgebra/IntervalUtilities.hs view
@@ -12,7 +12,7 @@ {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TupleSections #-}-+{-# LANGUAGE ScopedTypeVariables #-}  module IntervalAlgebra.IntervalUtilities   (@@ -20,6 +20,8 @@     -- * Fold over sequential intervals     combineIntervals   , combineIntervalsL+  , combineIntervalsFromSorted+  , combineIntervalsFromSortedL   , rangeInterval   , gaps   , gapsL@@ -55,7 +57,7 @@   , filterNotDisjoint   , filterConcur   , filterWithin-  , filterEnclose+  , filterEncloses   , filterEnclosedBy      -- * Functions for manipulating intervals@@ -90,7 +92,12 @@                                                 , (||)                                                 ) import safe      Data.Eq                        ( Eq((==)) )-import safe      Data.Foldable                  ( Foldable(foldl', null, toList)+import safe      Data.Foldable                  ( Foldable+                                                  ( foldl'+                                                  , foldr+                                                  , null+                                                  , toList+                                                  )                                                 , all                                                 , any                                                 , or@@ -99,6 +106,10 @@                                                 , (.)                                                 , flip                                                 )+import safe      Data.List                      ( map+                                                , reverse+                                                , sortOn+                                                ) import safe      Data.Maybe                     ( Maybe(..)                                                 , maybe                                                 , maybeToList@@ -119,10 +130,7 @@                                                 , ComparativePredicateOf1                                                 , ComparativePredicateOf2                                                 , Interval-                                                , IntervalCombinable-                                                  ( (<+>)-                                                  , (><)-                                                  )+                                                , IntervalCombinable((><))                                                 , IntervalRelation(..)                                                 , IntervalSizeable                                                   ( diff@@ -134,12 +142,13 @@                                                 , begin                                                 , beginerval                                                 , beginervalFromEnd+                                                , bi                                                 , concur                                                 , contains                                                 , disjoint                                                 , during-                                                , enclose                                                 , enclosedBy+                                                , encloses                                                 , end                                                 , enderval                                                 , endervalFromBegin@@ -173,15 +182,16 @@                                                 , mapMaybe                                                 ) +{- $setup+>>> import GHC.List ( (++), zip )+>>> import IntervalAlgebra.IntervalDiagram+>>> import Prettyprinter ( pretty )+-}  ------------------------------------------------- -- Unexported utilties used in functions below -- ------------------------------------------------- --- Just a synonym used to examples to save typing-iv :: Int -> Int -> Interval Int-iv = beginerval- -- An internal utility function for creating a @Fold@ that maps over a structure -- by consecutive pairs into a new structure. makeFolder :: (Monoid (m b), Applicative m) => (a -> a -> b) -> L.Fold a (m b)@@ -201,7 +211,7 @@      , Applicative t      , Witherable.Witherable t      , IntervalSizeable a b-     , Intervallic i0 a+     , Intervallic i0      , IntervalCombinable i1 a      )   => ((b -> Bool) -> t b -> Bool)@@ -213,7 +223,7 @@ -- | Gets the durations of gaps (via 'IntervalAlgebra.(><)') between all pairs --   of the input. pairGaps-  :: (Intervallic i a, IntervalSizeable a b, IntervalCombinable i a)+  :: (Intervallic i, IntervalSizeable a b, IntervalCombinable i a)   => [i a]   -> [Maybe b] pairGaps es = fmap (fmap duration . uncurry (><)) (pairs es)@@ -233,7 +243,7 @@ -- >>> lookback 4 (beginerval 10 (1 :: Int)) -- (-3, 1) lookback-  :: (Intervallic i a, IntervalSizeable a b)+  :: (Intervallic i, IntervalSizeable a b)   => b   -- ^ lookback duration   -> i a   -> Interval a@@ -245,7 +255,7 @@ -- >>> lookahead 4 (beginerval 1 (1 :: Int)) -- (2, 6) lookahead-  :: (Intervallic i a, IntervalSizeable a b)+  :: (Intervallic i, IntervalSizeable a b)   => b   -- ^ lookahead duration   -> i a   -> Interval a@@ -255,7 +265,7 @@ --   specified duration among the input intervals? anyGapsWithinAtLeastDuration   :: ( IntervalSizeable a b-     , Intervallic i0 a+     , Intervallic i0      , IntervalCombinable i1 a      , Monoid (t (Interval a))      , Monoid (t (Maybe (Interval a)))@@ -275,7 +285,7 @@ -- True allGapsWithinLessThanDuration   :: ( IntervalSizeable a b-     , Intervallic i0 a+     , Intervallic i0      , IntervalCombinable i1 a      , Monoid (t (Interval a))      , Monoid (t (Maybe (Interval a)))@@ -304,21 +314,27 @@ -- | Returns a list of the 'IntervalRelation' between each consecutive pair  --   of intervals. This is just a specialized 'relations' which returns a list. ----- >>> relationsL [iv 1 0, iv 1 1] +-- >>> relationsL [bi 1 0, bi 1 1] -- [Meets] ---relationsL :: (Foldable f, Intervallic i a) => f (i a) -> [IntervalRelation]+relationsL+  :: (Foldable f, Ord a, Intervallic i) => f (i a) -> [IntervalRelation] relationsL = relations  -- | A generic form of 'relations' which can output any 'Applicative' and  --   'Monoid' structure. ----- >>> (relations [iv 1 0,iv 1 1]) :: [IntervalRelation]+-- >>> (relations [bi 1 0,bi 1 1]) :: [IntervalRelation] -- [Meets] -- -- relations-  :: (Foldable f, Applicative m, Intervallic i a, Monoid (m IntervalRelation))+  :: ( Foldable f+     , Applicative m+     , Ord a+     , Intervallic i+     , Monoid (m IntervalRelation)+     )   => f (i a)   -> m IntervalRelation relations = L.fold (makeFolder relate)@@ -327,11 +343,11 @@ -- | Forms a 'Just' new interval from the intersection of two intervals,  --   provided the intervals are not disjoint. -- --- >>> intersect (iv 5 0) (iv 2 3)+-- >>> intersect (bi 5 0) (bi 2 3) -- Just (3, 5) -- intersect-  :: (Intervallic i a, IntervalSizeable a b) => i a -> i a -> Maybe (Interval a)+  :: (Intervallic i, IntervalSizeable a b) => i a -> i a -> Maybe (Interval a) intersect x y | disjoint x y = Nothing               | otherwise    = Just $ beginerval (diff e b) b  where@@ -351,13 +367,45 @@ gapsM = L.fold (makeFolder (\i j -> getInterval i >< getInterval j)) {-# INLINABLE gapsM #-} --- | Returns a @Maybe@ container of intervals consisting of the gaps ---   between intervals in the input. *To work properly, the input should be---   sorted*. See 'gapsL' for a version that always returns a list.------ >>> gaps [iv 4 1, iv 4 8, iv 3 11]--- Nothing---+{- | Returns a @Maybe@ container of intervals consisting of the gaps between+intervals in the input. __To work properly, the input should be sorted.__ See+'gapsL' for a version that always returns a list.++>>> x1 = bi 4 1+>>> x2 = bi 4 8+>>> x3 = bi 3 11+>>> ivs = [x1, x2, x3]+>>> ivs+[(1, 5),(8, 12),(11, 14)]+>>> gaps ivs+Nothing+>>> pretty $ standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) []+ ----          <- [x1]+        ----   <- [x2]+           --- <- [x3]+==============++>>> x1 = bi 4 1+>>> x2 = bi 3 7+>>> x3 = bi 2 13+>>> ivs = [x1, x2, x3]+>>> ivs+[(1, 5),(7, 10),(13, 15)]+>>> gapIvs = gaps ivs+>>> gapIvs+Just [(5, 7),(10, 13)]+>>> :{+case gapIvs of+  Nothing -> pretty ""+  (Just x) -> pretty $+    standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) [(x, "gapIvs")]+:}+ ----           <- [x1]+       ---      <- [x2]+             -- <- [x3]+     --   ---   <- [gapIvs]+===============+-} gaps   :: ( IntervalCombinable i a      , Traversable f@@ -369,10 +417,47 @@ gaps = sequenceA . gapsM {-# INLINABLE gaps #-} --- | Returns a (possibly empty) list of intervals consisting of the gaps between---   intervals in the input container. *To work properly, the input should be ---   sorted*. This version outputs a list. See 'gaps' for a version that lifts---   the result to same input structure @f@.+{- | Returns a (possibly empty) list of intervals consisting of the gaps between+intervals in the input container.+__To work properly, the input should be sorted.__ This version outputs a list.+See 'gaps' for a version that lifts the result to same input structure @f@.++>>> x1 = bi 4 1+>>> x2 = bi 4 8+>>> x3 = bi 3 11+>>> ivs = [x1, x2, x3]+>>> ivs+[(1, 5),(8, 12),(11, 14)]+>>> gapIvs = gapsL ivs+>>> gapIvs+[]+>>> :{+pretty $ standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) []+:}+ ----          <- [x1]+        ----   <- [x2]+           --- <- [x3]+==============++>>> x1 = bi 4 1+>>> x2 = bi 3 7+>>> x3 = bi 2 13+>>> ivs = [x1, x2, x3]+>>> ivs+[(1, 5),(7, 10),(13, 15)]+>>> gapIvs = gapsL ivs+>>> gapIvs+[(5, 7),(10, 13)]+>>> :{+pretty $+  standardExampleDiagram (zip ivs ["x1", "x2", "x3"]) [(gapIvs, "gapIvs")]+:}+ ----           <- [x1]+       ---      <- [x2]+             -- <- [x3]+     --   ---   <- [gapIvs]+===============+-} gapsL   :: ( IntervalCombinable i a      , Applicative f@@ -386,23 +471,22 @@  -- | Returns the 'duration' of each 'Intervallic i a' in the 'Functor' @f@. ----- >>> durations [iv 9 1, iv 10 2, iv 1 5]+-- >>> durations [bi 9 1, bi 10 2, bi 1 5 :: Interval Int] -- [9,10,1] ---durations-  :: (Functor f, Intervallic i a, IntervalSizeable a b) => f (i a) -> f b+durations :: (Functor f, Intervallic i, IntervalSizeable a b) => f (i a) -> f b durations = fmap duration  -- | In the case that x y are not disjoint, clips y to the extent of x. -- --- >>> clip (iv 5 0) (iv 3 3)+-- >>> clip (bi 5 0) ((bi 3 3) :: Interval Int) -- Just (3, 5) ----- >>> clip (iv 3 0) (iv 2 4)+-- >>> clip (bi 3 0) ((bi 2 4) :: Interval Int) -- Nothing -- clip-  :: (Intervallic i0 a, Intervallic i1 a, IntervalSizeable a b)+  :: (Intervallic i0, Intervallic i1, IntervalSizeable a b)   => i0 a   -> i1 a   -> Maybe (Interval a)@@ -417,14 +501,14 @@   jx = starts <|> during <|> finishes {-# INLINABLE clip #-} --- | Applies 'gaps' to all the non-disjoint intervals in @x@ that are *not* disjoint+-- | Applies 'gaps' to all the non-disjoint intervals in @x@ that are /not/ disjoint -- from @i@. Intervals that 'overlaps' or are 'overlappedBy' @i@ are 'clip'ped  -- to @i@, so that all the intervals are 'within' @i@. If all of the input intervals  -- are disjoint from the focal interval or if the input is empty, then 'Nothing'  -- is returned. When there are no gaps among the concurring intervals, then --- `Just mempty` (e.g. `Just []`) is returned.+-- @Just mempty@ (e.g. @Just []@) is returned. ----- >>> gapsWithin (iv 9 1) [iv 5 0, iv 2 7, iv 3 12]+-- >>> gapsWithin (bi 9 1) [bi 5 0, bi 2 7, bi 3 12] -- Just [(5, 7),(9, 10)] -- gapsWithin@@ -433,7 +517,7 @@      , Monoid (f (Interval a))      , Monoid (f (Maybe (Interval a)))      , IntervalSizeable a b-     , Intervallic i0 a+     , Intervallic i0      , IntervalCombinable i1 a      )   => i0 a  -- ^ i@@ -448,72 +532,153 @@   res = catMaybes $ gapsM (s <> ivs <> e) {-# INLINABLE gapsWithin #-} --- The Box is an internal type used to hold accumulated, combined intervals in --- 'combineIntervalsL'.-newtype Box a = Box { unBox :: [a] }+{- | Returns a container of intervals where any intervals that meet or share+support are combined into one interval. This functions sorts the input intervals+first. See @combineIntervalsL@ for a version that works only on lists. If you+know the input intervals are sorted, use @combineIntervalsFromSorted@ instead. -packIntervalBoxes :: (Intervallic i a) => [i a] -> [Box (Interval a)]-packIntervalBoxes = fmap (\z -> Box [getInterval z])+>>> x1 = bi 10 0+>>> x2 = bi 5 2+>>> x3 = bi 2 10+>>> x4 = bi 2 13+>>> ivs = [x1, x2, x3, x4]+>>> ivs+[(0, 10),(2, 7),(10, 12),(13, 15)]+>>> xComb = combineIntervals ivs+>>> xComb+[(0, 12),(13, 15)]+>>> :{+pretty $+  standardExampleDiagram+    (zip ivs ["x1", "x2", "x3", "x4"])+    [(xComb, "xComb")]+:}+----------      <- [x1]+  -----         <- [x2]+          --    <- [x3]+             -- <- [x4]+------------ -- <- [xComb]+===============+-}+combineIntervals+  :: (Applicative f, Ord a, Intervallic i, Monoid (f (Interval a)), Foldable f)+  => f (i a)+  -> f (Interval a)+combineIntervals = combineIntervalsWith combineIntervalsL -instance (Ord a) => Semigroup (Box (Interval a)) where-  Box x <> Box y = Box $ listCombiner (<->) x y+{- | Returns a container of intervals where any intervals that meet or share+support are combined into one interval. The condition is applied cumulatively,+from left to right, so+__to work properly, the input list should be sorted in increasing order__. See+@combineIntervalsLFromSorted@ for a version that works only on lists. --- | Returns a container of intervals where any intervals that meet or share support---   are combined into one interval. *To work properly, the input should ---   be sorted*. See 'combineIntervalsL' for a version that works only on lists.------ >>> combineIntervals [iv 10 0, iv 5 2, iv 2 10, iv 2 13]--- [(0, 12),(13, 15)]----combineIntervals-  :: ( Applicative f-     , Ord a-     , Intervallic i a-     , Monoid (f (Interval a))-     , Foldable f-     )+>>> combineIntervalsFromSorted [bi 10 0, bi 5 2, bi 2 10, bi 2 13]+[(0, 12),(13, 15)]+-}+combineIntervalsFromSorted+  :: (Applicative f, Ord a, Intervallic i, Monoid (f (Interval a)), Foldable f)   => f (i a)   -> f (Interval a)-combineIntervals x =-  foldl' (\x y -> x <> pure y) mempty (combineIntervalsL $ toList x)-  -- TODO: surely combineIntervals and combineIntervalsL could be combined-{-# INLINABLE combineIntervals #-}+combineIntervalsFromSorted = combineIntervalsWith combineIntervalsFromSortedL --- | Returns a list of intervals where any intervals that meet or share support---   are combined into one interval. *To work properly, the input list should ---   be sorted*. ------ >>> combineIntervalsL [iv 10 0, iv 5 2, iv 2 10, iv 2 13]--- [(0, 12),(13, 15)]----combineIntervalsL :: (Intervallic i a) => [i a] -> [Interval a]-combineIntervalsL l = unBox $ foldl' (<>) (Box []) (packIntervalBoxes l)-{-# INLINABLE combineIntervalsL #-}+-- | Unexported helper+combineIntervalsWith+  :: (Applicative f, Ord a, Intervallic i, Monoid (f (Interval a)), Foldable f)+  => ([i a] -> [Interval a])+  -> f (i a)+  -> f (Interval a)+combineIntervalsWith f x = foldl' (\x y -> x <> pure y) mempty (f $ toList x) --- |--- Maybe form an @Interval a@ from @Control.Foldl t => t (Interval a)@ spanning--- the range of all intervals in the list, i.e.  whose @begin@ is the minimum--- of @begin@ across intervals in the list and whose @end@ is the maximum of--- @end@. ------ >>> rangeInterval [beginerval 0 0, beginerval 0 (-1)]--- Just (-1, 1)--- >>> rangeInterval ([] :: [Interval Int])--- Nothing--- >>> rangeInterval (Just (beginerval 0 0))--- Just (0, 1)+{- | Returns a list of intervals where any intervals that meet or share support+are combined into one interval. This function sorts the input. If you know the+input intervals are sorted, use @combineIntervalsLFromSorted@.++>>> x1 = bi 10 0+>>> x2 = bi 5 2+>>> x3 = bi 2 10+>>> x4 = bi 2 13+>>> ivs = [x1, x2, x3, x4]+>>> ivs+[(0, 10),(2, 7),(10, 12),(13, 15)]+>>> xComb = combineIntervalsL ivs+>>> xComb+[(0, 12),(13, 15)]+>>> :{+pretty $+  standardExampleDiagram+    (zip ivs ["x1", "x2", "x3", "x4"])+    [(xComb, "xComb")]+:}+----------      <- [x1]+  -----         <- [x2]+          --    <- [x3]+             -- <- [x4]+------------ -- <- [xComb]+===============+-}+combineIntervalsL :: (Intervallic i, Ord a) => [i a] -> [Interval a]+combineIntervalsL = combineIntervalsFromSortedL . sortOn getInterval++{- | Returns a list of intervals where any intervals that meet or share support+are combined into one interval. The operation is applied cumulatively, from left+to right, so+__to work properly, the input list should be sorted in increasing order__.++>>> combineIntervalsFromSortedL [bi 10 0, bi 5 2, bi 2 10, bi 2 13]+[(0, 12),(13, 15)]++>>> combineIntervalsFromSortedL [bi 10 0, bi 5 2, bi 0 8]+[(0, 10)]+-}+combineIntervalsFromSortedL+  :: forall a i . (Ord a, Intervallic i) => [i a] -> [Interval a]+combineIntervalsFromSortedL = reverse . foldl' op []+ where+  op []       y = [getInterval y]+  op (x : xs) y = if x `before` y+    -- Since x <= y, not (x `before` y) iff they meet or share support+    then yiv : x : xs+    else extenterval x yiv : xs+    where yiv = getInterval y++{- | @Maybe@ form an @Interval a@ from @Control.Foldl t => t (Interval a)@+spanning the range of all intervals in the list, i.e. whose @begin@ is the+minimum of @begin@ across intervals in the list and whose @end@ is the maximum+of @end@.++>>> rangeInterval ([] :: [Interval Int])+Nothing++>>> x1 = bi 2 2+>>> x2 = bi 3 6+>>> x3 = bi 4 7+>>> ivs = [x1, x2, x3] :: [Interval Int]+>>> ivs+[(2, 4),(6, 9),(7, 11)]+>>> spanIv = rangeInterval ivs+>>> spanIv+Just (2, 11)+>>> :{+case spanIv of+  Nothing -> pretty ""+  (Just x) -> pretty $ standardExampleDiagram+    (zip (ivs ++ [x]) ["x1", "x2", "x3", "spanIv"])+    []+:}+  --        <- [x1]+      ---   <- [x2]+       ---- <- [x3]+  --------- <- [spanIv]+===========++>>> rangeInterval Nothing+Nothing+>>> rangeInterval (Just (bi 1 0))+Just (0, 1)+-} rangeInterval :: (Ord a, L.Foldable t) => t (Interval a) -> Maybe (Interval a) rangeInterval = L.fold (liftA2 extenterval <$> L.minimum <*> L.maximum) --- Internal function for combining maybe intervals in the 'combineIntervalsL' --- function-(<->) :: (IntervalCombinable i a) => Maybe (i a) -> Maybe (i a) -> [Interval a]-(<->) Nothing  Nothing  = []-(<->) Nothing  (Just y) = [getInterval y]-(<->) (Just x) Nothing  = [getInterval x]-(<->) (Just x) (Just y) = (<+>) (getInterval x) (getInterval y)-{-# INLINABLE (<->) #-}- -- | Given a predicate combinator, a predicate, and list of intervals, returns  --   the input unchanged if the predicate combinator is @True@. Otherwise, returns --   an empty list. See 'nothingIfAny' and 'nothingIfNone' for examples.@@ -532,12 +697,12 @@ -- For example, the following returns 'Nothing' because none of the intervals -- in the input list 'starts' (3, 5). ----- >>> nothingIfNone (starts (iv 2 3)) [iv 1 3, iv 1 5]+-- >>> nothingIfNone (starts (bi 2 3)) [bi 1 3, bi 1 5] -- Nothing -- -- In the following, (3, 5) 'starts' (3, 6), so 'Just' the input is returned. ----- >>> nothingIfNone (starts (iv 2 3)) [iv 3 3, iv 1 5]+-- >>> nothingIfNone (starts (bi 2 3)) [bi 3 3, bi 1 5] -- Just [(3, 6),(5, 6)] -- nothingIfNone@@ -549,10 +714,10 @@  -- | Returns 'Nothing' if *any* of the element of input satisfy the predicate condition. ----- >>> nothingIfAny (startedBy (iv 2 3)) [iv 3 3, iv 1 5]+-- >>> nothingIfAny (startedBy (bi 2 3)) [bi 3 3, bi 1 5] -- Just [(3, 6),(5, 6)] ----- >>> nothingIfAny (starts (iv 2 3)) [iv 3 3, iv 1 5]+-- >>> nothingIfAny (starts (bi 2 3)) [bi 3 3, bi 1 5] -- Nothing -- nothingIfAny@@ -564,7 +729,7 @@  -- | Returns 'Nothing' if *all* of the element of input satisfy the predicate condition. ----- >>> nothingIfAll (starts (iv 2 3)) [iv 3 3, iv 4 3]+-- >>> nothingIfAll (starts (bi 2 3)) [bi 3 3, bi 4 3] -- Nothing -- nothingIfAll@@ -577,7 +742,7 @@ -- | Creates a function for filtering a 'Witherable.Filterable' of @i1 a@s  --   by comparing the @Interval a@s that of an @i0 a@.  makeFilter-  :: (Filterable f, Intervallic i0 a, Intervallic i1 a)+  :: (Filterable f, Intervallic i0, Intervallic i1)   => ComparativePredicateOf2 (i0 a) (i1 a)   -> i0 a   -> (f (i1 a) -> f (i1 a))@@ -588,8 +753,8 @@ a (potentially different) 'Intervallic' type using the corresponding interval predicate function. -}-filterOverlaps, filterOverlappedBy, filterBefore, filterAfter, filterStarts, filterStartedBy, filterFinishes, filterFinishedBy, filterMeets, filterMetBy, filterDuring, filterContains, filterEquals, filterDisjoint, filterNotDisjoint, filterConcur, filterWithin, filterEnclose, filterEnclosedBy-  :: (Filterable f, Intervallic i0 a, Intervallic i1 a)+filterOverlaps, filterOverlappedBy, filterBefore, filterAfter, filterStarts, filterStartedBy, filterFinishes, filterFinishedBy, filterMeets, filterMetBy, filterDuring, filterContains, filterEquals, filterDisjoint, filterNotDisjoint, filterConcur, filterWithin, filterEncloses, filterEnclosedBy+  :: (Filterable f, Ord a, Intervallic i0, Intervallic i1)   => i0 a   -> f (i1 a)   -> f (i1 a)@@ -610,7 +775,7 @@ filterNotDisjoint = makeFilter notDisjoint filterConcur = makeFilter concur filterWithin = makeFilter within-filterEnclose = makeFilter enclose+filterEncloses = makeFilter encloses filterEnclosedBy = makeFilter enclosedBy  -- | Folds over a list of Paired Intervals and in the case that the 'getPairData' @@ -644,7 +809,7 @@ packMeeting = fmap (\z -> Meeting [z])  -- Test a list of intervals to be sure they all meet; if not return Nothing.-parseMeeting :: Intervallic i a => [i a] -> Maybe (Meeting [i a])+parseMeeting :: (Ord a, Intervallic i) => [i a] -> Maybe (Meeting [i a]) parseMeeting x | all (== Meets) (relationsL x) = Just $ Meeting x                | otherwise                     = Nothing @@ -658,7 +823,7 @@  -- A general function for combining any two @Meeting [i a]@ by 'listCombiner'. joinMeeting-  :: Intervallic i a+  :: (Ord a, Intervallic i)   => ComparativePredicateOf1 (i a)   -> Meeting [i a]   -> Meeting [i a]@@ -669,7 +834,7 @@ -- The intervals @x@ and @y@ should meet! The predicate function @p@ determines -- when the two intervals that meet should be combined. join2MeetingWhen-  :: Intervallic i a+  :: (Ord a, Intervallic i)   => ComparativePredicateOf1 (i a)   -> Maybe (i a)   -> Maybe (i a)@@ -789,4 +954,3 @@  hasEqData :: (Eq b) => [PairedInterval b a] -> Bool hasEqData x = or (L.fold (makeFolder (==)) (fmap getPairData x) :: [Bool])-
src/IntervalAlgebra/PairedInterval.hs view
@@ -25,12 +25,12 @@  import safe      Control.Applicative            ( liftA2 ) import safe      Control.DeepSeq                ( NFData )-import safe      Data.Bifunctor                 ( Bifunctor(bimap) ) import safe      Data.Binary                    ( Binary ) import safe      GHC.Generics                   ( Generic ) import safe      IntervalAlgebra.Core           ( ComparativePredicateOf1                                                 , Interval                                                 , IntervalCombinable(..)+                                                , IntervalSizeable                                                 , Intervallic(..)                                                 , before                                                 , extenterval@@ -42,15 +42,9 @@ newtype PairedInterval b a = PairedInterval (Interval a, b)     deriving (Eq, Generic) -instance (Ord a) => Intervallic (PairedInterval b) a where+instance Intervallic (PairedInterval b) where   getInterval (PairedInterval x) = fst x   setInterval (PairedInterval (x, y)) i = PairedInterval (i, y)--instance Functor (PairedInterval b) where-  fmap f (PairedInterval (x, y)) = PairedInterval (fmap f x, y)--instance Bifunctor PairedInterval where-  bimap f g (PairedInterval (x, y)) = PairedInterval (fmap g x, f y)  instance (NFData a, NFData b) => NFData (PairedInterval b a) instance (Binary a, Binary b) => Binary (PairedInterval b a)
src/IntervalAlgebra/RelationProperties.hs view
@@ -145,11 +145,11 @@         -> Property     prop_enclosedBy_predicate = prop_predicate_unions withinRelations enclosedBy -    prop_enclose_predicate :: (Ord a) =>+    prop_encloses_predicate :: (Ord a) =>           Interval a         -> Interval a         -> Property-    prop_enclose_predicate = prop_predicate_unions (converse withinRelations) enclose+    prop_encloses_predicate = prop_predicate_unions (converse withinRelations) encloses  instance IntervalRelationProperties Int Int instance IntervalRelationProperties Day Integer
test-relation-properties/RelationPropertiesSpec.hs view
@@ -32,7 +32,7 @@         it "during" $ property (prop_IAduring @Int)         it "disjoint" $ property (prop_disjoint_predicate @Int)         it "within" $ property (prop_within_predicate @Int)-        it "enclose" $ property (prop_enclose_predicate @Int)+        it "encloses" $ property (prop_encloses_predicate @Int)         it "enclosedBy" $ property (prop_enclosedBy_predicate @Int)         it "notDisjoint" $ property (prop_notdisjoint_predicate @Int)         it "concur" $ property (prop_concur_predicate @Int)@@ -47,7 +47,7 @@         it "during" $ property (prop_IAduring @Day)         it "disjoint" $ property (prop_disjoint_predicate @Day)         it "within" $ property (prop_within_predicate @Day)-        it "enclose" $ property (prop_enclose_predicate @Day)+        it "encloses" $ property (prop_encloses_predicate @Day)         it "enclosedBy" $ property (prop_enclosedBy_predicate @Day)         it "notDisjoint" $ property (prop_notdisjoint_predicate @Day)         it "concur" $ property (prop_concur_predicate @Day)@@ -62,7 +62,7 @@         it "during" $ property (prop_IAduring @UTCTime)         it "disjoint" $ property (prop_disjoint_predicate @UTCTime)         it "within" $ property (prop_within_predicate @UTCTime)-        it "enclose" $ property (prop_enclose_predicate @UTCTime)+        it "encloses" $ property (prop_encloses_predicate @UTCTime)         it "enclosedBy" $ property (prop_enclosedBy_predicate @UTCTime)         it "notDisjoint" $ property (prop_notdisjoint_predicate @UTCTime)         it "concur" $ property (prop_concur_predicate @UTCTime)
test/IntervalAlgebra/IntervalUtilitiesSpec.hs view
@@ -45,6 +45,7 @@ import           IntervalAlgebra.IntervalUtilities                                                 ( clip                                                 , combineIntervals+                                                , combineIntervalsFromSorted                                                 , durations                                                 , filterAfter                                                 , filterBefore@@ -52,8 +53,8 @@                                                 , filterContains                                                 , filterDisjoint                                                 , filterDuring-                                                , filterEnclose                                                 , filterEnclosedBy+                                                , filterEncloses                                                 , filterEquals                                                 , filterFinishedBy                                                 , filterFinishes@@ -172,7 +173,7 @@     pure $ IntervalReferenced refIv rels iv  -- Testing functions-checkSeqStates :: (Intervallic i Int) => [i Int] -> Bool+checkSeqStates :: (Intervallic i) => [i Int] -> Bool checkSeqStates x = (length x > 1) || all (== Meets) (relationsL x)  -- Creation functions@@ -438,10 +439,10 @@       -> Property    prop_filterEnclosedBy = prop_filtration filterEnclosedBy withinRelations -   prop_filterEnclose :: Interval a+   prop_filterEncloses :: Interval a       -> [Interval a]       -> Property-   prop_filterEnclose = prop_filtration filterEnclose (converse withinRelations)+   prop_filterEncloses = prop_filtration filterEncloses (converse withinRelations)     prop_filterConcur :: Interval a       -> [Interval a]@@ -568,7 +569,7 @@     it "filterNotDisjoint property" $ property (prop_filterNotDisjoint @Int)     it "filterWithin property" $ property (prop_filterWithin @Int)     it "filterConcur property" $ property (prop_filterConcur @Int)-    it "filterEnclose property" $ property (prop_filterEnclose @Int)+    it "filterEncloses property" $ property (prop_filterEncloses @Int)     it "filterEnclosedBy property" $ property (prop_filterEnclosedBy @Int)    describe "nothingIf unit tests" $ do@@ -656,8 +657,14 @@     it "combineIntervals [] should be []"       $          combineIntervals ([] :: [Interval Int])       `shouldBe` []-    it "combineIntervals [(0, 10), (2, 7), (10, 12), (13, 15)]"+    it "combineIntervals works on sorted intervals"       $          combineIntervals [iv 10 0, iv 5 2, iv 2 10, iv 2 13]+      `shouldBe` [iv 12 0, iv 2 13]+    it "combineIntervalsFromSorted works on sorted intervals"+      $          combineIntervalsFromSorted [iv 10 0, iv 5 2, iv 2 10, iv 2 13]+      `shouldBe` [iv 12 0, iv 2 13]+    it "combineIntervals works on unsorted intervals"+      $          combineIntervals [iv 2 13, iv 10 0, iv 2 10, iv 5 2]       `shouldBe` [iv 12 0, iv 2 13]    describe "combineIntervals property tests" $ modifyMaxSuccess (* 10) $ do
test/IntervalAlgebra/PairedIntervalSpec.hs view
@@ -2,7 +2,6 @@   ( spec   ) where -import           Data.Bifunctor                 ( Bifunctor(bimap) ) import           Data.Bool import           Data.Time                      ( Day(ModifiedJulianDay)                                                 , fromGregorian@@ -12,6 +11,7 @@                                                 , before                                                 , beginerval                                                 , equals+                                                , toEnumInterval                                                 ) import           IntervalAlgebra.PairedInterval ( Empty(..)                                                 , PairedInterval@@ -43,15 +43,11 @@   describe "Basic tests of paired intervals" $ do     it "the same pairInterval should be equal" $ t1 == t1 `shouldBe` True     it "different pairInterval should not be equal" $ t1 /= t2 `shouldBe` True-    it "fmapping into a different interval type"-      $ fmap ModifiedJulianDay (makePairedInterval "hi" (beginerval 5 0))+    -- NOTE toEnum (fromGregorian 1858 11 17) is 0, since that date is the+    -- origin in the modified Julian calendar.+    it "toEnumInterval into PairedInterval b Day"+      $          toEnumInterval (makePairedInterval "hi" (beginerval 5 0))       `shouldBe` makePairedInterval "hi"-                                    (beginerval 5 (fromGregorian 1858 11 17))-    it "bimapping into a different type"-      $          bimap (== "hi")-                       ModifiedJulianDay-                       (makePairedInterval "hi" (beginerval 5 0))-      `shouldBe` makePairedInterval True                                     (beginerval 5 (fromGregorian 1858 11 17))     it "show paired interval" $ show t1 `shouldBe` "{(0, 5), \"hi\"}" 
test/IntervalAlgebraSpec.hs view
@@ -120,9 +120,12 @@       $          show (beginerval 10 (0 :: Int))       `shouldBe` "(0, 10)" -    it "fmap can convert Interval Integer to Interval Day"-      $          fmap ModifiedJulianDay (beginerval 1 0)-      `shouldBe` beginerval 1 (fromGregorian 1858 11 17)+    -- NOTE toEnum (fromGregorian 1858 11 17) is 0,+    -- since that date is the origin in the modified+    -- Julian calendar.+    it "fromEnumInterval converts Interval Day"+      $          fromEnumInterval (beginerval 0 (fromGregorian 1858 11 17))+      `shouldBe` beginerval 0 0      it "(0, 2) <= (1, 3) is True"       $          beginerval 2 (0 :: Int)@@ -332,4 +335,3 @@     it "concur matches notDisjoint"       $          concur (beginerval 1 0) (beginerval 10 (0 :: Int))       `shouldBe` notDisjoint (beginerval 1 0) (beginerval 10 (0 :: Int))-
+ tutorial/TutorialMain.hs view
@@ -0,0 +1,823 @@+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE OverloadedStrings #-}++module Main where++-- tag::import-declarations[]+import IntervalAlgebra+import IntervalAlgebra.IntervalDiagram++import Data.Bifunctor ( Bifunctor(..) )+import Data.List ( sort )+import Data.Time+    ( addDays, fromGregorian, secondsToDiffTime, Day, UTCTime(..) )+import Witch ( into )+import Data.Set ( fromList, difference, Set )+-- end::import-declarations[]++main :: IO ()+main = do++  -- Add file header -----------------------------------------------------------++  putStrLn "Generated by running `cabal run tutorial -v0 > tutorial/TutorialMain.out`"+  putStrLn "Do not edit by hand\n\n"+++  -- show Interval examples ----------------------------------------------------++  putStrLn "-- tag::interval-show-print[]"++  putStr "\n-- An example Interval Integer"+  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\n-- An example Interval Day"+  putStr "\nprint ivDay\n---> "+  print ivDay++  putStr "\n-- An example Interval UTCTime"+  putStr "\nprint ivUTC\n---> "+  print ivUTC++  putStrLn "-- end::interval-show-print[]"+++  -- Basic Interval instances examples ------------------------------------------++  putStrLn "-- tag::interval-basic-instances-print[]"++  putStr "\nprint $ ivInteger == ivInteger\n---> "+  print $ ivInteger == ivInteger++  putStr "\nprint $ ivDay < ivDay\n---> "+  print $ ivDay < ivDay++  putStr "\nprint $ show ivInteger\n---> "+  print $ show ivInteger++  putStrLn "-- end::interval-basic-instances-print[]"+++  -- parseInterval examples ----------------------------------------------------++  putStrLn "-- tag::parseinterval-print[]"++  putStr "\nprint rightIvInteger\n---> "+  print rightIvInteger++  putStr "\nprint leftIvInteger\n---> "+  print leftIvInteger++  putStr "\nprint rightIvDay\n---> "+  print rightIvDay++  putStr "\nprint rightIvUTC\n---> "+  print rightIvUTC++  putStrLn "-- end::parseinterval-print[]"+++  -- safeInterval examples -----------------------------------------------------++  putStrLn "-- tag::safeinterval-print[]"++  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\nprint ivMinDurInteger\n---> "+  print ivMinDurInteger++  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\nprint ivDay\n---> "+  print ivDay++  putStr "\nprint ivUTC\n---> "+  print ivUTC++  putStrLn "-- end::safeinterval-print[]"+++  -- beginerval and enderval examples -------------------------------------------------------++  putStrLn "-- tag::beginerval-enderval-print[]"++  putStr "\nprint (beginerval 2 3 :: Interval Integer)\n---> "+  print (beginerval 2 3 :: Interval Integer)++  putStr "\nprint (beginerval (-2) 3 :: Interval Integer)\n---> "+  print (beginerval (-2) 3 :: Interval Integer)++  putStr "\nprint (enderval 2 12 :: Interval Integer)\n---> "+  print (enderval 2 12 :: Interval Integer)++  putStr "\nprint (enderval (-2) 12 :: Interval Integer)\n---> "+  print (enderval (-2) 12 :: Interval Integer)++  putStrLn "-- end::beginerval-enderval-print[]"+++  -- Creating moments examples --------------------------------------------------++  putStrLn "-- tag::creating-moments-print[]"++  putStr "\nprint (beginervalMoment 11 :: Interval Integer)\n---> "+  print (beginervalMoment 11 :: Interval Integer)++  putStr "\nprint (endervalMoment 11 :: Interval Integer)\n---> "+  print (endervalMoment 11 :: Interval Integer)++  putStrLn "-- end::creating-moments-print[]"+++  -- Creating PairedIntervals examples --------------------------------------++  putStrLn "-- tag::creating-pairedinterval-print[]"++  putStr "\nprint pairListstringInteger\n---> "+  print pairListstringInteger++  putStr "\nprint pairStringDay\n---> "+  print pairStringDay++  putStrLn "-- end::creating-pairedinterval-print[]"+++  -- Basic PairedInterval instances examples ------------------------------------++  putStrLn "-- tag::pairedinterval-basic-instances-print[]"++  putStr "\nprint $ pairStringDay == pairStringDay\n---> "+  print $ pairStringDay == pairStringDay++  putStr "\nprint $ pairListstringInteger < pairListstringInteger\n---> "+  print $ pairListstringInteger < pairListstringInteger++  putStr "\nprint $ show pairStringDay\n---> "+  print $ show pairStringDay++  putStrLn "-- end::pairedinterval-basic-instances-print[]"+++  -- Getting/setting PairedInterval intervals example --------------------------++  putStrLn "-- tag::pairedinterval-getset-intervals-print[]"++  putStr "\nprint pairListstringInteger\n---> "+  print pairListstringInteger++  putStr "\nprint $ getInterval pairListstringInteger\n---> "+  print $ getInterval pairListstringInteger++  putStr "\nprint $ setInterval pairListstringInteger (safeInterval (4, 9) :: Interval Integer)\n---> "+  print $ setInterval pairListstringInteger (safeInterval (4, 9) :: Interval Integer)++  putStr "\nprint $ intervals [pairListstringInteger, pairListstringInteger]\n---> "+  print $ intervals [pairListstringInteger, pairListstringInteger]++  putStr "\nprint $ begin pairListstringInteger\n---> "+  print $ begin pairListstringInteger++  putStr "\nprint $ end pairListstringInteger\n---> "+  print $ end pairListstringInteger++  putStrLn "-- end::pairedinterval-getset-intervals-print[]"+++  -- Example getting/setting PairedInterval data -------------------------------++  putStrLn "-- tag::pairedinterval-getset-data-print[]"++  putStr "\nprint pairStringDay\n---> "+  print pairStringDay++  putStr "\nprint $ getPairData pairStringDay\n---> "+  print $ getPairData pairStringDay++  putStr "\nprint $ makePairedInterval \"ski trip\" (getInterval pairStringDay)\n---> "+  print $ makePairedInterval "ski trip" (getInterval pairStringDay)++  putStrLn "-- end::pairedinterval-getset-data-print[]"+++  -- Intervallic interval instance examples ------------------------------------------------------++  putStrLn "-- tag::intervallic-interval-instance-print[]"++  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\nprint $ getInterval ivInteger\n---> "+  print $ getInterval ivInteger++  putStr "\nprint $ setInterval ivInteger (beginerval 3 12 :: Interval Integer)\n---> "+  print $ setInterval ivInteger (beginerval 3 12 :: Interval Integer)++  putStr "\nprint $ begin ivInteger\n---> "+  print $ begin ivInteger++  putStr "\nprint $ end ivInteger\n---> "+  print $ end ivInteger++  putStrLn "-- end::intervallic-interval-instance-print[]"+++  -- IntervalSizeable instance examples ------------------------------------------------------++  putStrLn "-- tag::intervalsizeable-instance-print[]"++  putStr "\nprint ivDay\n---> "+  print ivDay++  putStr "\nprint $ moment @Day\n---> "+  print $ moment @Day++  putStr "\nprint $ duration ivDay\n---> "+  print $ duration ivDay++  putStr "\nprint $ add 15 (begin ivDay)\n---> "+  print $ add 15 (begin ivDay)++  putStr "\nprint $ diff (add 15 (begin ivDay)) (begin ivDay)\n---> "+  print $ diff (add 15 (begin ivDay)) (begin ivDay)++  putStrLn "-- end::intervalsizeable-instance-print[]"+++  -- IntervalCombineable Interval examples -------------------------------------++  putStrLn "-- tag::intervalcombinable-interval-print[]"++  putStrLn "\n-- The Just Interval formed from combining the Intervals, since iv0to2 `meets` iv2to5"+  putStr "print $ iv0to2 .+. iv2to5\n---> "+  print $ iv0to2 .+. iv2to5++  putStrLn "\n-- A Nothing since iv0to2 doesn't `meets` iv5to8"+  putStr "print $ iv0to2 .+. iv5to8\n---> "+  print $ iv0to2 .+. iv5to8++  putStrLn "\n-- The Just Interval formed from the end of the first and the beginning of the\n-- second, since iv0to2 is `before` iv5to8"+  putStr "print $ iv0to2 >< iv5to8\n---> "+  print $ iv0to2 >< iv5to8++  putStrLn "\n-- A Nothing since iv0to2 isn't `before` iv2to5"+  putStr "print $ iv0to2 >< iv2to5\n---> "+  print $ iv0to2 >< iv2to5++  putStrLn "-- end::intervalcombinable-interval-print[]"+++  -- IntervalCombineable PairedInterval examples -------------------------------++  putStrLn "-- tag::intervalcombinable-pairedinterval-print[]"++  putStrLn "\n-- The Just Interval formed from combining the Intervals and taking the data\n-- portion from the second argument, since iv0to2 `meets` iv2to5"+  putStr "print $ makePairedInterval \"a\" iv0to2 .+. makePairedInterval \"b\" iv2to5\n---> "+  print $ makePairedInterval "a" iv0to2 .+. makePairedInterval "b" iv2to5++  putStrLn "\n-- A Nothing since iv0to2 doesn't `meets` iv5to8"+  putStr "print $ makePairedInterval \"a\" iv0to2 .+. makePairedInterval \"b\" iv5to8\n---> "+  print $ makePairedInterval "a" iv0to2 .+. makePairedInterval "b" iv5to8++  putStrLn "\n-- The Just Interval formed from spanning the Intervals and taking the data\n-- portion from the `mempty` method of the Monoid String instance, since\n-- iv0to2 is `before` iv5to8"+  putStr "print $ makePairedInterval \"a\" iv0to2 >< makePairedInterval \"b\" iv5to8\n---> "+  print $ makePairedInterval "a" iv0to2 >< makePairedInterval "b" iv5to8++  putStrLn "\n-- A Nothing since iv0to2 isn't `before` iv2to5"+  putStr "print $ makePairedInterval \"a\" iv0to2 >< makePairedInterval \"b\" iv2to5\n---> "+  print $ makePairedInterval "a" iv0to2 >< makePairedInterval "b" iv2to5++  putStrLn "-- end::intervalcombinable-pairedinterval-print[]"+++  -- Expanding intervals examples -----------------------------------------------++  putStrLn "-- tag::expanding-intervals-print[]"++  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\nprint $ expandl 4 ivInteger\n---> "+  print $ expandl 4 ivInteger++  putStr "\nprint $ expandl 0 ivInteger\n---> "+  print $ expandl 0 ivInteger++  putStr "\nprint $ expandr 5 ivInteger\n---> "+  print $ expandr 5 ivInteger++  putStr "\nprint $ expandr (-3) ivInteger\n---> "+  print $ expandr (-3) ivInteger++  putStr "\nprint $ expand 4 5 ivInteger\n---> "+  print $ expand 4 5 ivInteger++  putStr "\nprint $ expand 0 (-3) ivInteger\n---> "+  print $ expand 0 (-3) ivInteger++  putStrLn "-- end::expanding-intervals-print[]"+++  -- Sharing an endpoint interval examples -----------------------------------------------++  putStrLn "-- tag::sharing-endpoint-interval-print[]"++  putStr "\nprint ivInteger\n---> "+  print ivInteger++  putStr "\nbeginervalFromEnd 5 ivInteger\n---> "+  print $ beginervalFromEnd 5 ivInteger++  putStr "\nbeginervalFromEnd (-2) ivInteger\n---> "+  print $ beginervalFromEnd (-2) ivInteger++  putStr "\nendervalFromBegin 12 ivInteger\n---> "+  print $ endervalFromBegin 12 ivInteger++  putStr "\nendervalFromBegin (-6) ivInteger\n---> "+  print $ endervalFromBegin (-6) ivInteger++  putStr "\nprint $ momentize ivInteger\n---> "+  print $ momentize ivInteger++  putStrLn "-- end::sharing-endpoint-interval-print[]"+++  -- Example shifting intervals -----------------------------------------------++  putStrLn "-- tag::shifting-intervals-print[]"++  putStr "\nprint [iv2to4, iv5to8]\n---> "+  print [iv2to4, iv5to8]++  putStr "\nprint ivDay\n---> "+  print ivDay++  putStr "\nprint $ shiftFromBegin iv2to4 iv5to8\n---> "+  print $ shiftFromBegin iv2to4 iv5to8++  putStr "\nprint $ shiftFromBegin ivDay ivDay\n---> "+  print $ shiftFromBegin ivDay ivDay++  putStr "\nprint $ shiftFromEnd iv2to4 iv5to8\n---> "+  print $ shiftFromEnd iv2to4 iv5to8++  putStr "\nprint $ shiftFromEnd ivDay ivDay\n---> "+  print $ shiftFromEnd ivDay ivDay++  putStrLn "-- end::shifting-intervals-print[]"+++  -- Relations variables diagram example --------------------------------------------++  putStrLn "-- tag::relations-variables-diagram-print[]"++  print $ pretty diagr++  putStrLn "-- end::relations-variables-diagram-print[]"+++  -- Composing relations examples -------------------------------------------++  putStrLn "-- tag::composing-relations-print[]"++  putStr "\nprint endedPriorRelations\n---> "+  print endedPriorRelations++  putStr "\nprint notEndedPriorRelations\n---> "+  print notEndedPriorRelations++  putStr "\nprint notEndedPriorRelations'\n---> "+  print notEndedPriorRelations'++  putStr "\nprint intervalRelations'\n---> "+  print intervalRelations'++  putStr "\nprint empty\n---> "+  print empty++  putStrLn "-- end::composing-relations-print[]"+++  -- Composing predicates v1 examples ---------------------------------------++  putStrLn "-- tag::composing-predicates-1-print[]"++  putStr "\nprint $ iv0to2 `precedes` iv3to6"+  putStr "\nprint $ iv0to2 `meets` iv3to6"+  putStr "\nprint $ iv0to2 `endedPrior` iv3to6\n---> "+  print $ iv0to2 `precedes` iv3to6+  putStr "---> "+  print $ iv0to2 `meets` iv3to6+  putStr "---> "+  print $ iv0to2 `endedPrior` iv3to6++  putStrLn "-- end::composing-predicates-1-print[]"+++  -- Composing predicates v2 examples ---------------------------------------++  putStrLn "-- tag::composing-predicates-2-print[]"++  putStr "\nprint $ iv0to2 `precedes` iv2to4"+  putStr "\nprint $ iv0to2 `meets` iv2to4"+  putStr "\nprint $ iv0to2 `endedPrior` iv2to4\n---> "+  print $ iv0to2 `precedes` iv2to4+  putStr "---> "+  print $ iv0to2 `meets` iv2to4+  putStr "---> "+  print $ iv0to2 `endedPrior` iv2to4++  putStrLn "-- end::composing-predicates-2-print[]"+++  -- Composing predicates v3 examples ---------------------------------------++  putStrLn "-- tag::composing-predicates-3-print[]"++  putStr "\nprint $ iv5to8 `precedes` iv2to4"+  putStr "\nprint $ iv5to8 `meets` iv2to4"+  putStr "\nprint $ iv5to8 `endedPrior` iv2to4\n---> "+  print $ iv5to8 `precedes` iv2to4+  putStr "---> "+  print $ iv5to8 `meets` iv2to4+  putStr "---> "+  print $ iv5to8 `endedPrior` iv2to4++  putStrLn "-- end::composing-predicates-3-print[]"+++  -- Extended example 1 examples --------------------------------------------------------++  putStrLn "-- tag::extended-example-1-print[]"++  putStr "\nprint $ head results\n---> "+  print $ head results++  putStr "\nprint $ results !! 1\n---> "+  print $ results !! 1++  putStr "\nprint $ results !! 2\n---> "+  print $ results !! 2++  putStr "\nprint $ results !! 3\n---> "+  print $ results !! 3++  putStrLn "-- end::extended-example-1-print[]"+++-- tag::parseinterval-examples[]+rightIvInteger :: Either ParseErrorInterval (Interval Integer)+rightIvInteger = parseInterval 0 2++leftIvInteger :: Either ParseErrorInterval (Interval Integer)+leftIvInteger = parseInterval 2 2++rightIvDay :: Either ParseErrorInterval (Interval Day)+rightIvDay =+  parseInterval (fromGregorian 1967 01 18) (fromGregorian 1967 01 22)++rightIvUTC :: Either ParseErrorInterval (Interval UTCTime)+rightIvUTC = parseInterval+  (UTCTime (fromGregorian 1967 01 18) (secondsToDiffTime 32400))+  (UTCTime (fromGregorian 1967 01 18) (secondsToDiffTime 33200))+-- end::parseinterval-examples[]+++-- tag::safeinterval-examples[]+ivInteger :: Interval Integer+ivInteger = safeInterval (2, 6)++ivMinDurInteger :: Interval Integer+ivMinDurInteger = safeInterval (2, 2)++ivDay :: Interval Day+ivDay = safeInterval (fromGregorian 1967 01 18, fromGregorian 1967 01 24)++ivUTC :: Interval UTCTime+ivUTC = safeInterval+  ( UTCTime (fromGregorian 1967 01 18) (secondsToDiffTime 32400)+  , UTCTime (fromGregorian 1967 01 18) (secondsToDiffTime 33200)+  )+-- end::safeinterval-examples[]+++-- tag::ivXtoY-examples[] ----------------++iv0to2, iv2to4, iv2to5, iv4to5, iv5to8, iv6to8, iv3to6 :: Interval Integer+iv0to2 = safeInterval (0, 2)+iv2to4 = safeInterval (2, 4)+iv2to5 = safeInterval (2, 5)+iv3to6 = safeInterval (3, 6)+iv4to5 = safeInterval (4, 5)+iv5to8 = safeInterval (5, 8)+iv6to8 = safeInterval (6, 8)++-- end::ivXtoY-examples[]+++-- tag::creating-pairedinterval-examples[] --------------------++pairListstringInteger :: PairedInterval [String] Integer+pairListstringInteger =+  makePairedInterval ["John", "Paul", "George", "Ringo"] ivInteger++pairStringDay :: PairedInterval String Day+pairStringDay = makePairedInterval "vacation" ivDay++-- end::creating-pairedinterval-examples[]+++-- tag::composing-relations-examples[]++-- Set, `fromList`, and in a later example `difference` are imported from+-- Data.Set+endedPriorRelations :: Set IntervalRelation+endedPriorRelations = fromList [Before, Meets]++-- We can in general create a new Set by taking the set Difference of one Set+-- and another Set+notEndedPriorRelations :: Set IntervalRelation+notEndedPriorRelations = intervalRelations `difference` endedPriorRelations++-- However, the `complement` function is provided for the common case of taking+-- the Set Difference of the `intervalRelations` Set and another Set+notEndedPriorRelations' :: Set IntervalRelation+notEndedPriorRelations' = complement endedPriorRelations++-- IntervalAlgebra exports versions of `Data.Set`s `intersection` and `union`+-- functions where the types are specialized to `Set IntervalRelation`s+intervalRelations' :: Set IntervalRelation+intervalRelations' = endedPriorRelations `union` notEndedPriorRelations++-- The intersection of two disjoint sets+empty :: Set IntervalRelation+empty = endedPriorRelations `intersection` notEndedPriorRelations++-- end::composing-relations-examples[]+++-- tag::composing-predicates-examples[] -----------------------++-- We can construct a predicate function from a 'Set IntervalRelation'+endedPrior+  :: (Ord a, Intervallic i0, Intervallic i1)+  => ComparativePredicateOf2 (i0 a) (i1 a)+endedPrior = predicate (fromList [Before, Meets])++-- We can also construct a predicate function directly from a list of predicate+-- functions+endedPrior'+  :: (Ord a, Intervallic i0, Intervallic i1)+  => ComparativePredicateOf2 (i0 a) (i1 a)+endedPrior' = unionPredicates [before, meets]++-- As an alternative to `unionPredicates` we can compose predicate functions+-- using the <|> operator. If we had multiple predicates we could use e.g.:+--     p1 <|> p2 <|> p3+endedPrior''+  :: (Ord a, Intervallic i0, Intervallic i1)+  => ComparativePredicateOf2 (i0 a) (i1 a)+endedPrior'' = before <|> meets++-- end::composing-predicates-examples[]+++-- tag::extended-example-1-types[] --------------------++data DataType = Enrollment | Treatment TreatmentType | Diagnosis DiagnosisType+  deriving (Eq, Ord, Show)++data TreatmentType = StandardVaccine | NewVaccine+  deriving (Eq, Ord, Show)++data DiagnosisType = RightAsRain | UpsetTummy | CommonCold | Flu+  deriving (Eq, Ord, Show)++type StudyEvent = PairedInterval DataType Integer++type SubjEvents = [StudyEvent]++data ProcessedSubj = ProcessedSubj+  { getEnrollment   :: Maybe (Interval Integer)+  , getFirstTrt     :: Maybe StudyEvent+  , getFirstFlu     :: Maybe StudyEvent+  , getTrtType      :: Maybe TreatmentType+  , getTimeToFlu    :: Maybe Integer+  , getTimeToEndEnr :: Maybe Integer+  }+  deriving Show++maxEnrGap :: Integer+maxEnrGap = 8++-- end::extended-example-1-types[]+++-- tag::extended-example-1-study-data-subj-1[] ----------------++id1Event1, id1Event2, id1Event3, id1Event4, id1Event5, id1Event6, id1Event7+  :: StudyEvent+id1Event1 = makePairedInterval Enrollment (safeInterval (6, 191))+id1Event2 = makePairedInterval Enrollment (safeInterval (199, 345))+id1Event3 = makePairedInterval Enrollment (safeInterval (347, 422))+id1Event4 = makePairedInterval (Diagnosis RightAsRain) (safeInterval (12, 13))+id1Event5 = makePairedInterval (Treatment NewVaccine) (safeInterval (22, 23))+id1Event6 = makePairedInterval (Diagnosis RightAsRain) (safeInterval (131, 132))+id1Event7 = makePairedInterval (Diagnosis CommonCold) (safeInterval (161, 162))++id1Events :: SubjEvents+id1Events = sort+  [id1Event1, id1Event2, id1Event3, id1Event4, id1Event5, id1Event6, id1Event7]++-- end::extended-example-1-study-data-subj-1[]+++-- tag::extended-example-1-study-data-subj-2[] ----------------++id2Event1, id2Event2, id2Event3, id2Event4, id2Event5, id2Event6, id2Event7, id2Event8+  :: StudyEvent+id2Event1 = makePairedInterval Enrollment (safeInterval (2, 206))+id2Event2 = makePairedInterval Enrollment (safeInterval (222, 299))+id2Event3 = makePairedInterval Enrollment (safeInterval (304, 486))+id2Event4 = makePairedInterval (Diagnosis RightAsRain) (safeInterval (4, 5))+id2Event5 =+  makePairedInterval (Treatment StandardVaccine) (safeInterval (98, 99))+id2Event6 = makePairedInterval (Diagnosis CommonCold) (safeInterval (161, 162))+id2Event7 = makePairedInterval (Diagnosis UpsetTummy) (safeInterval (191, 192))+id2Event8 = makePairedInterval (Diagnosis Flu) (safeInterval (255, 256))++id2Events :: SubjEvents+id2Events = sort+  [ id2Event1, id2Event2, id2Event3, id2Event4, id2Event5 , id2Event6+  , id2Event7, id2Event8 ]++-- end::extended-example-1-study-data-subj-2[]+++-- tag::extended-example-1-study-data-subj-3[] ----------------++id3Event1, id3Event2, id3Event3 :: StudyEvent+id3Event1 = makePairedInterval Enrollment (safeInterval (7, 197))+id3Event2 = makePairedInterval (Treatment StandardVaccine) (safeInterval (19, 20))+id3Event3 = makePairedInterval (Diagnosis Flu) (safeInterval (180, 181))++id3Events :: SubjEvents+id3Events = sort [id3Event1, id3Event2, id3Event3]++-- end::extended-example-1-study-data-subj-3[]+++-- tag::extended-example-1-study-data-subj-4[] ----------------++id4Event1, id4Event2 :: StudyEvent+id4Event1 = makePairedInterval Enrollment (safeInterval (3, 89))+id4Event2 = makePairedInterval (Diagnosis RightAsRain) (safeInterval (47, 48))++id4Events :: SubjEvents+id4Events = sort [id4Event1, id4Event2]++-- end::extended-example-1-study-data-subj-4[]+++-- tag::extended-example-1-processing-functions[] -------------++-- Construct the elements of a `ProcessedSubj` one step at-a-time. Most of the+-- actual work is done by the helper functions defined below+processSubj :: SubjEvents -> ProcessedSubj+processSubj xs =+  let enrPeriod    = calcEnrPeriod xs                   -- enrollment period+      enrEvents    = calcEnrEvents enrPeriod xs         -- events within enrollment+      firstTrt     = findFirstTrt enrPeriod xs          -- first treatment in enr+      firstTrtType = extractTrtType firstTrt            -- first trt type+      firstTrtIv   = fmap getInterval firstTrt          -- first trt interval+      firstFlu     = findFirstFlu firstTrtIv enrEvents  -- first flu in enr+      ttFlu        = calcDiff firstFlu firstTrt         -- time to first flu+      ttEndEnr     = calcAtRisk enrPeriod firstTrt      -- time to end of enr+  in  ProcessedSubj enrPeriod firstTrt firstFlu firstTrtType ttFlu ttEndEnr++-- Construct the "enrollment period", which is defined at the period of time+-- with the start endpoint given by their earliest enrollment period and end+-- endpoint given by the first time that they fall out of the grace period. In+-- the event that a subject did not have any enrollment periods then the return+-- value is a Nothing.+--+-- Note that this function uses the `combineIntervals` function which was not+-- covered in this tutorial, but is exported from IntervalAlgebra via+-- IntervalAlgebra.IntervalUtilities.+calcEnrPeriod :: SubjEvents -> Maybe (Interval Integer)+calcEnrPeriod xs | null combinedPeriods = Nothing+                 | otherwise            = Just (head combinedPeriods)+  where combinedPeriods = (combineIntervals . addMaxEnrGap . extractEnrIvs) xs++-- Filter the enrollment events in the SubjEvents and extract the Interval+-- from each one+extractEnrIvs :: SubjEvents -> [Interval Integer]+extractEnrIvs = intervals . filter (checkEnr . getPairData)+ where+  checkEnr Enrollment = True+  checkEnr _          = False++-- Extend the end endpoint for each Interval by `maxEnrGap`+addMaxEnrGap :: [Interval Integer] -> [Interval Integer]+addMaxEnrGap = map (expandr maxEnrGap)++-- Filter the SubjEvents to those with endpoints that do not extend past the+-- enrollment period's endpoints+calcEnrEvents :: Maybe (Interval Integer) -> SubjEvents -> SubjEvents+calcEnrEvents mayIv xs = case mayIv of+  Nothing -> []+  Just y  -> filter (\x -> getInterval x `enclosedBy` y) xs++-- Find the first flu vaccine administrations occuring within the enrollment+-- period+findFirstTrt :: Maybe (Interval Integer) -> SubjEvents -> Maybe StudyEvent+findFirstTrt Nothing _ = Nothing+findFirstTrt (Just iv) xs | null filteredIntakes = Nothing+                          | otherwise            = Just (head filteredIntakes)+ where+  p x = checkTrt (getPairData x) && (getInterval x `enclosedBy` iv)+  checkTrt (Treatment _) = True+  checkTrt _             = False+  filteredIntakes = filter p xs++-- Extract the treatment type out of a StudyEvent. If there is no event or the+-- StudyEvent type isn't TreatmentType then return Nothing+extractTrtType :: Maybe StudyEvent -> Maybe TreatmentType+extractTrtType Nothing  = Nothing+extractTrtType (Just x) = case getPairData x of+  Treatment StandardVaccine -> Just StandardVaccine+  Treatment NewVaccine      -> Just NewVaccine+  _                         -> Nothing++-- Find the first flu diagnosis occuring within the enrollment period+findFirstFlu :: Maybe (Interval Integer) -> SubjEvents -> Maybe StudyEvent+findFirstFlu Nothing _ = Nothing+findFirstFlu (Just iv) xs | null filteredFlus = Nothing+                          | otherwise         = Just (head filteredFlus)+ where+  endedPrior = before <|> meets+  p x = checkDiagFlu (getPairData x) && (iv `endedPrior` getInterval x)+  checkDiagFlu (Diagnosis Flu) = True+  checkDiagFlu _               = False+  filteredFlus = filter p xs++-- Calculate the difference between the start endpoint of the first Intervallic+-- and the start endpoint of the second Intervallic+calcDiff+  :: (IntervalSizeable a b, Intervallic i0, Intervallic i1)+  => Maybe (i0 a)+  -> Maybe (i1 a)+  -> Maybe b+calcDiff (Just y) (Just x) = Just $ diff (begin y) (end x)+calcDiff _ _               = Nothing++-- Calculate the difference between the end endpoint of the first Intervallic+-- and the start endpoint of the second Intervallic+calcAtRisk+  :: (IntervalSizeable a b, Intervallic i0, Intervallic i1)+  => Maybe (i0 a)+  -> Maybe (i1 a)+  -> Maybe b+calcAtRisk (Just y) (Just x) = Just $ diff (end y) (end x)+calcAtRisk _ _               = Nothing++-- end::extended-example-1-processing-functions[]+++-- tag::extended-example-1-calculate-results[] ----------------++results :: [ProcessedSubj]+results = map processSubj [id1Events, id2Events, id3Events, id4Events]++-- end::extended-example-1-calculate-results[]+++--------------------------------------------------------------------------------+-- The remaining is untagged data+--------------------------------------------------------------------------------++diagr :: Either IntervalDiagramParseError (IntervalDiagram Integer)+diagr = parseIntervalDiagram+  defaultIntervalDiagramOptions+  []+  (Just Bottom)+  (into @(IntervalText Integer) ('=', safeInterval (0, 12 :: Integer)))+  [ ([deftIT iv0to2], ["iv0to2"])+  , ([deftIT iv2to4], ["iv2to4"])+  , ([deftIT iv2to5], ["iv2to5"])+  , ([deftIT iv3to6], ["iv3to6"])+  , ([deftIT iv4to5], ["iv4to5"])+  , ([deftIT iv6to8], ["iv6to8"])+  , ([deftIT iv5to8], ["iv5to8"])+  ]++intoIntervalText :: Interval Integer -> IntervalText Integer+intoIntervalText x = into @(IntervalText Integer) ('-', x)++deftIT :: Interval Integer -> IntervalText Integer+deftIT = intoIntervalText