An immutable range library in F# where a range is only defined by a minimum and a maximum value (hence, there is no step).
Source
type Range<'a when 'a:comparison> =
{ Min : 'a
Max : 'a
}
override x.ToString() =
sprintf "Range (%A, %A)" x.Min x.Max
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Range =
type t<'a when 'a:comparison> = Range<'a>
let checkMinMax min max =
if min > max then invalidArg "min" <| sprintf "min:%A > max:%A" min max
let isValid r = r.Min <= r.Max
let checkRange r =
if not <| isValid r then invalidArg "r" <| sprintf "r.Min:%A > r.Max:%A" r.Min r.Max
let create min max =
checkMinMax min max
{ Min = min
Max = max
}
let contains x r =
checkRange r
r.Min <= x && x <= r.Max
let englobes r' r =
checkRange r'
checkRange r
contains (r'.Min) r && contains (r'.Max) r
let startsBefore x r =
checkRange r
r.Min < x
let startsAfter x r =
checkRange r
r.Min > x
let endsBefore x r =
checkRange r
r.Max < x
let endsAfter x r =
checkRange r
r.Max > x
let areAdjacent r r' =
checkRange r'
checkRange r
r'.Min = r.Max || r.Min = r'.Max
let doIntersect r r' =
checkRange r'
checkRange r
contains (r'.Min) r || contains (r'.Max) r || englobes r r'
let intersection r r' =
checkRange r'
checkRange r
if doIntersect r r' then
Some <| create (max (r.Min) (r'.Min)) (min (r.Max) (r'.Max))
else
None
let merge r r' =
checkRange r'
checkRange r
if doIntersect r r' then
Some <| create (min (r.Min) (r'.Min)) (max (r.Max) (r'.Max))
else
None
let inline length r = r.Max - r.Min
Signature
type Range<'a when 'a:comparison> =
{ Min : 'a
Max : 'a
}
override ToString : unit -> string
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Range =
type t<'a when 'a:comparison> = Range<'a>
///[create low high] returns a new [Range] initialized with [low] and [high] as its bounds.
val create : low:'a -> high:'a -> Range<'a>
///[contains x r] returns true if [x] falls within the bounds of [r].
val contains : x:'a -> r:t<'a> -> bool
///[englobes r' r] returns true if [r'] is englobed by [r].
val englobes : r':t<'a> -> r:t<'a> -> bool
///[startsBefore x r] returns true if [r] starts before [x], i.e. [x > LowerBound r].
val startsBefore : x:'a -> r:t<'a> -> bool
///[startsAfter x r] returns true if [r] starts after [x], i.e. [x < LowerBound r].
val startsAfter : x:'a -> r:t<'a> -> bool
///[endsBefore x r] returns true if [r] ends before [x], i.e. [x > UpperBound r].
val endsBefore : x:'a -> r:t<'a> -> bool
///[endsAfter x r] returns true if [r] ends after [x], i.e. [x < UpperBound r].
val endsAfter : x:'a -> r:t<'a> -> bool
///[areAdjacent r r'] returns true if [r] and [r'] share a bound.
val areAdjacent : r:t<'a> -> r':t<'a> -> bool
///[doIntersect r r'] returns true if [r] and [r'] cross over.
val doIntersect : r:t<'a> -> r':t<'a> -> bool
///[intersection r r'] returns [None] if [r] and [r'] don't intersect
///[Some x] if they do intersect, where [x] is the [Range]
///where [r] and [r'] intersect.
val intersection : r:t<'a> -> r':t<'a> -> option<t<'a>>
///[merge r r'] returns [None] if [r] and [r'] don't intersect
///[Some x] if they do intersect, where [x] is the [Range]
///with the lowest bound and uppest bound of [r] and [r'].
val merge : r:t<'a> -> r':t<'a> -> option<t<'a>>
///[length r] returns the difference between the upper and lower bounds of [r].
val inline length : t< ^a> -> ^b when ^a : (static member ( - ) : ^a * ^a -> ^b)
