Fixpoint pmap_lookup' (ts : pmap Type) (p : positive) : option Type :=
match p with
| xH => pmap_here ts
| xI p => pmap_lookup' (pmap_right ts) p
| xO p => pmap_lookup' (pmap_left ts) p
end.
Record OneOf (ts : pmap Type) : Type := mkOneOf
{ index : positive
; value : match pmap_lookup' ts index with
| None => Empty_set
| Some T => T
end
}.
Definition Into {ts} {T : Type} (n : positive) (pf : pmap_lookup' ts n = Some T)
: T -> OneOf ts :=
match pf in _ = X return match X with
| Some T => T
| None => Empty_set
end -> OneOf ts
with
| eq_refl => @mkOneOf ts n
end.
Fixpoint asNth' {ts : pmap Type} (p p' : positive)
: match pmap_lookup' ts p' with
| None => Empty_set
| Some T => T
end -> option (match pmap_lookup' ts p with
| None => Empty_set
| Some T => T
end) :=
match p as p , p' as p'
return match pmap_lookup' ts p' with
| None => Empty_set
| Some T => T
end -> option (match pmap_lookup' ts p with
| None => Empty_set
| Some T => T
end)
with
| xH , xH => Some
| xI p , xI p' => asNth' p p'
| xO p , xO p' => asNth' p p'
| _ , _ => fun _ => None
end.
Definition asNth {ts : pmap Type} (p : positive) (oe : OneOf ts)
: option (match pmap_lookup' ts p with
| None => Empty_set
| Some T => T
end) :=
@asNth' ts p oe.(index ts) oe.(value ts).
Definition OutOf {ts} {T : Type} (n : positive)
(pf : pmap_lookup' ts n = Some T)
: OneOf ts -> option T :=
match pf in _ = X return OneOf ts -> option match X with
| None => Empty_set:Type
| Some T => T
end
with
| eq_refl => @asNth ts n
end.
Proof using.
unfold OutOf, Into.
intros.
repeat rewrite (eq_Arr_eq pf).
repeat rewrite (eq_Const_eq pf).
repeat rewrite (eq_Const_eq (eq_sym pf)).
unfold asNth. simpl.
rewrite asNth'_get_lookup.
{ generalize dependent (pmap_lookup' ts p).
intros. subst. reflexivity. }
Qed.

Theorem asNth_eq
: forall ts p oe v,
@asNth ts p oe = Some v ->
oe = {| index := p ; value := v |}.