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)

Comments are closed.