module Stdlib.Data.Range;
import Stdlib.Data.Fixity open;
import Stdlib.Data.Bool.Base open;
import Stdlib.Trait.Natural open;
import Stdlib.Trait.Ord open;
import Stdlib.Trait.Foldable open;
import Stdlib.Data.Nat open;
--- An inclusive range of naturals
type Range N :=
mkRange@{
low : N;
high : N;
};
type StepRange N :=
mkStepRange@{
range : Range N;
step : N;
};
syntax operator to range;
--- `x to y` is the range [x..y]
to {N} {{Natural N}} (low high : N) : Range N := mkRange low high;
syntax operator step step;
--- `x to y step s` is the range [x, x + s, ..., y]
step {N} (range : Range N) (step : N) : StepRange N := mkStepRange range step;
instance
foldableRangeI {N} {{Eq N}} {{Natural N}} : Foldable (Range N) N :=
mkFoldable@{
for {B : Type} (fun : B -> N -> B) (initialValue : B) : Range N -> B
| (mkRange low high) :=
let
terminating
go (acc : B) (next : N) : B :=
if
| next == high := fun acc next
| else := go (fun acc next) (next + 1);
in go initialValue low;
rfor {B : Type} (fun : B -> N -> B) (initialValue : B) : Range N -> B
| (mkRange low high) :=
let
terminating
go (next : N) : B :=
if
| next == high := fun initialValue next
| else := fun (go (next + 1)) next;
in go low;
};
instance
foldableStepRangeI {N} {{Ord N}} {{Natural N}} : Foldable (StepRange N) N :=
mkFoldable@{
for {B : Type} (fun : B -> N -> B) (initialValue : B) : StepRange N -> B
| (mkStepRange (mkRange low high) step) :=
let
terminating
go (acc : B) (next : N) : B :=
if
| next > high := acc
| else := go (fun acc next) (next + step);
in go initialValue low;
rfor {B : Type} (fun : B -> N -> B) (initialValue : B) : StepRange N -> B
| (mkStepRange (mkRange low high) step) :=
let
terminating
go (next : N) : B :=
if
| next <= high := fun (go (next + step)) next
| else := initialValue;
in go low;
};