Require Export List. Export ListNotations.
Local Open Scope Z_scope.
Fixpoint repeat_op_nat{T: Type}(n: nat)(start: T)(op: T -> T): T := match n with
| O => start
| S m => op (repeat_op_nat m start op)
end.
Definition repeat_op{T: Type}(n: Z)(start: T)(op: T -> T): T := repeat_op_nat (Z.to_nat n) start op.
Fixpoint repeat_op_table_nat{T: Type}(n: nat)(start: T)(op: T -> T): list T := match n with
| O => []
| S m => (repeat_op_table_nat m start op) ++ [repeat_op_nat m start op]
end.
Definition repeat_op_table{T: Type}(n: Z)(start: T)(op: T -> T): list T :=
repeat_op_table_nat (Z.to_nat n) start op.
Fixpoint fill_list_nat{T: Type}(n: nat)(f: nat -> T): list T := match n with
| O => []
| S m => (fill_list_nat m f) ++ [f m]
end.
Definition fill_list{T: Type}(n: Z)(f: Z -> T): list T :=
fill_list_nat (Z.to_nat n) (fun i => f (Z.of_nat i)).

Lemma fill_list_step: forall {T: Type} (n: Z) (f: Z -> T),
0 <= n ->
fill_list (n + 1) f = fill_list n f ++ [f n].