| /- | |
| 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 | |
| instance : Membership Nat Range where | |
| mem i r := r.start ≤ i ∧ i < r.stop | |
| 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 β := | |
| -- pass `stop` and `step` separately so the `range` object can be eliminated through inlining | |
| let rec @[specialize] loop (fuel i stop step : Nat) (b : β) : m β := do | |
| if i ≥ stop then | |
| return b | |
| else match fuel with | |
| | 0 => pure b | |
| | fuel+1 => match (← f i b) with | |
| | ForInStep.done b => pure b | |
| | ForInStep.yield b => loop fuel (i + step) stop step b | |
| loop range.stop range.start range.stop range.step init | |
| instance : ForIn m Range Nat where | |
| forIn := Range.forIn | |
| @[inline] protected def forIn' {β : Type u} {m : Type u → Type v} [Monad m] (range : Range) (init : β) (f : (i : Nat) → i ∈ range → β → m (ForInStep β)) : m β := | |
| let rec @[specialize] loop (start stop step : Nat) (f : (i : Nat) → start ≤ i ∧ i < stop → β → m (ForInStep β)) (fuel i : Nat) (hl : start ≤ i) (b : β) : m β := do | |
| if hu : i < stop then | |
| match fuel with | |
| | 0 => pure b | |
| | fuel+1 => match (← f i ⟨hl, hu⟩ b) with | |
| | ForInStep.done b => pure b | |
| | ForInStep.yield b => loop start stop step f fuel (i + step) (Nat.le_trans hl (Nat.le_add_right ..)) b | |
| else | |
| return b | |
| loop range.start range.stop range.step f range.stop range.start (Nat.le_refl ..) init | |
| instance : ForIn' m Range Nat inferInstance 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 (fuel i stop step : Nat) : m PUnit := do | |
| if i ≥ stop then | |
| pure ⟨⟩ | |
| else match fuel with | |
| | 0 => pure ⟨⟩ | |
| | fuel+1 => f i; loop fuel (i + step) stop step | |
| loop range.stop range.start range.stop range.step | |
| instance : ForM m Range Nat where | |
| forM := Range.forM | |
| syntax:max "[" withoutPosition(":" term) "]" : term | |
| syntax:max "[" withoutPosition(term ":" term) "]" : term | |
| syntax:max "[" withoutPosition(":" term ":" term) "]" : term | |
| syntax:max "[" withoutPosition(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 | |
| theorem Membership.mem.upper {i : Nat} {r : Std.Range} (h : i ∈ r) : i < r.stop := h.2 | |
| theorem Membership.mem.lower {i : Nat} {r : Std.Range} (h : i ∈ r) : r.start ≤ i := h.1 | |
| theorem Membership.get_elem_helper {i n : Nat} {r : Std.Range} (h₁ : i ∈ r) (h₂ : r.stop = n) : | |
| i < n := h₂ ▸ h₁.2 | |
| macro_rules | |
| | `(tactic| get_elem_tactic_trivial) => `(tactic| apply Membership.get_elem_helper; assumption; rfl) |