Instance list_PCM (P : Ghost) : Ghost := { valid a := True; Join_G := list_join }.

(* Specifications: *)
(* up *)
Lemma replace_nth_length : forall {A} n l (a : A),
length (replace_nth n l a) = length l.
(* up *)
Lemma replace_nth_app : forall {A} n l1 l2 (a : A),
replace_nth n (l1 ++ l2) a = if lt_dec n (length l1) then replace_nth n l1 a ++ l2
else l1 ++ replace_nth (n - length l1) l2 a.
Lemma list_join_app : forall {P : Ghost} l1 l2 m1 m2 n1 n2,
length l1 = length m1 -> length l1 = length n1 ->
list_join l1 m1 n1 -> list_join l2 m2 n2 ->
list_join (l1 ++ l2) (m1 ++ m2) (n1 ++ n2).
Lemma list_join_None : forall {P : Ghost} n l, (n <= length l)%nat ->
list_join (repeat None n) l l.
Lemma list_join_over : forall {P : Ghost} l l1 l2 l1', (length l <= length l1)%nat ->
list_join l l1 l1' -> list_join l (l1 ++ l2) (l1' ++ l2).
Lemma singleton_length : forall {A} n (a : A), length (list_singleton n a) = S n.
Lemma list_join_singleton : forall {P : Ghost} n a c l
(Hn : (n < length l)%nat) (Hjoin: join (Some a) (nth n l None) (Some c)),
list_join (list_singleton n a) l (replace_nth n l (Some c)).
(* up *)
Lemma replace_nth_same : forall {A} n l (d : A), replace_nth n l (nth n l d) = l.
Lemma nth_replace_nth : forall {A} n l a (d : A), (n < length l)%nat ->
nth n (replace_nth n l a) d = a.
Lemma nth_replace_nth' : forall {A} n m l a (d : A), m <> n ->
nth m (replace_nth n l a) d = nth m l d.
Lemma Znth_replace_nth : forall {A} {d : Inhabitant A} n l (a : A), (n < length l)%nat ->
Znth (Z.of_nat n) (replace_nth n l a) = a.
Lemma Znth_replace_nth' : forall {A} {d : Inhabitant A} n m l (a : A), m <> Z.of_nat n ->
Znth m (replace_nth n l a) = Znth m l.
Lemma ghost_list_nth : forall {P : Ghost} g n l (a : G) (Ha : nth n l None = Some a),
ghost_list g l = ghost_list g (list_singleton n a) * ghost_list g (replace_nth n l None).
Lemma list_join_length : forall {P : Ghost} l1 l2 l3, list_join l1 l2 l3 ->
(length l1 <= length l3)%nat.
Lemma list_join_filler : forall {P : Ghost} l1 l2 l3 n, list_join l1 l2 l3 ->
(n <= length l3 - length l1)%nat -> list_join (l1 ++ repeat None n) l2 l3.
Lemma list_join_nth : forall {P : Ghost} l1 l2 l3 n, list_join l1 l2 l3 ->
join (nth n l1 None) (nth n l2 None) (nth n l3 None).
Lemma list_join_max : forall {P : Ghost} l1 l2 l3, list_join l1 l2 l3 ->
length l3 = Max.max (length l1) (length l2).
Lemma list_join_nth_error : forall {P : Ghost} l1 l2 l3 n, list_join l1 l2 l3 ->
join (nth_error l1 n) (nth_error l2 n) (nth_error l3 n).
Lemma list_join_alt : forall {P : Ghost} l1 l2 l3,
list_join l1 l2 l3 <-> forall n, join (nth_error l1 n) (nth_error l2 n) (nth_error l3 n).
Lemma nth_error_replace_nth : forall {A} n l (a : A), (n < length l)%nat ->
nth_error (replace_nth n l a) n = Some a.
Lemma nth_error_replace_nth' : forall {A} n m l (a : A), m <> n ->
nth_error (replace_nth n l a) m = nth_error l m.