ianmackenzie/elm-interval/1.0.1

NOTE: the latest version is 3.1.0

Interval

Represents a finite, bounded interval with a minimum and maximum value, for example the interval from 3 to 5.

Constructors

singleton : Float -> Interval

Construct a zero-width interval containing a single value.

Interval.singleton 3
--> Interval.fromEndpoints ( 3, 3 )
fromEndpoints : ( Float, Float ) -> Interval

Construct an interval from its endpoints (the minimum and maximum values of the interval).

rgbRange =
    Interval.fromEndpoints ( 0, 255 )


alphaRange =
    Interval.fromEndpoints ( 0, 1 )

The two values should be given in order but will be swapped if necessary to ensure a valid interval is returned:

Interval.endpoints (Interval.fromEndpoints ( 3, 2 ))
--> ( 2, 3 )
from : Float -> Float -> Interval

Construct an interval containing the two given values (which can be provided in either order).

Interval.endpoints (Interval.from 2 5)
--> ( 2, 5 )


Interval.endpoints (Interval.from 5 2)
--> ( 2, 5 )
containingValues : List Float -> Maybe Interval

Construct an interval containing all values in the given list. If the list is empty, returns Nothing.

Interval.containingValues [ 2, 1, 3 ]
--> Just (Interval.from 1 3)


Interval.containingValues [ -3 ]
--> Just (Interval.singleton -3)


Interval.containingValues []
--> Nothing
aggregate : List Interval -> Maybe Interval

Construct an interval containing all of the intervals in the given list. If the list is empty, returns Nothing.

Interval.aggregate
    [ Interval.singleton 2
    , Interval.from 3 4
    ]
--> Just (Interval.from 2 4)


Interval.aggregate []
--> Nothing

Construct an interval containing both of the given intervals.

firstInterval =
    Interval.from 1 2


secondInterval =
    Interval.from 3 6


Interval.hull firstInterval secondInterval
--> Interval.from 1 6

Attempt to construct an interval containing all the values common to both given intervals. If the intervals do not intersect, returns Nothing.

Interval.intersection
    (Interval.from 1 3)
    (Interval.from 2 5)
--> Just (Interval.from 2 3)


Interval.intersection
    (Interval.from 1 3)
    (Interval.from 4 7)
--> Nothing

If the two intervals just touch, a singleton interval will be returned:

Interval.intersection
    (Interval.from 1 3)
    (Interval.from 3 5)
--> Just (Interval.singleton 3)

Properties

endpoints : Interval -> ( Float, Float )

Get the endpoints of an interval (its minimum and maximum values) as a tuple. The first value will always be less than or equal to the second.

( minValue, maxValue ) =
    Interval.endpoints someInterval

For any interval,

Interval.endpoints interval

is equivalent to (but more efficient than)

( Interval.minValue interval
, Interval.maxValue interval
)
minValue : Interval -> Float

Get the minimum value of an interval.

Interval.minValue (Interval.from 1 3)
--> 1
maxValue : Interval -> Float

Get the maximum value of an interval.

Interval.maxValue (Interval.from 1 3)
--> 3
midpoint : Interval -> Float

Get the midpoint of an interval.

Interval.midpoint (Interval.from 1 5)
--> 3
width : Interval -> Float

Get the width of an interval.

Interval.width (Interval.from 1 5)
--> 4

Interpolation

interpolate : Interval -> Float -> Float

Interpolate between an interval's endpoints; a value of 0.0 corresponds to the minimum value of the interval, a value of 0.5 corresponds to its midpoint and a value of 1.0 corresponds to its maximum value. Values less than 0.0 or greater than 1.0 can be used to extrapolate.

Interval.interpolate (Interval.from -1 5) 0
--> -1


Interval.interpolate (Interval.from -1 5) 0.75
--> 3.5


Interval.interpolate (Interval.from -1 5) -0.5
--> -4

Note that the interpolation is in fact from the minimum value to the maximum, not "from the first Interval.from argument to the second":

Interval.interpolate (Interval.from 0 10) 0.2
--> 2


Interval.interpolate (Interval.from 10 0) 0.2
--> 2 -- not 8!

Arithmetic

Get the image of sin(x) applied on the interval.

Interval.sin (Interval.from 0 (degrees 45))
--> Interval.from 0 0.7071


Interval.sin (Interval.from 0 pi)
--> Interval.from 0 1

Get the image of cos(x) applied on the interval.

Interval.cos (Interval.from 0 (degrees 45))
--> Interval.from 0.7071 1


Interval.cos (Interval.from 0 pi)
--> Interval.from -1 1

Queries

contains : Float -> Interval -> Bool

Check if an interval contains a given value.

Interval.contains 0 (Interval.from -1 3)
--> True


Interval.contains 5 (Interval.from -1 3)
--> False

The minimum and maximum values of an interval are considered to be contained in the interval, although if you are relying on this then there is a good chance your code is vulnerable to numerical roundoff!

Interval.contains 3 (Interval.from -1 3)
--> True

Check if two intervals touch or overlap (have any values in common).

Interval.from -5 5
    |> Interval.intersects (Interval.from 0 10)
--> True


Interval.from -5 5
    |> Interval.intersects (Interval.from 10 20)
--> False

Intervals that just touch each other are considered to intersect (this is consistent with intersection which will return a zero-width interval for the intersection of two just-touching intervals):

Interval.from -5 5
    |> Interval.intersects (Interval.from 5 10)
--> True

As with contains, though, if you are relying on this then there is a good chance your code is vulnerable to numerical roundoff!

Check if the second interval is fully contained in the first.

Interval.from -5 5
    |> Interval.isContainedIn (Interval.from 0 10)
--> False


Interval.from -5 5
    |> Interval.isContainedIn (Interval.from -10 10)
--> True

Be careful with the argument order! If not using the |> operator, the second example would be written as:

Interval.isContainedIn (Interval.from -10 10)
    (Interval.from -5 5)
--> True