Definition gname := nat.
Definition own {RA: Ghost} (n: gname) (a: G) (pp: preds) :=
EX v : _, Own (singleton n (existT _ RA (exist _ a v), pp)).
Definition list_set {A} (m : list (option A)) k v : list (option A) :=
firstn k m ++ repeat None (k - length m) ++ Some v :: skipn (S k) m.

(* Specifications: *)
Lemma singleton_join_gen: forall k a c (m: ghost)
(Hjoin: join (Some a) (nth k m None) (Some c)),
join (singleton k a) m (list_set m k c).
Lemma map_repeat : forall {A B} (f : A -> B) x n, map f (repeat x n) = repeat (f x) n.
Lemma ghost_fmap_singleton: forall f g k v, ghost_fmap f g (singleton k v) =
singleton k (match v with (a, b) => (a, preds_fmap f g b) end).
Lemma ghost_fmap_singleton_inv : forall f g a k v,
ghost_fmap f g a = singleton k v ->
exists v', a = singleton k v' /\ v = let (a, b) := v' in (a, preds_fmap f g b).
Lemma ghost_alloc: forall {RA: Ghost} a pp, ghost.valid a ->
emp |-- bupd (EX g: gname, own g a pp).
Lemma singleton_join: forall a b c k,
join (singleton k a) (singleton k b) (singleton k c) <-> join a b c.
Lemma singleton_join_inv: forall k a b c,
join (singleton k a) (singleton k b) c -> exists c', join a b c' /\ c = singleton k c'.
Lemma ghost_valid_2: forall {RA: Ghost} g a1 a2 pp,
own g a1 pp * own g a2 pp |-- !!ghost.valid_2 a1 a2.
Lemma ghost_op: forall {RA: Ghost} g (a1 a2 a3: G) pp, join a1 a2 a3 ->
own g a3 pp = own g a1 pp * own g a2 pp.
Lemma ghost_valid: forall {RA: Ghost} g a pp,
own g a pp |-- !!ghost.valid a.
Lemma singleton_join_inv_gen: forall k a (b c: ghost),
join (singleton k a) b c ->
join (Some a) (nth k b None) (nth k c None) /\
exists c', nth k c None = Some c' /\ c = list_set b k c'.
Lemma ghost_update_ND: forall {RA: Ghost} g (a: G) B pp,
fp_update_ND a B -> own g a pp |-- bupd (EX b : _, !!(B b) && own g b pp).
Lemma ghost_update: forall {RA: Ghost} g (a b: G) pp,
fp_update a b -> own g a pp |-- bupd (own g b pp).
Lemma ghost_dealloc: forall {RA: Ghost} g a pp,
own g a pp |-- bupd emp.
Lemma list_set_same : forall {A} n l (a : A), nth n l None = Some a ->
list_set l n a = l.