Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
This module provides types and functions for defining intervals and determining how they relate to each other. This can be useful to determine if an event happened during a certain time frame, or if two time frames overlap (and if so, how exactly they overlap).
There are many other packages on Hackage that deal with intervals, notably data-interval and intervals. You may prefer one of them for more general interval operations. This module is more focused on how intervals relate to each other.
This module was inspired by James F. Allen's report, Maintaining Knowledge About Temporal Intervals. It also uses terminology from that report. You should not need to read the report in order to understand this module, but if you want to read it you can find it here: https://hdl.handle.net/1802/10574.
Synopsis
- data Interval a
- toInterval :: Ord a => (a, a) -> Interval a
- fromInterval :: Interval a -> (a, a)
- lesser :: Interval a -> a
- greater :: Interval a -> a
- isEmpty :: Eq a => Interval a -> Bool
- isNonEmpty :: Eq a => Interval a -> Bool
- data Relation
- relate :: Ord a => Interval a -> Interval a -> Relation
- invert :: Relation -> Relation
Documentation
This type represents an interval bounded by two values, the lesser
and
the greater
. These values can be anything with an Ord
instance: numbers,
times, strings — you name it.
Use toInterval
to construct an interval and fromInterval
to deconstruct
one. Use relate
to determine how two intervals relate to each other.
Instances
toInterval :: Ord a => (a, a) -> Interval a Source #
Converts a tuple into an Interval
. Note that this requires an Ord
constraint so that the Interval
can be sorted on construction.
Use fromInterval
to go in the other direction.
fromInterval :: Interval a -> (a, a) Source #
Converts an Interval
into a tuple. Generally you can think of this as
the inverse of toInterval
. However the tuple returned by this function may
be swapped compared to the one originally passed to toInterval
.
fromInterval (toInterval
(1, 2))==
(1, 2) fromInterval (toInterval
(2, 1))==
(1, 2)
fromInterval (toInterval (x, y)) == (min x y, max x y)
lesser :: Interval a -> a Source #
Gets the lesser value from an Interval
.
lesser (toInterval
(1, 2))==
1 lesser (toInterval
(2, 1))==
1
lesser (toInterval (x, y)) == min x y
greater :: Interval a -> a Source #
Gets the greater value from an Interval
.
greater (toInterval
(1, 2))==
2 greater (toInterval
(2, 1))==
2
greater (toInterval (x, y)) == max x y
isEmpty :: Eq a => Interval a -> Bool Source #
Returns True
if the given Interval
is empty, False
otherwise. An
Interval
is empty if its lesser
equals its greater
.
isEmpty (toInterval
(1, 1))==
True
isEmpty (toInterval
(1, 2))==
False
See isNonEmpty
for the opposite check.
This type describes how two Interval
s relate to each other. Each
constructor represents one of the 13 possible relations. Taken together
these relations are mutually exclusive and exhaustive.
Use relate
to determine the relation between two Interval
s.
The following image shows all 13 possible Interval
relations. If for
whatever reason you can't see the image, each constructor for this type has
ASCII art showing the Interval
relation.
Before |
+---+ | x | +---+ +---+ | y | +---+ |
Meets |
+---+ | x | +---+ +---+ | y | +---+ |
Overlaps |
+---+ | x | +---+ +---+ | y | +---+ |
FinishedBy |
+-----+ | x | +-----+ +---+ | y | +---+ |
Contains |
+-------+ | x | +-------+ +---+ | y | +---+ |
Starts |
+---+ | x | +---+ +-----+ | y | +-----+ |
Equal |
+---+ | x | +---+ +---+ | y | +---+ |
StartedBy |
+-----+ | x | +-----+ +---+ | y | +---+ |
During |
+---+ | x | +---+ +-------+ | y | +-------+ |
Finishes |
+---+ | x | +---+ +-----+ | y | +-----+ |
OverlappedBy |
+---+ | x | +---+ +---+ | y | +---+ |
MetBy |
+---+ | x | +---+ +---+ | y | +---+ |
After |
+---+ | x | +---+ +---+ | y | +---+ |
relate :: Ord a => Interval a -> Interval a -> Relation Source #
Relates two Interval
s. Calling relate x y
tells you how Interval
x
relates to Interval
y
. Consult the Relation
documentation for an
explanation of all the possible results.
relate (toInterval
(1, 2)) (toInterval
(3, 7))==
Before
relate (toInterval
(2, 3)) (toInterval
(3, 7))==
Meets
relate (toInterval
(2, 4)) (toInterval
(3, 7))==
Overlaps
relate (toInterval
(2, 7)) (toInterval
(3, 7))==
FinishedBy
relate (toInterval
(2, 8)) (toInterval
(3, 7))==
Contains
relate (toInterval
(3, 4)) (toInterval
(3, 7))==
Starts
relate (toInterval
(3, 7)) (toInterval
(3, 7))==
Equal
relate (toInterval
(3, 8)) (toInterval
(3, 7))==
StartedBy
relate (toInterval
(4, 6)) (toInterval
(3, 7))==
During
relate (toInterval
(6, 7)) (toInterval
(3, 7))==
Finishes
relate (toInterval
(6, 8)) (toInterval
(3, 7))==
OverlappedBy
relate (toInterval
(7, 8)) (toInterval
(3, 7))==
MetBy
relate (toInterval
(8, 9)) (toInterval
(3, 7))==
After
Note that relating an empty interval with a non-empty interval may be surprising when the intervals share an endpoint.
>>> relate (toInterval
(3, 3)) (toInterval
(3, 7))==
Overlaps
>>> relate (toInterval
(7, 7)) (toInterval
(3, 7))==
OverlappedBy
>>> relate (toInterval
(3, 7)) (toInterval
(3, 3))==
OverlappedBy
>>> relate (toInterval
(3, 7)) (toInterval
(7, 7))==
Overlaps
invert :: Relation -> Relation Source #
Inverts a Relation
. Every Relation
has an inverse.
invertBefore
==
After
invertAfter
==
Before
invertMeets
==
MetBy
invertMetBy
==
Meets
invertOverlaps
==
OverlappedBy
invertOverlappedBy
==
Overlaps
invertStarts
==
StartedBy
invertStartedBy
==
Starts
invertFinishes
==
FinishedBy
invertFinishedBy
==
Finishes
invertContains
==
During
invertDuring
==
Contains
invertEqual
==
Equal
Inverting a Relation
twice will return the original Relation
.
invert (invert r) == r
Inverting a Relation
is like swapping the arguments to relate
.
invert (relate x y) == relate y x