Model and operate on a range of values in Elm.
{ config : TypeConfig subtype
, range : RangeInternal subtype
}
A range of a certain type that stores information about its bounds.
Be aware that a Range stores functions internally. If you want to use (==)
for comparing two Ranges use the eq operator.
{ toString : subtype -> String
, fromString : String -> Result String subtype
, compare : subtype -> subtype -> Basics.Order
, canonical : Maybe (Canonical subtype)
}
When you need to use a custom type you must create an instance of this.
This acts as a value level typeclass.
( ( BoundFlag
, subtype -> subtype )
, ( BoundFlag
, subtype -> subtype )
)
A discrete range type should have a canonicalization function that is aware of the desired step size for the element type. The canonicalization function is charged with converting equivalent values of the range type to have identical representations, in particular consistently inclusive or exclusive bounds. If a canonicalization function is not specified, then ranges with different formatting will always be treated as unequal, even though they might represent the same set of values in reality.
Here is the definition for an integer range:
( ( Inc, (+) 1 ), ( Exc, (+) 1 ) )
It specifies that the lower bound should be inclusive and the upper exclusive. If the supplied bound flags are different during creating then step the value by
empty : TypeConfig subtype -> Range subtype
Create an empty range
Range.empty Range.types.int
create : TypeConfig subtype -> Maybe subtype -> Maybe subtype -> Result String (Range subtype)
Create a range in standard form (lower bound inclusive, upper bound exclusive).
Range.create Range.types.float (Just 1.2) Nothing
createWith : TypeConfig subtype -> Maybe subtype -> Maybe subtype -> Maybe ( BoundFlag, BoundFlag ) -> Result String (Range subtype)
Create a range with whatever user specified flags.
Range.create Range.types.float (Just 1.5) (Just 12.2) (Just ( Range.Inc, Range.Inc ))
The kind of bounds, inclusive or exclusive, to be supplied to createWith.
fromString : TypeConfig subtype -> String -> Result String (Range subtype)
Create a range from a string.
Range.fromString Range.types.int "(1,5)"
types : { int : TypeConfig Basics.Int, float : TypeConfig Basics.Float, string : TypeConfig String, timestamp : TypeConfig Time.Posix }
Built-in TypeConfigs for common types.
toString : Range subtype -> String
Convert a range to its string representation.
-- Ok [1,2)
Range.create Range.types.int (Just 1) (Just 2)
|> Result.map Range.toString
decoder : TypeConfig subtype -> Json.Decode.Decoder (Range subtype)
JSON decoder
encode : Range subtype -> Json.Encode.Value
Encode a Range
to JSON
eq : Range subtype -> Range subtype -> Basics.Bool
Equal
-- > Ok True
Result.map2 Range.eq
(Range.create Range.types.int (Just 1) (Just 5))
(Range.fromString Range.types.int "[1,4]")
Use this over (==)
which may cause a runtime error.
neq : Range subtype -> Range subtype -> Basics.Bool
Not Equal
-- Ok True
Result.map2 Range.neq
(Range.create Range.types.float (Just 1.1) (Just 2.2))
(Range.create Range.types.float (Just 1.1) (Just 2.3))
lt : Range subtype -> Range subtype -> Basics.Bool
Less Than
-- Ok True
Result.map2 Range.lt
(Range.create Range.types.int (Just 1) (Just 10))
(Range.create Range.types.int (Just 2) (Just 3))
gt : Range subtype -> Range subtype -> Basics.Bool
Greater Than
-- Ok True
Result.map2 Range.gt
(Range.create Range.types.int (Just 1) (Just 10))
(Range.create Range.types.int (Just 1) (Just 5))
le : Range subtype -> Range subtype -> Basics.Bool
Less Than or Equal
-- Ok True
Result.map2 Range.lte
(Range.create Range.types.float (Just 1.1) (Just 2.2))
(Range.create Range.types.float (Just 1.1) (Just 2.2))
ge : Range subtype -> Range subtype -> Basics.Bool
Greater Than or Equal
-- Ok True
Result.map2 Range.gte
(Range.create Range.types.float (Just 1.1) (Just 2.2))
(Range.create Range.types.float (Just 1.1) (Just 2.0))
cr : Range subtype -> Range subtype -> Basics.Bool
Contains Range
-- Ok True
Result.map2 Range.cr
(Range.create Range.types.int (Just 2) (Just 4))
(Range.create Range.types.int (Just 2) (Just 3))
ce : Range subtype -> subtype -> Basics.Bool
Contains Element
-- Ok True
Result.map2 Range.ce
(Range.fromString Range.types.timestamp "[2011-01-01,2011-03-01)"
(Iso8601.toTime "2011-01-10")
ov : Range subtype -> Range subtype -> Basics.Bool
Overlap (have points in common)
-- Ok True
Result.map2 Range.ov
(Range.create Range.types.int (Just 3) (Just 7))
(Range.create Range.types.int (Just 4) (Just 12))
sl : Range subtype -> Range subtype -> Basics.Bool
Strictly Left of
-- Ok True
Result.map2 Range.sl
(Range.create Range.types.int (Just 1) (Just 10))
(Range.create Range.types.int (Just 100) (Just 110))
sr : Range subtype -> Range subtype -> Basics.Bool
Strictly Right of
-- Ok True
Result.map2 Range.sr
(Range.create Range.types.int (Just 50) (Just 60))
(Range.create Range.types.int (Just 20) (Just 30))
nxr : Range subtype -> Range subtype -> Basics.Bool
Does not extend to the right of
-- Ok True
Result.map2 Range.nxr
(Range.create Range.types.int (Just 1) (Just 20))
(Range.create Range.types.int (Just 18) (Just 20))
nxl : Range subtype -> Range subtype -> Basics.Bool
Does not extend to the left of
-- Ok True
Result.map2 Range.nxl
(Range.create Range.types.int (Just 7) (Just 20))
(Range.create Range.types.int (Just 5) (Just 10))
adj : Range subtype -> Range subtype -> Basics.Bool
Is Adjacent to
-- Ok True
Result.map2 Range.adj
(Range.create Range.types.float (Just 1.1) (Just 2.2))
(Range.create Range.types.float (Just 2.2) (Just 3.3))
union : Range subtype -> Range subtype -> Result String (Range subtype)
Union
-- Ok "[5,20)"
Result.map2 Range.adj
(Range.create Range.types.float (Just 5) (Just 15))
(Range.create Range.types.float (Just 10) (Just 20))
|> Result.map Range.toString
intersect : Range subtype -> Range subtype -> Range subtype
Intersection
-- Ok [10,15)
Result.map2 Range.intersect
(Range.create Range.types.float (Just 5) (Just 15))
(Range.create Range.types.float (Just 10) (Just 20))
|> Result.map Range.toString
diff : Range subtype -> Range subtype -> Result String (Range subtype)
Difference
-- Ok [5,10)
Result.map2 Range.intersect
(Range.create Range.types.float (Just 5) (Just 15))
(Range.create Range.types.float (Just 10) (Just 20))
|> Result.toString
lowerElement : Range subtype -> Maybe subtype
The element of a range's lower bound.
-- Ok (Just 1.1)
Range.create Range.types.float (Just 1.1) (Just 2.2)
|> Result.map Range.lowerElement
If the range is empty or the bound infinity then the result is Nothing
.
upperElement : Range subtype -> Maybe subtype
The element of a range's upper bound.
-- Ok (Just 2.2)
Range.create Range.types.float (Just 1.1) (Just 2.2)
|> Result.map Range.upperElement
If the range is empty or the bound infinity then the result is Nothing
.
isEmpty : Range subtype -> Basics.Bool
Is the range empty?
-- Ok False
Range.create Range.types.float (Just 1.1) (Just 2.2)
|> Result.map Range.isEmpty
lowerBoundInclusive : Range subtype -> Basics.Bool
Is the lower bound inclusive.
-- Ok True
Range.create Range.types.float (Just 1.1) (Just 2.2)
|> Result.map Range.lowerBoundInclusive
If a range is empty or the lower bound is infinite then it is not inclusive.
upperBoundInclusive : Range subtype -> Basics.Bool
Is the upper bound inclusive.
-- Ok False
Range.create Range.types.float (Just 1.1) (Just 2.2)
|> Result.map Range.upperBoundInclusive
If a range is empty or the upper bound is infinite then it is not inclusive.
lowerBoundInfinite : Range subtype -> Basics.Bool
Is the lower bound infinite.
-- Ok True
Range.create Range.types.float Nothing (Just 2.2)
|> Result.map Range.lowerBoundInfinite
If a range is empty then it is not infinite.
upperBoundInfinite : Range subtype -> Basics.Bool
Is the upper bound infinite.
-- Ok False
Range.create Range.types.float Nothing (Just 2.2)
|> Result.map Range.upperBoundInfinite
If a range is empty then it is not infinite.
merge : Range subtype -> Range subtype -> Range subtype
The smallest range which includes both of the given ranges.
Like set union, except also allow and account for non-adjacent input ranges.
-- Ok "[1,4)"
Result.map2 Range.merge
(Range.create Range.types.int (Just 1) (Just 2))
(Range.create Range.types.int (Just 3) (Just 4))
|> Result.map Range.toString