Section Nth'.
(* In this implementation of [nth_error], instead of encoding an option to the output tape, we use the finite parameter to indicate whether the result is [Some] or [None]. The advantage is that the client doesn't have to add the option to its alphabet. *)
Variable (sig sigX : finType) (X : Type) (cX : codable sigX X).
(* Hypothesis (defX: inhabitedC sigX). *)
Variable (retr1 : Retract (sigList sigX) sig) (retr2 : Retract sigNat sig).
Local Instance retr_X_list' : Retract sigX sig := ComposeRetract retr1 (Retract_sigList_X _).
(* Check _ : codable sig (list X). *)
(* Check _ : codable sig nat. *)
Definition Nth'_Step_size {sigX X : Type} {cX : codable sigX X} (n : nat) (l : list X) : Vector.t (nat -> nat) 3 :=
match n, l with
| S n', x :: l' =>
[| CaseList_size0 x; S; CaseList_size1 x >> Reset_size x|]
| 0, x :: x' =>
[|fun s0 => CaseList_size0 x s0; id; fun s2 => CaseList_size1 x s2|]
| 0, nil => [|id; id; id|]
| S n', nil => [|id; fun s1 => S s1; id|]
end.
Definition Nth'_Step : pTM sig^+ (option bool) 3 :=
If (LiftTapes (ChangeAlphabet CaseNat _) [|Fin1|])
(If (LiftTapes (ChangeAlphabet (CaseList sigX) _) [|Fin0; Fin2|]) (* n = S n' *)
(Return (LiftTapes (Reset _) [|Fin2|]) None) (* l = x :: l'; continue *)
(Return Nop (Some false))) (* l = nil; return false *)
(Relabel (LiftTapes (ChangeAlphabet (CaseList sigX) _) [|Fin0; Fin2|]) Some) (* n = 0 *)
.
Definition Nth'_Step_steps {sigX X : Type} {cX : codable sigX X} (l : list X) (n : nat) :=
match n, l with
| S n', x :: l' =>
2 + CaseNat_steps + CaseList_steps_cons x + Reset_steps x
| S n', nil =>
2 + CaseNat_steps + CaseList_steps_nil
| O, x :: l' =>
1 + CaseNat_steps + CaseList_steps_cons x
| O, nil =>
1 + CaseNat_steps + CaseList_steps_nil
end.
Definition Nth'_Step_steps_CaseList (xs : list X) :=
match xs with
| x :: xs' => 1 + CaseList_steps_cons x + Reset_steps x
| nil => 1 + CaseList_steps_nil
end.
Fixpoint Nth'_Loop_size {sigX X : Type} {cX : codable sigX X} (n : nat) (l : list X) {struct n} : Vector.t (nat -> nat) 3 :=
match n, l with
| S n', x :: l' => Nth'_Step_size n l >>> Nth'_Loop_size n' l'
| _, _ => Nth'_Step_size n l
end.
Definition Nth'_Loop := While Nth'_Step.
Fixpoint Nth'_Loop_steps {sigX X : Type} {cX : codable sigX X} (l : list X) (n : nat) { struct l } :=
match n, l with
| S n', x :: l'  => S (Nth'_Step_steps l n) + Nth'_Loop_steps l' n' (* continue *)
| S n', nil => Nth'_Step_steps l n (* return *)
| O, x :: l' => Nth'_Step_steps l n (* return *)
| O, nil => Nth'_Step_steps l n (* only [CaseNat] and [If] *)
end.

Lemma Nth'_Loop_SpecT_size (xs:list X) n (ss : Vector.t nat 3) :
TripleT
≃≃([],withSpace ([|Contains _ xs; Contains _ n; Void|]) ss)
(Nth'_Loop_steps xs n) Nth'_Loop
(fun yout =>
≃≃([yout = match nth_error xs n with None => false | _ => true end],
withSpace match nth_error xs n with
| Some x => [|Contains _ (skipn (S n) xs); Contains _ (n - (S (length xs))); Contains _ x|]
| None  => [|Contains _ (skipn (S n) xs); Contains _ (n - (S (length xs))); Void|]
end
(appSize (Nth'_Loop_size n xs) ss))).