@@ -12,53 +12,81 @@ import Stdlib.Data.Nat open;
1212type Range N :=
1313 mkRange {
1414 low : N;
15- high : N;
16- step : N
15+ high : N
1716 };
1817
19- syntax iterator for {init := 1; range := 1};
20-
21- {-# specialize: [1, 2, 3, 5] #-}
22- for {A N} {{Ord N}} {{Natural N}} (f : A → N → A) (a : A) : Range N → A
23- | mkRange@{low; high; step} :=
24- let
25- {-# specialize-by: [f] #-}
26- terminating
27- go (acc : A) (n : N) : A := ite (n > high) acc (go (f acc n) (n + step));
28- in go a low;
18+ type StepRange N :=
19+ mkStepRange {
20+ range : Range N;
21+ step : N
22+ };
2923
3024syntax operator to range;
3125
3226--- `x to y` is the range [x..y]
3327{-# inline: always #-}
34- to {N} {{Natural N}} (l h : N) : Range N := mkRange l h 1 ;
28+ to {N} {{Natural N}} (l h : N) : Range N := mkRange l h;
3529
3630syntax operator step step;
3731
3832--- `x to y step s` is the range [x, x + s, ..., y]
3933{-# inline: always #-}
40- step {N} (r : Range N) (s : N) : Range N := r@Range{step := s};
34+ step {N} (r : Range N) (s : N) : StepRange N := mkStepRange r s;
35+
36+ -- This instance assumes that `low <= high`.
37+ {-# specialize: true, inline: case #-}
38+ instance
39+ foldableRangeI {N} {{Eq N}} {{Natural N}} : Foldable (Range N) N :=
40+ mkFoldable@{
41+ {-# specialize: [1, 3] #-}
42+ for {B : Type} (f : B -> N -> B) (ini : B) : Range N -> B
43+ | (mkRange low high) :=
44+ let
45+ {-# specialize-by: [f, high] #-}
46+ terminating
47+ go (acc : B) (next : N) : B :=
48+ if
49+ | next == high := f acc next
50+ | else := go (f acc next) (next + 1);
51+ in go ini low;
52+ {-# specialize: [1, 3] #-}
53+ rfor {B : Type} (f : B -> N -> B) (ini : B) : Range N -> B
54+ | (mkRange low high) :=
55+ let
56+ {-# specialize-by: [f, high] #-}
57+ terminating
58+ go (next : N) : B :=
59+ if
60+ | next == high := f ini next
61+ | else := f (go (next + 1)) next;
62+ in go low
63+ };
4164
4265-- This instance assumes that (low + step*k > high) for some k.
66+ {-# specialize: true, inline: case #-}
4367instance
44- foldableRangeI {N} {{Ord N}} {{Natural N}} : Foldable (Range N) N :=
68+ foldableStepRangeI {N} {{Ord N}} {{Natural N}} : Foldable (StepRange N) N :=
4569 mkFoldable@{
46- for {B : Type} (g : B -> N -> B) (ini : B) : Range N -> B
47- | (mkRange low high step) :=
70+ {-# specialize: [1, 3] #-}
71+ for {B : Type} (f : B -> N -> B) (ini : B) : StepRange N -> B
72+ | (mkStepRange (mkRange low high) step) :=
4873 let
74+ {-# specialize-by: [f, high, step] #-}
4975 terminating
5076 go (acc : B) (next : N) : B :=
5177 if
52- | next <= high := go (g acc next) (next + step)
53- | else := acc;
78+ | next > high := acc
79+ | else := go (f acc next) (next + step) ;
5480 in go ini low;
55- rfor {B : Type} (g : B -> N -> B) (ini : B) : Range N -> B
56- | (mkRange low high step) :=
81+ {-# specialize: [1, 3] #-}
82+ rfor {B : Type} (f : B -> N -> B) (ini : B) : StepRange N -> B
83+ | (mkStepRange (mkRange low high) step) :=
5784 let
85+ {-# specialize-by: [f, high, step] #-}
5886 terminating
59- go (base : B) ( next : N) : B :=
87+ go (next : N) : B :=
6088 if
61- | next <= high := g (go base (next + step)) next
62- | else := base ;
63- in go ini low
89+ | next <= high := f (go (next + step)) next
90+ | else := ini ;
91+ in go low
6492 };
0 commit comments