1-- Prefixes and suffixes of a list: take and drop, their lengths, how they2-- recombine, and how they read through concatenation, mapping, 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.TakeDrop9import Replicate1011def listTake {A : Set} (n : Nat) (xs : List(A)) →Set12| n, List.nil => []13| n, List.cons(a, tail) =>14 boolChoice(isZero(n), [], a :: listTake(predecessor(n), tail))15descends xs1617def listDrop {A : Set} (n : Nat) (xs : List(A)) →Set18| n, List.nil => []19| n, List.cons(a, tail) =>20 boolChoice(isZero(n), a :: tail, listDrop(predecessor(n), tail))21descends xs2223theorem listTake.nil (A : Set) (n : Nat)24shows listTake{A}(n, []) = []25proof26simp [listTake]2728theorem listTake.zero (A : Set) (xs : List(A))29shows listTake{A}(0, xs) = []30proof31induction xs32| List.nil =>simp [listTake]33| List.cons(a, tail) using ih =>simp [listTake, isZero, boolChoice]3435theorem listTake.succ_cons (A a : Set) (xs : List(A)) (n : Nat)36requires element : a ∈ A37shows listTake{A}(succ(n), a :: xs) = a :: listTake{A}(n, xs)38proof39simp [listTake, isZero, predecessor, boolChoice]4041theorem listDrop.nil (A : Set) (n : Nat)42shows listDrop{A}(n, []) = []43proof44simp [listDrop]4546theorem listDrop.zero (A : Set) (xs : List(A))47shows listDrop{A}(0, xs) = xs48proof49induction xs50| List.nil =>simp [listDrop]51| List.cons(a, tail) using ih =>simp [listDrop, isZero, boolChoice]5253theorem listDrop.succ_cons (A a : Set) (xs : List(A)) (n : Nat)54requires element : a ∈ A55shows listDrop{A}(succ(n), a :: xs) = listDrop{A}(n, xs)56proof57simp [listDrop, isZero, predecessor, boolChoice]5859theorem listTake.closed (A : Set) (xs : List(A)) (n : Nat)60shows List(A, listTake{A}(n, xs))61proof62induction xs generalizing n63| List.nil =>64intros n nNat65rw listTake.nil66typecheck67| List.cons(a, tail) using ih =>68intros n nNat69have element : a ∈ A byassumption70have whole : List(A, a :: tail) bytypecheck71have shape := natural.zero_or_successor with*72cases shape with zero | successor73 . rw [zero, listTake.zero]74typecheck75 . obtain⟨k, kNat, equal⟩:= successor76have inner := ih with k, kNat77rw [equal, listTake.succ_cons]78typecheck7980theorem listDrop.closed (A : Set) (xs : List(A)) (n : Nat)81shows List(A, listDrop{A}(n, xs))82proof83induction xs generalizing n84| List.nil =>85intros n nNat86rw listDrop.nil87typecheck88| List.cons(a, tail) using ih =>89intros n nNat90have element : a ∈ A byassumption91have whole : List(A, a :: tail) bytypecheck92have shape := natural.zero_or_successor with*93cases shape with zero | successor94 . rw [zero, listDrop.zero]95typecheck96 . obtain⟨k, kNat, equal⟩:= successor97have inner := ih with k, kNat98rw [equal, listDrop.succ_cons]99exact inner100101-- The prefix followed by the suffix is the list.102theorem listTake.append_drop (A : Set) (xs : List(A)) (n : Nat)103shows append(listDrop{A}(n, xs), listTake{A}(n, xs)) = xs104proof105induction xs generalizing n106| List.nil =>107intros n nNat108rw [listTake.nil, listDrop.nil]109simp [append]110| List.cons(a, tail) using ih =>111intros n nNat112have element : a ∈ A byassumption113have whole : List(A, a :: tail) bytypecheck114have shape := natural.zero_or_successor with*115cases shape with zero | successor116 . rw [zero, listTake.zero, listDrop.zero]117simp [append]118 . obtain⟨k, kNat, equal⟩:= successor119have inner := ih with k, kNat120have taken := listTake.closed at A, tail, k with*121have dropped := listDrop.closed at A, tail, k with*122rw [equal, listTake.succ_cons, listDrop.succ_cons, append.cons, inner]123rfl124125theorem listTake.length_le_count (A : Set) (xs : List(A)) (n : Nat)126shows length{A}(listTake{A}(n, xs)) ≤ n127proof128induction xs generalizing n129| List.nil =>130intros n nNat131rw [listTake.nil, length.nil]132arith133| List.cons(a, tail) using ih =>134intros n nNat135have element : a ∈ A byassumption136have whole : List(A, a :: tail) bytypecheck137have shape := natural.zero_or_successor with*138cases shape with zero | successor139 . rw [zero, listTake.zero, length.nil]140arith141 . obtain⟨k, kNat, equal⟩:= successor142have inner := ih with k, kNat143have taken := listTake.closed at A, tail, k with*144rw [equal, listTake.succ_cons, length.cons]145arith146147theorem listTake.length_le (A : Set) (xs : List(A)) (n : Nat)148shows length{A}(listTake{A}(n, xs)) ≤ length{A}(xs)149proof150havesplit:= listTake.append_drop at A, xs, n with*151have taken := listTake.closed at A, xs, n with*152have dropped := listDrop.closed at A, xs, n with*153have bound := append.length_left_le at A, listTake{A}(n, xs), listDrop{A}(n, xs) with*154 rwa splitat bound155156theorem listDrop.length_le (A : Set) (xs : List(A)) (n : Nat)157shows length{A}(listDrop{A}(n, xs)) ≤ length{A}(xs)158proof159havesplit:= listTake.append_drop at A, xs, n with*160have taken := listTake.closed at A, xs, n with*161have dropped := listDrop.closed at A, xs, n with*162have bound := append.length_right_le at A, listTake{A}(n, xs), listDrop{A}(n, xs) with*163 rwa splitat bound164165theorem listTake.length (A : Set) (xs : List(A)) (n : Nat)166requires bound : n ≤ length{A}(xs)167shows length{A}(listTake{A}(n, xs)) = n168proof169induction xs generalizing n170| List.nil =>171intros n nNat bound172rw length.nil at bound173have shape := natural.zero_or_successor with*174cases shape with zero | successor175 . rw [zero, listTake.nil, length.nil]176rfl177 . obtain⟨k, kNat, equal⟩:= successor178rw equal at bound179exfalso180arith181| List.cons(a, tail) using ih =>182intros n nNat bound183have element : a ∈ A byassumption184have whole : List(A, a :: tail) bytypecheck185rw length.cons at bound186have shape := natural.zero_or_successor with*187cases shape with zero | successor188 . rw [zero, listTake.zero, length.nil]189rfl190 . obtain⟨k, kNat, equal⟩:= successor191rw equal at bound192have smaller : k ≤ length{A}(tail) byarith193have inner := ih with k, kNat, smaller194have taken := listTake.closed at A, tail, k with*195rw [equal, listTake.succ_cons, length.cons, inner]196rfl197198theorem listTake.all (A : Set) (xs : List(A)) (n : Nat)199requires bound : length{A}(xs) ≤ n200shows listTake{A}(n, xs) = xs201proof202induction xs generalizing n203| List.nil =>204intros n nNat bound205exact listTake.nil at A, n206| List.cons(a, tail) using ih =>207intros n nNat bound208have element : a ∈ A byassumption209have whole : List(A, a :: tail) bytypecheck210rw length.cons at bound211have shape := natural.zero_or_successor with*212cases shape with zero | successor213 . rw zero at bound214exfalso215arith216 . obtain⟨k, kNat, equal⟩:= successor217rw equal at bound218have smaller : length{A}(tail) ≤ k byarith219have inner := ih with k, kNat, smaller220rw [equal, listTake.succ_cons, inner]221rfl222223theorem listTake.self (A : Set) (xs : List(A))224shows listTake{A}(length{A}(xs), xs) = xs225proof226have reflexive := LessEqual.reflexive at length{A}(xs) with*227exact listTake.all with reflexive228229theorem listDrop.all (A : Set) (xs : List(A)) (n : Nat)230requires bound : length{A}(xs) ≤ n231shows listDrop{A}(n, xs) = []232proof233induction xs generalizing n234| List.nil =>235intros n nNat bound236exact listDrop.nil at A, n237| List.cons(a, tail) using ih =>238intros n nNat bound239have element : a ∈ A byassumption240have whole : List(A, a :: tail) bytypecheck241rw length.cons at bound242have shape := natural.zero_or_successor with*243cases shape with zero | successor244 . rw zero at bound245exfalso246arith247 . obtain⟨k, kNat, equal⟩:= successor248rw equal at bound249have smaller : length{A}(tail) ≤ k byarith250have inner := ih with k, kNat, smaller251rw [equal, listDrop.succ_cons, inner]252rfl253254theorem listDrop.self (A : Set) (xs : List(A))255shows listDrop{A}(length{A}(xs), xs) = []256proof257have reflexive := LessEqual.reflexive at length{A}(xs) with*258exact listDrop.all with reflexive259260theorem listDrop.length (A : Set) (xs : List(A)) (n : Nat)261requires bound : n ≤ length{A}(xs)262shows length{A}(listDrop{A}(n, xs)) + n = length{A}(xs)263proof264havesplit:= listTake.append_drop at A, xs, n with*265have taken := listTake.closed at A, xs, n with*266have dropped := listDrop.closed at A, xs, n with*267have lengths := length.append at A, listDrop{A}(n, xs), listTake{A}(n, xs) with*268rw [split, listTake.length] at lengths269 symm at lengths270 rwa add.commutative at lengths271272theorem listTake.eq_nil (A : Set) (xs : List(A)) (n : Nat)273requires empty : listTake{A}(n, xs) = []274shows n =0∨ xs = []275proof276have shape := natural.zero_or_successor with*277cases shape with zero | successor278 . left279exact zero280 . right281obtain⟨k, kNat, equal⟩:= successor282have listShape := List.cases with*283cases listShape with nil | cons284 . exact nil285 . obtain⟨a, element, tail, tailList, equal2⟩:= cons286rw [equal, equal2, listTake.succ_cons] at empty287have taken := listTake.closed at A, tail, k with*288exfalso289have distinct := List.cons_ne_nil at A, a, listTake{A}(k, tail) with element290exact distinct with empty291292theorem listTake.take (A : Set) (xs : List(A)) (m n : Nat)293requires bound : m ≤ n294shows listTake{A}(m, listTake{A}(n, xs)) = listTake{A}(m, xs)295proof296induction xs generalizing m n297| List.nil =>298intros m n mNat nNat bound299rw [listTake.nil, listTake.nil]300rfl301| List.cons(a, tail) using ih =>302intros m n mNat nNat bound303have element : a ∈ A byassumption304have whole : List(A, a :: tail) bytypecheck305have outer := listTake.closed at A, a :: tail, n with*306have shapeM := natural.zero_or_successor at m with mNat307cases shapeM with zeroM | successorM308 . rw [zeroM, listTake.zero, listTake.zero]309rfl310 . obtain⟨j, jNat, equalM⟩:= successorM311have shapeN := natural.zero_or_successor at n with nNat312cases shapeN with zeroN | successorN313 . rw [equalM, zeroN] at bound314exfalso315arith316 . obtain⟨k, kNat, equalN⟩:= successorN317rw [equalM, equalN] at bound318have smaller : j ≤ k byarith319have inner := ih with j, k, jNat, kNat, smaller320have taken := listTake.closed at A, tail, k with*321rw [equalM, equalN, listTake.succ_cons, listTake.succ_cons, inner]322rw listTake.succ_cons323rfl324325theorem listTake.idempotent (A : Set) (xs : List(A)) (n : Nat)326shows listTake{A}(n, listTake{A}(n, xs)) = listTake{A}(n, xs)327proof328have reflexive := LessEqual.reflexive at n with*329exact listTake.take with reflexive330331theorem listDrop.drop (A : Set) (xs : List(A)) (m n : Nat)332shows listDrop{A}(m, listDrop{A}(n, xs)) = listDrop{A}(n + m, xs)333proof334induction xs generalizing n335| List.nil =>336intros n nNat337rw [listDrop.nil, listDrop.nil, listDrop.nil]338rfl339| List.cons(a, tail) using ih =>340intros n nNat341have element : a ∈ A byassumption342have whole : List(A, a :: tail) bytypecheck343have shape := natural.zero_or_successor at n with nNat344cases shape with zero | successor345 . rw [zero, listDrop.zero, add.left_unit]346rfl347 . obtain⟨k, kNat, equal⟩:= successor348have inner := ih with k, kNat349have shift : succ(k) + m = succ(k + m) bysimp [add, add.succ_right]350rw [equal, listDrop.succ_cons, inner, shift, listDrop.succ_cons]351rfl352353theorem listDrop.succ (A : Set) (xs : List(A)) (n : Nat)354shows listDrop{A}(succ(n), xs) = listTail{A}(listDrop{A}(n, xs))355proof356induction xs generalizing n357| List.nil =>358intros n nNat359rw [listDrop.nil, listDrop.nil, listTail.nil]360rfl361| List.cons(a, tail) using ih =>362intros n nNat363have element : a ∈ A byassumption364have whole : List(A, a :: tail) bytypecheck365have shape := natural.zero_or_successor at n with nNat366cases shape with zero | successor367 . rw [zero, listDrop.zero, listDrop.succ_cons, listDrop.zero, listTail.cons]368rfl369 . obtain⟨k, kNat, equal⟩:= successor370have inner := ih with k, kNat371rw [equal, listDrop.succ_cons, listDrop.succ_cons, inner]372rfl373374theorem listDrop.one (A : Set) (xs : List(A))375shows listDrop{A}(1, xs) = listTail{A}(xs)376proof377have step := listDrop.succ at A, xs, 0with*378rw [listDrop.zero] at step379exact step380381theorem listDrop.tail (A : Set) (xs : List(A)) (n : Nat)382shows listDrop{A}(succ(n), xs) = listDrop{A}(n, listTail{A}(xs))383proof384have shape := List.cases with*385cases shape with nil | cons386 . rw [nil, listTail.nil, listDrop.nil, listDrop.nil]387rfl388 . obtain⟨a, element, tail, tailList, equal⟩:= cons389rw [equal, listTail.cons, listDrop.succ_cons]390rfl391392-- Take and drop across a concatenation.393theorem listTake.append_left (A : Set) (xs ys : List(A)) (n : Nat)394requires bound : n ≤ length{A}(xs)395shows listTake{A}(n, append(ys, xs)) = listTake{A}(n, xs)396proof397induction xs generalizing n398| List.nil =>399intros n nNat bound400rw length.nil at bound401have ysList : List(A, ys) bytypecheck402rw append.nil403have shape := natural.zero_or_successor with*404cases shape with zero | successor405 . rw [zero, listTake.zero, listTake.nil]406rfl407 . obtain⟨k, kNat, equal⟩:= successor408rw equal at bound409exfalso410arith411| List.cons(a, tail) using ih =>412intros n nNat bound413have element : a ∈ A byassumption414have whole : List(A, a :: tail) bytypecheck415rw length.cons at bound416have appended := append.closed at A, tail, ys with*417have appendedWhole : List(A, append(ys, a :: tail)) bytypecheck418have shape := natural.zero_or_successor with*419cases shape with zero | successor420 . rw [zero, listTake.zero, listTake.zero]421rfl422 . obtain⟨k, kNat, equal⟩:= successor423rw equal at bound424have smaller : k ≤ length{A}(tail) byarith425have inner := ih with k, kNat, smaller426rw [equal, append.cons, listTake.succ_cons, listTake.succ_cons, inner]427rfl428429theorem listDrop.append_left (A : Set) (xs ys : List(A)) (n : Nat)430requires bound : n ≤ length{A}(xs)431shows listDrop{A}(n, append(ys, xs)) = append(ys, listDrop{A}(n, xs))432proof433induction xs generalizing n434| List.nil =>435intros n nNat bound436rw length.nil at bound437have ysList : List(A, ys) bytypecheck438rw append.nil439have shape := natural.zero_or_successor with*440cases shape with zero | successor441 . rw [zero, listDrop.zero, listDrop.nil, append.nil]442rfl443 . obtain⟨k, kNat, equal⟩:= successor444rw equal at bound445exfalso446arith447| List.cons(a, tail) using ih =>448intros n nNat bound449have element : a ∈ A byassumption450have whole : List(A, a :: tail) bytypecheck451rw length.cons at bound452have appended := append.closed at A, tail, ys with*453have appendedWhole : List(A, append(ys, a :: tail)) bytypecheck454have shape := natural.zero_or_successor with*455cases shape with zero | successor456 . rw [zero, listDrop.zero, listDrop.zero]457rfl458 . obtain⟨k, kNat, equal⟩:= successor459rw equal at bound460have smaller : k ≤ length{A}(tail) byarith461have inner := ih with k, kNat, smaller462rw [equal, append.cons, listDrop.succ_cons, listDrop.succ_cons, inner]463rfl464465theorem listTake.append_right (A : Set) (xs ys : List(A)) (n : Nat)466shows listTake{A}(length{A}(xs) + n, append(ys, xs)) =467 append(listTake{A}(n, ys), xs)468proof469induction xs470| List.nil =>471have taken := listTake.closed at A, ys, n with*472rw [length.nil, add.left_unit]473simp [append]474| List.cons(a, tail) using ih =>475have element : a ∈ A byassumption476have whole : List(A, a :: tail) bytypecheck477have appended := append.closed at A, tail, ys with*478have taken := listTake.closed at A, ys, n with*479have shift : succ(length{A}(tail)) + n = succ(length{A}(tail) + n)480simp [add, add.succ_right]481rw [length.cons, shift, append.cons, listTake.succ_cons, ih, append.cons]482rfl483484theorem listDrop.append_right (A : Set) (xs ys : List(A)) (n : Nat)485shows listDrop{A}(length{A}(xs) + n, append(ys, xs)) = listDrop{A}(n, ys)486proof487induction xs488| List.nil =>489rw [length.nil, add.left_unit]490simp [append]491| List.cons(a, tail) using ih =>492have element : a ∈ A byassumption493have whole : List(A, a :: tail) bytypecheck494have appended := append.closed at A, tail, ys with*495have shift : succ(length{A}(tail)) + n = succ(length{A}(tail) + n)496simp [add, add.succ_right]497rw [length.cons, shift, append.cons, listDrop.succ_cons, ih]498rfl499500theorem listTake.append_self (A : Set) (xs ys : List(A))501shows listTake{A}(length{A}(xs), append(ys, xs)) = xs502proof503have reflexive := LessEqual.reflexive at length{A}(xs) with*504have step := listTake.append_left at A, xs, ys, length{A}(xs) with reflexive505rw [step, listTake.self]506rfl507508theorem listDrop.append_self (A : Set) (xs ys : List(A))509shows listDrop{A}(length{A}(xs), append(ys, xs)) = ys510proof511have step := listDrop.append_right at A, xs, ys, 0with*512rw [add.right_unit, listDrop.zero] at step513exact step514515-- Mapping commutes with take and drop.516theorem listTake.map (A B f : Set) (xs : List(A)) (n : Nat)517requires function : f : A → B518shows listMap{A}(f, listTake{A}(n, xs)) = listTake{B}(n, listMap{A}(f, xs))519proof520induction xs generalizing n521| List.nil =>522intros n nNat523rw [listTake.nil, listMap.nil, listTake.nil]524rfl525| List.cons(a, tail) using ih =>526intros n nNat527have element : a ∈ A byassumption528have whole : List(A, a :: tail) bytypecheck529have image := FunctionBetween.apply_closed with function, element530have mapped : List(B, listMap{A}(f, tail)) byexact listMap.closed with function531have mappedWhole : List(B, f(a) :: listMap{A}(f, tail)) bytypecheck532have shape := natural.zero_or_successor with*533cases shape with zero | successor534 . rw [zero, listTake.zero, listMap.nil, listMap.cons, listTake.zero]535rfl536 . obtain⟨k, kNat, equal⟩:= successor537have inner := ih with k, kNat538have taken := listTake.closed at A, tail, k with*539rw [equal, listTake.succ_cons, listMap.cons, inner, listMap.cons]540rw listTake.succ_cons541rfl542543theorem listDrop.map (A B f : Set) (xs : List(A)) (n : Nat)544requires function : f : A → B545shows listMap{A}(f, listDrop{A}(n, xs)) = listDrop{B}(n, listMap{A}(f, xs))546proof547induction xs generalizing n548| List.nil =>549intros n nNat550rw [listDrop.nil, listMap.nil, listDrop.nil]551rfl552| List.cons(a, tail) using ih =>553intros n nNat554have element : a ∈ A byassumption555have whole : List(A, a :: tail) bytypecheck556have image := FunctionBetween.apply_closed with function, element557have mapped : List(B, listMap{A}(f, tail)) byexact listMap.closed with function558have mappedWhole : List(B, f(a) :: listMap{A}(f, tail)) bytypecheck559have shape := natural.zero_or_successor with*560cases shape with zero | successor561 . rw [zero, listDrop.zero, listMap.cons, listDrop.zero]562rfl563 . obtain⟨k, kNat, equal⟩:= successor564have inner := ih with k, kNat565rw [equal, listDrop.succ_cons, inner, listMap.cons, listDrop.succ_cons]566rfl567568-- Take and drop of a constant list.569theorem listTake.replicate (A x : Set) (m k : Nat)570requires element : x ∈ A571shows listTake{A}(m, listReplicate(k + m, x)) = listReplicate(m, x)572proof573induction m574| zero =>575have list := listReplicate.closed at A, x, k +0with element576rw [listTake.zero, listReplicate.zero]577rfl578| succ(j) using ih =>579have list := listReplicate.closed at A, x, k + j with element580rw [add.succ_right, listReplicate.succ, listTake.succ_cons, ih]581rw listReplicate.succ582rfl583584theorem listDrop.replicate (A x : Set) (m k : Nat)585requires element : x ∈ A586shows listDrop{A}(m, listReplicate(k + m, x)) = listReplicate(k, x)587proof588induction m589| zero =>590have list := listReplicate.closed at A, x, k with element591rw [add.right_unit, listDrop.zero]592rfl593| succ(j) using ih =>594have list := listReplicate.closed at A, x, k + j with element595rw [add.succ_right, listReplicate.succ, listDrop.succ_cons, ih]596rfl597598-- Supports of prefixes and suffixes.599theorem listTake.support_subset (A : Set) (xs : List(A)) (n : Nat)600shows listSupport{A}(listTake{A}(n, xs)) ⊆ listSupport{A}(xs)601proof602havesplit:= listTake.append_drop at A, xs, n with*603have taken := listTake.closed at A, xs, n with*604have dropped := listDrop.closed at A, xs, n with*605intros y hy606have member := listSupport.mem_append_left at A, y, listTake{A}(n, xs), listDrop{A}(n, xs) with hy607 rwa splitat member608609theorem listDrop.support_subset (A : Set) (xs : List(A)) (n : Nat)610shows listSupport{A}(listDrop{A}(n, xs)) ⊆ listSupport{A}(xs)611proof612havesplit:= listTake.append_drop at A, xs, n with*613have taken := listTake.closed at A, xs, n with*614have dropped := listDrop.closed at A, xs, n with*615intros y hy616have member := listSupport.mem_append_right at A, y, listTake{A}(n, xs), listDrop{A}(n, xs) with hy617 rwa splitat member618619theorem listSupport.take_union_drop (A : Set) (xs : List(A)) (n : Nat)620shows listSupport{A}(xs) =621 listSupport{A}(listTake{A}(n, xs)) ∪ listSupport{A}(listDrop{A}(n, xs))622proof623havesplit:= listTake.append_drop at A, xs, n with*624have taken := listTake.closed at A, xs, n with*625have dropped := listDrop.closed at A, xs, n with*626have union := listSupport.append at A, listDrop{A}(n, xs), listTake{A}(n, xs) with*627 rwa splitat union628629-- Indexing into prefixes and suffixes.630theorem listTake.coefficient (A z : Set) (xs : List(A)) (n k : Nat)631requires bound : k < n632shows listCoefficient{A}(z, listTake{A}(n, xs), k) = listCoefficient{A}(z, xs, k)633proof634induction xs generalizing n k635| List.nil =>636intros n k nNat kNat bound637rw listTake.nil638rfl639| List.cons(a, tail) using ih =>640intros n k nNat kNat bound641have element : a ∈ A byassumption642have whole : List(A, a :: tail) bytypecheck643have shapeN := natural.zero_or_successor at n with nNat644cases shapeN with zeroN | successorN645 . rw zeroN at bound646exfalso647arith648 . obtain⟨j, jNat, equalN⟩:= successorN649have taken := listTake.closed at A, tail, j with*650rw [equalN, listTake.succ_cons]651have shapeK := natural.zero_or_successor at k with kNat652cases shapeK with zeroK | successorK653 . rw [zeroK, listCoefficient.zero, listCoefficient.zero]654rfl655 . obtain⟨r, rNat, equalK⟩:= successorK656rw [equalN, equalK] at bound657have smaller : r < j byarith658have inner := ih with j, r, jNat, rNat, smaller659rw [equalK, listCoefficient.succ, listCoefficient.succ]660exact inner661662theorem listDrop.coefficient (A z : Set) (xs : List(A)) (n k : Nat)663shows listCoefficient{A}(z, listDrop{A}(n, xs), k) = listCoefficient{A}(z, xs, n + k)664proof665induction xs generalizing n666| List.nil =>667intros n nNat668rw [listDrop.nil, listCoefficient.nil, listCoefficient.nil]669rfl670| List.cons(a, tail) using ih =>671intros n nNat672have element : a ∈ A byassumption673have whole : List(A, a :: tail) bytypecheck674have shape := natural.zero_or_successor at n with nNat675cases shape with zero | successor676 . rw [zero, listDrop.zero, add.left_unit]677rfl678 . obtain⟨j, jNat, equal⟩:= successor679have inner := ih with j, jNat680have shift : succ(j) + k = succ(j + k) bysimp [add, add.succ_right]681rw [equal, listDrop.succ_cons, inner, shift, listCoefficient.succ]682rfl683684theorem listCoefficient.head (A z : Set) (xs : List(A))685shows listCoefficient{A}(z, xs, 0) = listHeadOr{A}(z, xs)686proof687simp [listCoefficient]688689theorem listCoefficient.tail (A z : Set) (xs : List(A)) (n : Nat)690shows listCoefficient{A}(z, listTail{A}(xs), n) = listCoefficient{A}(z, xs, succ(n))691proof692simp [listCoefficient]693