1-- The list of the first n natural numbers in order: length, entries,2-- support, sortedness, counts, and prefixes3-- Part of Cumulus, the Grace17 mathematics library.4-- Copyright (c) 2026 Grant Passmore.5-- Released under the Apache License 2.0. See LICENSE in the repository root.6-- Authors: Grant Passmore78module Grace.Cumulus.List.Range9import Sorted1011def listRange (n : Nat) →Set12| zero => []13| succ(k) => append{ℕ}(k :: [], listRange(k))1415theorem listRange.zero16shows listRange(0) = []17proof18simp [listRange]1920theorem listRange.succ (n : Nat)21shows listRange(succ(n)) = append{ℕ}(n :: [], listRange(n))22proof23simp [listRange]2425theorem listRange.closed (n : Nat)26shows List(ℕ, listRange(n))27proof28induction n29| zero =>30rw listRange.zero31typecheck32| succ(k) using ih =>33have kIn : k ∈ ℕ := nat.omega.forward with*34have single : List(ℕ, k :: []) bytypecheck35rw listRange.succ36typecheck3738theorem listRange.length (n : Nat)39shows length{ℕ}(listRange(n)) = n40proof41induction n42| zero =>43rw [listRange.zero, length.nil]44rfl45| succ(k) using ih =>46have kIn : k ∈ ℕ := nat.omega.forward with*47have single : List(ℕ, k :: []) bytypecheck48have list := listRange.closed at k with*49rw [listRange.succ, length.append, ih, length.singleton, add.right_one]50rfl5152theorem listRange.coefficient (n i : Nat)53requires bound : i < n54shows listCoefficient{ℕ}(0, listRange(n), i) = i55proof56induction n57| zero =>58intro bound59exfalso60arith61| succ(k) using ih =>62intro bound63have kIn : k ∈ ℕ := nat.omega.forward with*64have list := listRange.closed at k with*65have length := listRange.length at k with*66rw listRange.succ67have alternatives : i < k ∨¬(i < k) bytauto68cases alternatives with below | notBelow69 . have inside : i < length{ℕ}(listRange(k)) by rwa length70have step := listCoefficient.snoc_below at ℕ, 0, k, listRange(k), i with kIn, inside71rw step72exact ih with below73 . have atLeast := LessEqual.of_not_Less at i, k with notBelow74have same : i = k75have upper := Less.successor_upper with bound76exact LessEqual.antisymmetric with upper, atLeast77have last := listCoefficient.snoc_last at ℕ, 0, k, listRange(k) with kIn78rw length at last79rw same80exact last8182theorem listRange.mem_support (n : Nat)83shows∀ y, y ∈ listSupport{ℕ}(listRange(n)) ↔ y ∈ n84proof85induction n86| zero =>87intro y88rw [listRange.zero, listSupport.nil]89constructor90 . intro member91exfalso92exactset.empty with member93 . intro member94have zero : y ∈∅by rwa ← nat.zero95exfalso96exactset.empty with zero97| succ(k) using ih =>98intro y99have kIn : k ∈ ℕ := nat.omega.forward with*100have single : List(ℕ, k :: []) bytypecheck101have list := listRange.closed at k with*102have successor := natural.successor_as_insert at k with*103have inner := ih with y104rw [listRange.succ, listSupport.append, listSupport.singleton, successor]105have union := union2.membership at y, listSupport{ℕ}(listRange(k)), {k}106have insertion := insert.membership at y, k, k107have singleton := singleton.membership at y, k108tauto109110theorem listRange.support (n : Nat)111shows listSupport{ℕ}(listRange(n)) = n112proof113have members := listRange.mem_support at n with*114ext y115exact members with y116117theorem listRange.mem_support_iff (n : Nat) (y : Set)118shows y ∈ listSupport{ℕ}(listRange(n)) ↔ (Nat(y) ∧ y < n)119proof120rw listRange.support121constructor122 . intro member123have natural := natural.member at n with*124have yNat := natural with y, member125have below := Less.of_membership at y, n with*, member126exact⟨yNat, below⟩127 . intro both128obtain⟨yNat, below⟩:= both129exact membership.of_Less at y, n with*, below130131theorem listRange.sorted (n : Nat)132shows ListSorted(listRange(n))133proof134have list := listRange.closed at n with*135have length := listRange.length at n with*136unfold ListSorted137intros i j iNat jNat below bound138rw length at bound139have smaller : i < n byarith140haveleft:= listRange.coefficient at n, i with smaller141haveright:= listRange.coefficient at n, j with bound142rw [left, right]143exact Less.implies_LessEqual with below144145theorem listRange.count_below (n i : Nat)146requires bound : i < n147shows listCount{ℕ}(i, listRange(n)) =1148proof149induction n150| zero =>151intro bound152exfalso153arith154| succ(k) using ih =>155intro bound156have kIn : k ∈ ℕ := nat.omega.forward with*157have single : List(ℕ, k :: []) bytypecheck158have list := listRange.closed at k with*159rw [listRange.succ, listCount.append]160have alternatives : i < k ∨¬(i < k) bytauto161cases alternatives with below | notBelow162 . have inner := ih with below163have different : i ≠ k164intro same165rw same at below166exact Less.irreflexive with*, below167have other := listCount.singleton_other at ℕ, i, k with kIn, different168rw [inner, other, add.right_unit]169rfl170 . have atLeast := LessEqual.of_not_Less at i, k with notBelow171have same : i = k172have upper := Less.successor_upper with bound173exact LessEqual.antisymmetric with upper, atLeast174have absent : ¬(i ∈ listSupport{ℕ}(listRange(k)))175intro member176have both := listRange.mem_support_iff.forward at k, i with member177rw same at both178have strict := both.right179exact Less.irreflexive at k with*, strict180have zero := listCount.zero_of_absent with absent181rw [zero, same, listCount.singleton_self, add.left_unit]182rfl183184theorem listRange.count_above (n i : Nat)185requires bound : n ≤ i186shows listCount{ℕ}(i, listRange(n)) =0187proof188have list := listRange.closed at n with*189have absent : ¬(i ∈ listSupport{ℕ}(listRange(n)))190intro member191have both := listRange.mem_support_iff.forward at n, i with member192have below := both.right193have strict : i < i byarith194exact Less.irreflexive at i with*, strict195exact listCount.zero_of_absent with absent196197theorem listRange.prefix (m n : Nat)198requires bound : m ≤ n199shows ListPrefix(ℕ, listRange(m), listRange(n))200proof201induction n202| zero =>203intro bound204have zero : m =0205have lower : 0≤ m byarith206exact LessEqual.antisymmetric with bound, lower207rw [zero, listRange.zero]208have nilList : List(ℕ, []) bytypecheck209exact ListPrefix.reflexive at ℕ, [] with*210| succ(k) using ih =>211intro bound212have kIn : k ∈ ℕ := nat.omega.forward with*213have single : List(ℕ, k :: []) bytypecheck214have list := listRange.closed at k with*215have listM := listRange.closed at m with*216have alternatives : m ≤ k ∨¬(m ≤ k) bytauto217cases alternatives with below | notBelow218 . have inner := ih with below219have extend := ListPrefix.append at ℕ, listRange(k), k :: [] with*220rw listRange.succ221exact ListPrefix.transitive with inner, extend222 . have above := Less.of_not_LessEqual at m, k with notBelow223have same : m = succ(k)224have upper : m ≤ succ(k) := bound225have lower : succ(k) ≤ m byarith226exact LessEqual.antisymmetric with upper, lower227rw same228have listSucc := listRange.closed at succ(k) with*229exact ListPrefix.reflexive at ℕ, listRange(succ(k)) with*230231theorem listRange.take (m n : Nat)232requires bound : m ≤ n233shows listTake{ℕ}(m, listRange(n)) = listRange(m)234proof235haveprefix:= listRange.prefix with bound236have listM := listRange.closed at m with*237have listN := listRange.closed at n with*238have taken := ListPrefix.eq_take withprefix239rw listRange.length at taken240 symm241exact taken242