1-- Concatenation of lists: how indexing reads through it, cancellation on2-- either side, and mapping over it3-- 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.Append9import Algebra.IndexedLists1011-- append(ys, xs) is xs followed by ys. Positions below the length of xs12-- read xs; later positions read ys, shifted by that length.13theorem listCoefficient.append_left (A z : Set) (xs ys : List(A)) (n : Nat)14requires bound : n < length{A}(xs)15shows listCoefficient{A}(z, append(ys, xs), n) = listCoefficient{A}(z, xs, n)16proof17induction xs generalizing n18| List.nil =>19intros n nNat bound20rw length.nil at bound21arith22| List.cons(a, tail) using ih =>23intros n nNat bound24have element : a ∈ A byassumption25have appended : List(A, append(ys, tail)) bytypecheck26rw append27have shape := natural.zero_or_successor with*28cases shape with zero | successor29 . rw [zero, listCoefficient.zero, listCoefficient.zero]30rfl31 . obtain⟨r, rNat, equal⟩:= successor32rw [equal, length.cons] at bound33have smaller : r < length{A}(tail) byarith34rw [equal, listCoefficient.succ, listCoefficient.succ]35exact ih with r, rNat, smaller3637theorem listCoefficient.append_right (A z : Set) (xs ys : List(A)) (n : Nat)38shows listCoefficient{A}(z, append(ys, xs), n + length{A}(xs)) = listCoefficient{A}(z, ys, n)39proof40induction xs41| List.nil =>42rw [append, length.nil, add.right_unit]43rfl44| List.cons(a, tail) using ih =>45have element : a ∈ A byassumption46have appended : List(A, append(ys, tail)) bytypecheck47 rwa [append, length.cons, add.succ_right, listCoefficient.succ]4849-- Cancellation: a common first part, or a common last part, can be dropped.50theorem append.cancel_first (A : Set) (xs ys zs : List(A))51requires equal : append(ys, xs) = append(zs, xs)52shows ys = zs53proof54have lengths : length{A}(append(ys, xs)) = length{A}(append(zs, xs))55rw equal56rfl57rw [length.append, length.append] at lengths58have sameLength := add.left_cancel with lengths59apply listCoefficient.ext at A, ∅, ys, zs with sameLength60intros n nNat bound61haveleft:= listCoefficient.append_right at A, ∅, xs, ys, n with*62haveright:= listCoefficient.append_right at A, ∅, xs, zs, n with*63rw equal atleft64 rwa ←left6566theorem append.cancel_last (A : Set) (xs ys zs : List(A))67requires equal : append(xs, ys) = append(xs, zs)68shows ys = zs69proof70have lengths : length{A}(append(xs, ys)) = length{A}(append(xs, zs))71rw equal72rfl73rw [length.append, length.append] at lengths74have sameLength := add.right_cancel with lengths75apply listCoefficient.ext at A, ∅, ys, zs with sameLength76intros n nNat bound77have boundZs : n < length{A}(zs) by rwa ← sameLength78haveleft:= listCoefficient.append_left at A, ∅, ys, xs, n with*79haveright:= listCoefficient.append_left at A, ∅, zs, xs, n with boundZs, *80rw equal atleft81 rwa ←left8283theorem listMap.append (A B f : Set) (xs ys : List(A))84requires function : f : A → B85shows listMap{A}(f, append(ys, xs)) = append{B}(listMap{A}(f, ys), listMap{A}(f, xs))86proof87induction xs88| List.nil =>89rw [append, listMap, append]90rfl91| List.cons(a, tail) using ih =>92have element : a ∈ A byassumption93have image := FunctionBetween.apply_closed with function, element94rw [append, listMap, listMap, ih, append]95rfl96