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.

(* Specifications: *)
Lemma repeat_op_step: forall {T: Type} (i: Z) (start: T) (op: T -> T),
0 <= i ->
repeat_op (i + 1) start op = op (repeat_op i start op).