lean4-htt/src/Init/Data/Range.lean
2021-06-29 17:14:52 -07:00

58 lines
1.9 KiB
Text

/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Init.Meta
namespace Std
-- We put `Range` in `Init` because we want the notation `[i:j]` without importing `Std`
-- We don't put `Range` in the top-level namespace to avoid collisions with user defined types
structure Range where
start : Nat := 0
stop : Nat
step : Nat := 1
namespace Range
universe u v
@[inline] protected def forIn {β : Type u} {m : Type u → Type v} [Monad m] (range : Range) (init : β) (f : Nat → β → m (ForInStep β)) : m β :=
let rec @[specialize] loop (i : Nat) (j : Nat) (b : β) : m β := do
if j ≥ range.stop then
pure b
else match i with
| 0 => pure b
| i+1 => match (← f j b) with
| ForInStep.done b => pure b
| ForInStep.yield b => loop i (j + range.step) b
loop range.stop range.start init
instance : ForIn m Range Nat where
forIn := Range.forIn
@[inline] protected def forM {m : Type u → Type v} [Monad m] (range : Range) (f : Nat → m PUnit) : m PUnit :=
let rec @[specialize] loop (i : Nat) (j : Nat) : m PUnit := do
if j ≥ range.stop then
pure ⟨⟩
else match i with
| 0 => pure ⟨⟩
| i+1 => f j; loop i (j + range.step)
loop range.stop range.start
instance : ForM m Range Nat where
forM := Range.forM
syntax:max "[" ":" term "]" : term
syntax:max "[" term ":" term "]" : term
syntax:max "[" ":" term ":" term "]" : term
syntax:max "[" term ":" term ":" term "]" : term
macro_rules
| `([ : $stop]) => `({ stop := $stop : Range })
| `([ $start : $stop ]) => `({ start := $start, stop := $stop : Range })
| `([ $start : $stop : $step ]) => `({ start := $start, stop := $stop, step := $step : Range })
| `([ : $stop : $step ]) => `({ stop := $stop, step := $step : Range })
end Range
end Std