1-- Constant lists: n copies of one element, their length, support, and2-- interaction with concatenation, mapping, reversal, and indexing3-- 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.Replicate9import Basic1011def listReplicate (n : Nat, x : Set) →Set12| zero, x => []13| succ(k), x => x :: listReplicate(k, x)1415theorem listReplicate.zero (x : Set)16shows listReplicate(0, x) = []17proof18simp [listReplicate]1920theorem listReplicate.succ (n : Nat) (x : Set)21shows listReplicate(succ(n), x) = x :: listReplicate(n, x)22proof23simp [listReplicate]2425theorem listReplicate.closed (A x : Set) (n : Nat)26requires element : x ∈ A27shows List(A, listReplicate(n, x))28proof29induction n30| zero =>31rw listReplicate.zero32typecheck33| succ(k) using ih =>34rw listReplicate.succ35typecheck3637theorem listReplicate.length (A x : Set) (n : Nat)38requires element : x ∈ A39shows length{A}(listReplicate(n, x)) = n40proof41induction n42| zero =>43rw [listReplicate.zero, length.nil]44rfl45| succ(k) using ih =>46have list := listReplicate.closed at A, x, k with element47rw [listReplicate.succ, length.cons, ih]48rfl4950theorem listReplicate.one (x : Set)51shows listReplicate(1, x) = x :: []52proof53simp [listReplicate]5455theorem listReplicate.support_subset (A x : Set) (n : Nat)56requires element : x ∈ A57shows listSupport{A}(listReplicate(n, x)) ⊆ {x}58proof59induction n60| zero =>61rw [listReplicate.zero, listSupport.nil]62exact empty.subset63| succ(k) using ih =>64have list := listReplicate.closed at A, x, k with element65rw [listReplicate.succ, listSupport.cons]66intros y hy67have alternatives := insert.membership.forward with hy68cases alternatives with head | rest69 . rw head70exact singleton.self at x71 . exact ih with y, rest7273theorem listReplicate.support_succ (A x : Set) (n : Nat)74requires element : x ∈ A75shows listSupport{A}(listReplicate(succ(n), x)) = {x}76proof77have list := listReplicate.closed at A, x, n with element78have subset := listReplicate.support_subset at A, x, succ(n) with element79apply Subset.antisymmetric with subset80intros y hy81have equal := singleton.membership.forward with hy82rw [equal, listReplicate.succ]83exact listSupport.mem_cons_self with element8485theorem listReplicate.mem_support (A x y : Set) (n : Nat)86requires element : x ∈ A87requires member : y ∈ listSupport{A}(listReplicate(n, x))88shows y = x89proof90have subset := listReplicate.support_subset at A, x, n with element91have single := subset with y, member92exact singleton.membership.forward with single9394theorem listReplicate.mem_support_iff (A x y : Set) (n : Nat)95requires element : x ∈ A96shows y ∈ listSupport{A}(listReplicate(n, x)) ↔0 < n ∧ y = x97proof98constructor99 . intro member100have equal := listReplicate.mem_support with element, member101have nonempty : listReplicate(n, x) ≠ []102intro empty103rw [empty, listSupport.nil] at member104exactset.empty with member105have shape := natural.zero_or_successor with*106cases shape with zero | successor107 . rw [zero, listReplicate.zero] at nonempty108exfalso109have same : [] = [] byrfl110exact nonempty with same111 . obtain⟨k, kNat, equal2⟩:= successor112rw equal2113constructor114 . arith115 . exact equal116 . intro both117obtain⟨positive, equal⟩:= both118have shape := natural.zero_or_successor with*119cases shape with zero | successor120 . rw zero at positive121exfalso122exact Less.irreflexive with Naturals.constructor.zero, positive123 . obtain⟨k, kNat, equal2⟩:= successor124rw [equal2, listReplicate.support_succ, equal]125exact singleton.self at x126127theorem listReplicate.append (A x : Set) (m n : Nat)128requires element : x ∈ A129shows append{A}(listReplicate(m, x), listReplicate(n, x)) = listReplicate(n + m, x)130proof131induction n132| zero =>133have list := listReplicate.closed at A, x, m with element134rw [listReplicate.zero, add.left_unit]135simp [append]136| succ(k) using ih =>137have list := listReplicate.closed at A, x, k with element138have other := listReplicate.closed at A, x, m with element139rw [listReplicate.succ, append.cons, ih]140have shift : succ(k) + m = succ(k + m) bysimp [add, add.succ_right]141rw [shift, listReplicate.succ]142rfl143144theorem listReplicate.map (A B f x : Set) (n : Nat)145requires function : f : A → B146requires element : x ∈ A147shows listMap{A}(f, listReplicate(n, x)) = listReplicate(n, f(x))148proof149induction n150| zero =>151rw [listReplicate.zero, listMap.nil, listReplicate.zero]152rfl153| succ(k) using ih =>154have list := listReplicate.closed at A, x, k with element155rw [listReplicate.succ, listMap.cons, ih, listReplicate.succ]156rfl157158theorem listReplicate.reverse (A x : Set) (n : Nat)159requires element : x ∈ A160shows reverse{A}(listReplicate(n, x)) = listReplicate(n, x)161proof162induction n163| zero =>164rw listReplicate.zero165simp [reverse]166| succ(k) using ih =>167have list := listReplicate.closed at A, x, k with element168have reversed : List(A, reverse(listReplicate(k, x))) bytypecheck169have single : List(A, x :: []) bytypecheck170rw [listReplicate.succ, reverse.cons, ih]171have one := listReplicate.one at x172rw [← one, listReplicate.append, add.right_one]173exact listReplicate.succ at k, x174175theorem listReplicate.tail (A x : Set) (n : Nat)176requires element : x ∈ A177shows listTail{A}(listReplicate(succ(n), x)) = listReplicate(n, x)178proof179have list := listReplicate.closed at A, x, n with element180rw [listReplicate.succ, listTail.cons]181rfl182183theorem listReplicate.coefficient (A z x : Set) (n k : Nat)184requires element : x ∈ A185requires bound : k < n186shows listCoefficient{A}(z, listReplicate(n, x), k) = x187proof188induction n generalizing k189| zero =>190intros k kNat bound191exfalso192arith193| succ(j) using ih =>194intros k kNat bound195have list := listReplicate.closed at A, x, j with element196have shape := natural.zero_or_successor at k with*197rw listReplicate.succ198cases shape with zero | successor199 . rw [zero, listCoefficient.zero]200rfl201 . obtain⟨r, rNat, equal⟩:= successor202rw equal at bound203have smaller : r < j byarith204rw [equal, listCoefficient.succ]205exact ih with r, rNat, smaller206207-- A list whose support lies in a singleton is constant.208theorem List.constant_of_support (A x : Set) (xs : List(A))209requires element : x ∈ A210requires support : listSupport{A}(xs) ⊆ {x}211shows xs = listReplicate(length{A}(xs), x)212proof213induction xs214| List.nil =>215intro support216rw [length.nil, listReplicate.zero]217rfl218| List.cons(a, tail) using ih =>219intro support220have headA : a ∈ A byassumption221have headIn := listSupport.mem_cons_self with headA222have headSingle := support with a, headIn223have head := singleton.membership.forward with headSingle224have rest : listSupport{A}(tail) ⊆ {x}225intros y hy226have member := listSupport.mem_cons_of_mem with headA, hy227exact support with y, member228have tails := ih with rest229rw [length.cons, listReplicate.succ, head]230rw← tails231rfl232233theorem listReplicate.injective_length (A x : Set) (m n : Nat)234requires element : x ∈ A235requires equal : listReplicate(m, x) = listReplicate(n, x)236shows m = n237proof238have lengths : length{A}(listReplicate(m, x)) = length{A}(listReplicate(n, x))239rw equal240rfl241rw [listReplicate.length, listReplicate.length] at lengths242exact lengths243