diff --git a/prelude/base.v b/prelude/base.v
index 89857cb93d8f8463f8406664e746088b4c335ed5..497e040cf16b37389ac249afc901eb04e2a214c4 100644
--- a/prelude/base.v
+++ b/prelude/base.v
@@ -767,6 +767,15 @@ Infix "=.>*" := (Forall2 bool_le) (at level 70).
 Instance: PartialOrder bool_le.
 Proof. repeat split; repeat intros [|]; compute; tauto. Qed.
 
+Lemma andb_True b1 b2 : b1 && b2 ↔ b1 ∧ b2.
+Proof. destruct b1, b2; simpl; tauto. Qed.
+Lemma orb_True b1 b2 : b1 || b2 ↔ b1 ∨ b2.
+Proof. destruct b1, b2; simpl; tauto. Qed.
+Lemma negb_True b : negb b ↔ ¬b.
+Proof. destruct b; simpl; tauto. Qed.
+Lemma Is_true_false (b : bool) : b = false → ¬b.
+Proof. now intros -> ?. Qed.
+
 (** * Miscellaneous *)
 Class Half A := half: A → A.
 Notation "½" := half : C_scope.
diff --git a/prelude/pmap.v b/prelude/pmap.v
index f11ab53d006e6e8a7d80fdd3942fa6be62333ed9..17c9d479ee8bd3d947dd07af6fdecde2fa8373f2 100644
--- a/prelude/pmap.v
+++ b/prelude/pmap.v
@@ -21,7 +21,7 @@ be represented as a binary tree of an arbitrary size that contains [None] at
 all nodes. *)
 Inductive Pmap_raw (A : Type) : Type :=
   | PLeaf: Pmap_raw A
-  | PNode: Pmap_raw A → option A → Pmap_raw A → Pmap_raw A.
+  | PNode: option A → Pmap_raw A → Pmap_raw A → Pmap_raw A.
 Arguments PLeaf {_}.
 Arguments PNode {_} _ _ _.
 
@@ -29,234 +29,151 @@ Instance Pmap_raw_eq_dec `{∀ x y : A, Decision (x = y)} (x y : Pmap_raw A) :
   Decision (x = y).
 Proof. solve_decision. Defined.
 
-(** The following decidable predicate describes non empty trees. *)
-Inductive Pmap_ne {A} : Pmap_raw A → Prop :=
-  | Pmap_ne_val l x r : Pmap_ne (PNode l (Some x) r)
-  | Pmap_ne_l l r : Pmap_ne l → Pmap_ne (PNode l None r)
-  | Pmap_ne_r l r : Pmap_ne r → Pmap_ne (PNode l None r).
-Local Hint Constructors Pmap_ne.
-
-Instance Pmap_ne_dec {A} : ∀ t : Pmap_raw A, Decision (Pmap_ne t).
-Proof.
- refine (
-  fix go t :=
-  match t return Decision (Pmap_ne t) with
-  | PLeaf => right _
-  | PNode _ (Some x) _ => left _
-  | PNode l Node r => cast_if_or (go l) (go r)
-  end); clear go; abstract first [constructor; by auto|by inversion 1].
-Defined.
-
-(** The following predicate describes well well formed trees. A tree is well
-formed if it is empty or if all nodes at the bottom contain a value. *)
-Inductive Pmap_wf {A} : Pmap_raw A → Prop :=
-  | Pmap_wf_leaf : Pmap_wf PLeaf
-  | Pmap_wf_node l x r : Pmap_wf l → Pmap_wf r → Pmap_wf (PNode l (Some x) r)
-  | Pmap_wf_empty l r :
-     Pmap_wf l → Pmap_wf r → (Pmap_ne l ∨ Pmap_ne r) → Pmap_wf (PNode l None r).
-Local Hint Constructors Pmap_wf.
-
-Instance Pmap_wf_dec {A} : ∀ t : Pmap_raw A, Decision (Pmap_wf t).
-Proof.
- refine (
-  fix go t :=
-  match t return Decision (Pmap_wf t) with
-  | PLeaf => left _
-  | PNode l (Some x) r => cast_if_and (go l) (go r)
-  | PNode l Node r =>
-     cast_if_and3 (decide (Pmap_ne l ∨ Pmap_ne r)) (go l) (go r)
-  end); clear go; abstract first [constructor; by auto|by inversion 1].
-Defined.
-
-(** Now we restrict the data type of trees to those that are well formed and
-thereby obtain a data type that ensures canonicity. *)
-Inductive Pmap (A : Type) : Type := PMap {
-  pmap_car : Pmap_raw A;
-  pmap_bool_prf : bool_decide (Pmap_wf pmap_car)
-}.
-Arguments PMap {_} _ _.
-Arguments pmap_car {_} _.
-Arguments pmap_bool_prf {_} _.
-Definition PMap' {A} (t : Pmap_raw A) (p : Pmap_wf t) : Pmap A :=
-  PMap t (bool_decide_pack _ p).
-Definition pmap_prf {A} (m : Pmap A) : Pmap_wf (pmap_car m) :=
-  bool_decide_unpack _ (pmap_bool_prf m).
-Lemma Pmap_eq {A} (m1 m2 : Pmap A) : m1 = m2 ↔ pmap_car m1 = pmap_car m2.
-Proof.
-  split; [by intros ->|intros]; destruct m1 as [t1 ?], m2 as [t2 ?].
-  simplify_equality'; f_equal; apply proof_irrel.
-Qed.
-
-(** * Operations on the data structure *)
-Global Instance Pmap_eq_dec `{∀ x y : A, Decision (x = y)}
-    (m1 m2 : Pmap A) : Decision (m1 = m2) :=
-  match Pmap_raw_eq_dec (pmap_car m1) (pmap_car m2) with
-  | left H => left (proj2 (Pmap_eq m1 m2) H)
-  | right H => right (H ∘ proj1 (Pmap_eq m1 m2))
+Fixpoint Pmap_wf {A} (t : Pmap_raw A) : bool :=
+  match t with
+  | PLeaf => true
+  | PNode None PLeaf PLeaf => false
+  | PNode _ l r => Pmap_wf l && Pmap_wf r
   end.
-Instance Pempty_raw {A} : Empty (Pmap_raw A) := PLeaf.
-Global Instance Pempty {A} : Empty (Pmap A) := PMap' ∅ Pmap_wf_leaf.
+Arguments Pmap_wf _ !_ / : simpl nomatch.
+Lemma Pmap_wf_l {A} o (l r : Pmap_raw A) : Pmap_wf (PNode o l r) → Pmap_wf l.
+Proof. destruct o, l, r; simpl; rewrite ?andb_True; tauto. Qed.
+Lemma Pmap_wf_r {A} o (l r : Pmap_raw A) : Pmap_wf (PNode o l r) → Pmap_wf r.
+Proof. destruct o, l, r; simpl; rewrite ?andb_True; tauto. Qed.
+Local Hint Immediate Pmap_wf_l Pmap_wf_r.
+Definition PNode' {A} (o : option A) (l r : Pmap_raw A) :=
+  match l, o, r with PLeaf, None, PLeaf => PLeaf | _, _, _ => PNode o l r end.
+Arguments PNode' _ _ _ _ : simpl never.
+Lemma PNode_wf {A} o (l r : Pmap_raw A) :
+  Pmap_wf l → Pmap_wf r → Pmap_wf (PNode' o l r).
+Proof. destruct o, l, r; simpl; auto. Qed.
+Local Hint Resolve PNode_wf.
 
+(** Operations *)
+Instance Pempty_raw {A} : Empty (Pmap_raw A) := PLeaf.
 Instance Plookup_raw {A} : Lookup positive A (Pmap_raw A) :=
   fix go (i : positive) (t : Pmap_raw A) {struct t} : option A :=
+  let _ : Lookup _ _ _ := @go in
   match t with
   | PLeaf => None
-  | PNode l o r =>
+  | PNode o l r => match i with 1 => o | i~0 => l !! i | i~1 => r !! i end
+  end.
+Local Arguments lookup _ _ _ _ _ !_ / : simpl nomatch.
+Fixpoint Psingleton_raw {A} (i : positive) (x : A) : Pmap_raw A :=
+  match i with
+  | 1 => PNode (Some x) PLeaf PLeaf
+  | i~0 => PNode None (Psingleton_raw i x) PLeaf
+  | i~1 => PNode None PLeaf (Psingleton_raw i x)
+  end.
+Fixpoint Ppartial_alter_raw {A} (f : option A → option A)
+    (i : positive) (t : Pmap_raw A) {struct t} : Pmap_raw A :=
+  match t with
+  | PLeaf => match f None with None => PLeaf | Some x => Psingleton_raw i x end
+  | PNode o l r =>
      match i with
-     | 1 => o | i~0 => @lookup _ _ _ go i l | i~1 => @lookup _ _ _ go i r
+     | 1 => PNode' (f o) l r
+     | i~0 => PNode' o (Ppartial_alter_raw f i l) r
+     | i~1 => PNode' o l (Ppartial_alter_raw f i r)
      end
   end.
-Instance Plookup {A} : Lookup positive A (Pmap A) := λ i m, pmap_car m !! i.
-
-Lemma Plookup_empty {A} i : (∅ : Pmap_raw A) !! i = None.
-Proof. by destruct i. Qed.
+Fixpoint Pfmap_raw {A B} (f : A → B) (t : Pmap_raw A) : Pmap_raw B :=
+  match t with
+  | PLeaf => PLeaf
+  | PNode o l r => PNode (f <$> o) (Pfmap_raw f l) (Pfmap_raw f r)
+  end.
+Fixpoint Pto_list_raw {A} (j : positive) (t : Pmap_raw A)
+    (acc : list (positive * A)) : list (positive * A) :=
+  match t with
+  | PLeaf => acc
+  | PNode o l r => default [] o (λ x, [(Preverse j, x)]) ++
+     Pto_list_raw (j~0) l (Pto_list_raw (j~1) r acc)
+  end%list.
+Fixpoint Pomap_raw {A B} (f : A → option B) (t : Pmap_raw A) : Pmap_raw B :=
+  match t with
+  | PLeaf => PLeaf
+  | PNode o l r => PNode' (o ≫= f) (Pomap_raw f l) (Pomap_raw f r)
+  end.
+Fixpoint Pmerge_raw {A B C} (f : option A → option B → option C)
+    (t1 : Pmap_raw A) (t2 : Pmap_raw B) : Pmap_raw C :=
+  match t1, t2 with
+  | PLeaf, t2 => Pomap_raw (f None ∘ Some) t2
+  | t1, PLeaf => Pomap_raw (flip f None ∘ Some) t1
+  | PNode o1 l1 r1, PNode o2 l2 r2 =>
+      PNode' (f o1 o2) (Pmerge_raw f l1 l2) (Pmerge_raw f r1 r2)
+  end.
 
-Lemma Pmap_ne_lookup {A} (t : Pmap_raw A) : Pmap_ne t → ∃ i x, t !! i = Some x.
+(** Proofs *)
+Lemma Pmap_wf_canon {A} (t : Pmap_raw A) :
+  (∀ i, t !! i = None) → Pmap_wf t → t = PLeaf.
 Proof.
-  induction 1 as [? x ?| l r ? IHl | l r ? IHr].
-  * intros. by exists 1, x.
-  * destruct IHl as [i [x ?]]. by exists (i~0), x.
-  * destruct IHr as [i [x ?]]. by exists (i~1), x.
+  induction t as [|o l IHl r IHr]; intros Ht ?; auto.
+  assert (o = None) as -> by (apply (Ht 1)).
+  assert (l = PLeaf) as -> by (apply IHl; try apply (λ i, Ht (i~0)); eauto).
+  by assert (r = PLeaf) as -> by (apply IHr; try apply (λ i, Ht (i~1)); eauto).
 Qed.
-
-Lemma Pmap_wf_eq_get {A} (t1 t2 : Pmap_raw A) :
-  Pmap_wf t1 → Pmap_wf t2 → (∀ i, t1 !! i = t2 !! i) → t1 = t2.
+Lemma Pmap_wf_eq {A} (t1 t2 : Pmap_raw A) :
+  (∀ i, t1 !! i = t2 !! i) → Pmap_wf t1 → Pmap_wf t2 → t1 = t2.
 Proof.
-  intros t1wf. revert t2.
-  induction t1wf as [| ? x ? ? IHl ? IHr | l r ? IHl ? IHr Hne1].
-  * destruct 1 as [| | ???? [?|?]]; intros Hget.
-    + done.
-    + discriminate (Hget 1).
-    + destruct (Pmap_ne_lookup l) as [i [??]]; trivial.
-      specialize (Hget (i~0)). simpl in *. congruence.
-    + destruct (Pmap_ne_lookup r) as [i [??]]; trivial.
-      specialize (Hget (i~1)). simpl in *. congruence.
-  * destruct 1; intros Hget.
-    + discriminate (Hget xH).
-    + f_equal.
-      - apply IHl; trivial. intros i. apply (Hget (i~0)).
-      - apply (Hget 1).
-      - apply IHr; trivial. intros i. apply (Hget (i~1)).
-    + specialize (Hget 1). simpl in *. congruence.
-  * destruct 1; intros Hget.
-    + destruct Hne1.
-      - destruct (Pmap_ne_lookup l) as [i [??]]; trivial.
-        specialize (Hget (i~0)); simpl in *. congruence.
-      - destruct (Pmap_ne_lookup r) as [i [??]]; trivial.
-        specialize (Hget (i~1)); simpl in *. congruence.
-    + specialize (Hget 1); simpl in *. congruence.
-    + f_equal.
-      - apply IHl; trivial. intros i. apply (Hget (i~0)).
-      - apply IHr; trivial. intros i. apply (Hget (i~1)).
+  revert t2.
+  induction t1 as [|o1 l1 IHl r1 IHr]; intros [|o2 l2 r2] Ht ??; simpl; auto.
+  * discriminate (Pmap_wf_canon (PNode o2 l2 r2)); eauto.
+  * discriminate (Pmap_wf_canon (PNode o1 l1 r1)); eauto.
+  * f_equal; [apply (Ht 1)| |].
+    + apply IHl; try apply (λ x, Ht (x~0)); eauto.
+    + apply IHr; try apply (λ x, Ht (x~1)); eauto.
 Qed.
+Lemma PNode_lookup {A} o (l r : Pmap_raw A) i :
+  PNode' o l r !! i = PNode o l r !! i.
+Proof. by destruct i, o, l, r. Qed.
 
-Fixpoint Psingleton_raw {A} (i : positive) (x : A) : Pmap_raw A :=
-  match i with
-  | 1 => PNode PLeaf (Some x) PLeaf
-  | i~0 => PNode (Psingleton_raw i x) None PLeaf
-  | i~1 => PNode PLeaf None (Psingleton_raw i x)
-  end.
-Lemma Psingleton_ne {A} i (x : A) : Pmap_ne (Psingleton_raw i x).
-Proof. induction i; simpl; intuition. Qed.
-Local Hint Resolve Psingleton_ne.
 Lemma Psingleton_wf {A} i (x : A) : Pmap_wf (Psingleton_raw i x).
-Proof. induction i; simpl; intuition. Qed.
-Local Hint Resolve Psingleton_wf.
+Proof. induction i as [[]|[]|]; simpl; rewrite ?andb_true_r; auto. Qed.
+Lemma Ppartial_alter_wf {A} f i (t : Pmap_raw A) :
+  Pmap_wf t → Pmap_wf (Ppartial_alter_raw f i t).
+Proof.
+  revert i; induction t as [|o l IHl r IHr]; intros i ?; simpl.
+  * destruct (f None); auto using Psingleton_wf.
+  * destruct i; simpl; eauto.
+Qed.
+Lemma Pfmap_wf {A B} (f : A → B) t : Pmap_wf t → Pmap_wf (Pfmap_raw f t).
+Proof.
+  induction t as [|[x|] [] ? [] ?]; simpl in *; rewrite ?andb_True; intuition.
+Qed.
+Lemma Pomap_wf {A B} (f : A → option B) t : Pmap_wf t → Pmap_wf (Pomap_raw f t).
+Proof. induction t; simpl; eauto. Qed.
+Lemma Pmerge_wf {A B C} (f : option A → option B → option C) t1 t2 :
+  Pmap_wf t1 → Pmap_wf t2 → Pmap_wf (Pmerge_raw f t1 t2).
+Proof. revert t2. induction t1; intros []; simpl; eauto using Pomap_wf. Qed.
+
+Lemma Plookup_empty {A} i : (∅ : Pmap_raw A) !! i = None.
+Proof. by destruct i. Qed.
 Lemma Plookup_singleton {A} i (x : A) : Psingleton_raw i x !! i = Some x.
 Proof. by induction i. Qed.
 Lemma Plookup_singleton_ne {A} i j (x : A) :
   i ≠ j → Psingleton_raw i x !! j = None.
-Proof. revert j. induction i; intros [?|?|]; simpl; auto. congruence. Qed.
-
-Definition PNode_canon {A} (l : Pmap_raw A) (o : option A) (r : Pmap_raw A) :=
-  match l, o, r with PLeaf, None, PLeaf => PLeaf | _, _, _ => PNode l o r end.
-Lemma PNode_canon_wf {A} (l : Pmap_raw A) (o : option A) (r : Pmap_raw A) :
-  Pmap_wf l → Pmap_wf r → Pmap_wf (PNode_canon l o r).
-Proof. intros H1 H2. destruct H1, o, H2; simpl; intuition. Qed.
-Local Hint Resolve PNode_canon_wf.
-Lemma PNode_canon_lookup_xH {A} (l : Pmap_raw A) o (r : Pmap_raw A) :
-  PNode_canon l o r !! 1 = o.
-Proof. by destruct l,o,r. Qed.
-Lemma PNode_canon_lookup_xO {A} (l : Pmap_raw A) o (r : Pmap_raw A) i :
-  PNode_canon l o r !! i~0 = l !! i.
-Proof. by destruct l,o,r. Qed.
-Lemma PNode_canon_lookup_xI {A} (l : Pmap_raw A) o (r : Pmap_raw A) i :
-  PNode_canon l o r !! i~1 = r !! i.
-Proof. by destruct l,o,r. Qed.
-Ltac PNode_canon_rewrite := repeat first
-  [ rewrite PNode_canon_lookup_xH | rewrite PNode_canon_lookup_xO
-  | rewrite PNode_canon_lookup_xI].
-
-Instance Ppartial_alter_raw {A} : PartialAlter positive A (Pmap_raw A) :=
-  fix go f i t {struct t} : Pmap_raw A :=
-  match t with
-  | PLeaf => match f None with None => PLeaf | Some x => Psingleton_raw i x end
-  | PNode l o r =>
-     match i with
-     | 1 => PNode_canon l (f o) r
-     | i~0 => PNode_canon (@partial_alter _ _ _ go f i l) o r
-     | i~1 => PNode_canon l o (@partial_alter _ _ _ go f i r)
-     end
-  end.
-Lemma Ppartial_alter_wf {A} f i (t : Pmap_raw A) :
-  Pmap_wf t → Pmap_wf (partial_alter f i t).
-Proof.
-  intros twf. revert i. induction twf.
-  * unfold partial_alter. simpl. case (f None); intuition.
-  * intros [?|?|]; simpl; intuition.
-  * intros [?|?|]; simpl; intuition.
-Qed.
-Instance Ppartial_alter {A} : PartialAlter positive A (Pmap A) := λ f i m,
-  PMap' (partial_alter f i (pmap_car m)) (Ppartial_alter_wf f i _ (pmap_prf m)).
+Proof. revert j. induction i; intros [?|?|]; simpl; auto with congruence. Qed.
 Lemma Plookup_alter {A} f i (t : Pmap_raw A) :
-  partial_alter f i t !! i = f (t !! i).
+  Ppartial_alter_raw f i t !! i = f (t !! i).
 Proof.
-  revert i. induction t.
-  * intros i. change (match f None with Some x => Psingleton_raw i x
-      | None => PLeaf end !! i = f None); destruct (f None).
-    + intros. apply Plookup_singleton.
-    + by destruct i.
-  * intros [?|?|]; simpl; by PNode_canon_rewrite.
+  revert i; induction t as [|o l IHl r IHr]; intros i; simpl.
+  * by destruct (f None); rewrite ?Plookup_singleton.
+  * destruct i; simpl; rewrite PNode_lookup; simpl; auto.
 Qed.
 Lemma Plookup_alter_ne {A} f i j (t : Pmap_raw A) :
-  i ≠ j → partial_alter f i t !! j = t !! j.
+  i ≠ j → Ppartial_alter_raw f i t !! j = t !! j.
 Proof.
-  revert i j. induction t as [|l IHl ? r IHr].
-  * intros. change (match f None with Some x => Psingleton_raw i x
-      | None => PLeaf end !! j = None); destruct (f None); [|done].
-    intros. by apply Plookup_singleton_ne.
-  * intros [?|?|] [?|?|]; simpl; PNode_canon_rewrite; auto; congruence.
+  revert i j; induction t as [|o l IHl r IHr]; simpl.
+  * by intros; destruct (f None); rewrite ?Plookup_singleton_ne.
+  * by intros [?|?|] [?|?|] ?; simpl; rewrite ?PNode_lookup; simpl; auto.
 Qed.
-
-Instance Pfmap_raw : FMap Pmap_raw := λ A B f,
-  fix go t :=
-  match t with
-  | PLeaf => PLeaf | PNode l x r => PNode (go l) (f <$> x) (go r)
-  end.
-Lemma Pfmap_ne `(f : A → B) (t : Pmap_raw A) : Pmap_ne t → Pmap_ne (fmap f t).
-Proof. induction 1; csimpl; auto. Qed.
-Local Hint Resolve Pfmap_ne.
-Lemma Pfmap_wf `(f : A → B) (t : Pmap_raw A) : Pmap_wf t → Pmap_wf (fmap f t).
-Proof. induction 1; csimpl; intuition. Qed.
-Global Instance Pfmap : FMap Pmap := λ A B f m,
-  PMap' (f <$> pmap_car m) (Pfmap_wf f _ (pmap_prf m)).
-Lemma Plookup_fmap {A B} (f : A → B) (t : Pmap_raw A) i :
-  (f <$> t) !! i = f <$> t !! i.
-Proof. revert i. induction t. done. by intros [?|?|]; simpl. Qed.
-
-Fixpoint Pto_list_raw {A} (j : positive) (t : Pmap_raw A)
-    (acc : list (positive * A)) : list (positive * A) :=
-  match t with
-  | PLeaf => acc
-  | PNode l o r => default [] o (λ x, [(Preverse j, x)]) ++
-     Pto_list_raw (j~0) l (Pto_list_raw (j~1) r acc)
-  end%list.
+Lemma Plookup_fmap {A B} (f : A → B) t i : (Pfmap_raw f t) !! i = f <$> t !! i.
+Proof. revert i. by induction t; intros [?|?|]; simpl. Qed.
 Lemma Pelem_of_to_list {A} (t : Pmap_raw A) j i acc x :
   (i,x) ∈ Pto_list_raw j t acc ↔
     (∃ i', i = i' ++ Preverse j ∧ t !! i' = Some x) ∨ (i,x) ∈ acc.
 Proof.
   split.
-  { revert j acc. induction t as [|l IHl [y|] r IHr]; intros j acc; simpl.
+  { revert j acc. induction t as [|[y|] l IHl r IHr]; intros j acc; simpl.
     * by right.
     * rewrite elem_of_cons. intros [?|?]; simplify_equality.
       { left; exists 1. by rewrite (left_id_L 1 (++))%positive. }
@@ -271,10 +188,10 @@ Proof.
       left; exists (i' ~ 1). by rewrite Preverse_xI, (associative_L _). }
   revert t j i acc. assert (∀ t j i acc,
     (i, x) ∈ acc → (i, x) ∈ Pto_list_raw j t acc) as help.
-  { intros t; induction t as [|l IHl [y|] r IHr]; intros j i acc;
+  { intros t; induction t as [|[y|] l IHl r IHr]; intros j i acc;
       simpl; rewrite ?elem_of_cons; auto. }
   intros t j ? acc [(i&->&Hi)|?]; [|by auto]. revert j i acc Hi.
-  induction t as [|l IHl [y|] r IHr]; intros j i acc ?; simpl.
+  induction t as [|[y|] l IHl r IHr]; intros j i acc ?; simpl.
   * done.
   * rewrite elem_of_cons. destruct i as [i|i|]; simplify_equality'.
     + right. apply help. specialize (IHr (j~1) i).
@@ -292,7 +209,7 @@ Lemma Pto_list_nodup {A} j (t : Pmap_raw A) acc :
   (∀ i x, (i ++ Preverse j, x) ∈ acc → t !! i = None) →
   NoDup acc → NoDup (Pto_list_raw j t acc).
 Proof.
-  revert j acc. induction t as [|l IHl [y|] r IHr]; simpl; intros j acc Hin ?.
+  revert j acc. induction t as [|[y|] l IHl r IHr]; simpl; intros j acc Hin ?.
   * done.
   * repeat constructor.
     { rewrite Pelem_of_to_list. intros [(i&Hi&?)|Hj].
@@ -318,60 +235,59 @@ Proof.
    apply IHr; auto. intros i x Hi.
    apply (Hin (i~1) x). by rewrite Preverse_xI, (associative_L _) in Hi.
 Qed.
-Global Instance Pto_list {A} : FinMapToList positive A (Pmap A) := λ m,
-  Pto_list_raw 1 (pmap_car m) [].
-
-Instance Pomap_raw : OMap Pmap_raw := λ A B f,
-  fix go t :=
-  match t with
-  | PLeaf => PLeaf | PNode l o r => PNode_canon (go l) (o ≫= f) (go r)
-  end.
-Lemma Pomap_wf {A B} (f : A → option B) (t : Pmap_raw A) :
-  Pmap_wf t → Pmap_wf (omap f t).
-Proof. induction 1; csimpl; auto. Qed.
-Local Hint Resolve Pomap_wf.
-Lemma Pomap_lookup {A B} (f : A → option B) (t : Pmap_raw A) i :
-  omap f t !! i = t !! i ≫= f.
+Lemma Pomap_lookup {A B} (f : A → option B) t i :
+  Pomap_raw f t !! i = t !! i ≫= f.
 Proof.
-  revert i. induction t as [| l IHl o r IHr ]; [done |].
-  intros [?|?|]; csimpl; PNode_canon_rewrite; auto.
+  revert i. induction t as [|o l IHl r IHr]; intros [i|i|]; simpl;
+    rewrite ?PNode_lookup; simpl; auto.
+Qed.
+Lemma Pmerge_lookup {A B C} (f : option A → option B → option C)
+    (Hf : f None None = None) t1 t2 i :
+  Pmerge_raw f t1 t2 !! i = f (t1 !! i) (t2 !! i).
+Proof.
+  revert t2 i; induction t1 as [|o1 l1 IHl1 r1 IHr1]; intros t2 i; simpl.
+  { rewrite Pomap_lookup. by destruct (t2 !! i). }
+  unfold compose, flip.
+  destruct t2 as [|l2 o2 r2]; rewrite PNode_lookup.
+  * by destruct i; rewrite ?Pomap_lookup; simpl; rewrite ?Pomap_lookup;
+      match goal with |- ?o ≫= _ = _ => destruct o end.
+  * destruct i; rewrite ?Pomap_lookup; simpl; auto.
 Qed.
-Global Instance Pomap: OMap Pmap := λ A B f m,
-  PMap' (omap f (pmap_car m)) (Pomap_wf f _ (pmap_prf m)).
 
-Instance Pmerge_raw : Merge Pmap_raw :=
-  fix Pmerge_raw A B C f t1 t2 : Pmap_raw C :=
-  match t1, t2 with
-  | PLeaf, t2 => omap (f None ∘ Some) t2
-  | t1, PLeaf => omap (flip f None ∘ Some) t1
-  | PNode l1 o1 r1, PNode l2 o2 r2 =>
-     PNode_canon (@merge _ Pmerge_raw A B C f l1 l2)
-      (f o1 o2) (@merge _ Pmerge_raw A B C f r1 r2)
-  end.
-Local Arguments omap _ _ _ _ _ _ : simpl never.
-Lemma Pmerge_wf {A B C} (f : option A → option B → option C) t1 t2 :
-  Pmap_wf t1 → Pmap_wf t2 → Pmap_wf (merge f t1 t2).
-Proof. intros t1wf. revert t2. induction t1wf; destruct 1; simpl; auto. Qed.
-Global Instance Pmerge: Merge Pmap := λ A B C f m1 m2,
-  PMap' _ (Pmerge_wf f _ _ (pmap_prf m1) (pmap_prf m2)).
-Lemma Pmerge_spec {A B C} (f : option A → option B → option C)
-    (Hf : f None None = None) (t1 : Pmap_raw A) t2 i :
-  merge f t1 t2 !! i = f (t1 !! i) (t2 !! i).
+(** Packed version and instance of the finite map type class *)
+Inductive Pmap (A : Type) : Type :=
+  PMap { pmap_car : Pmap_raw A; pmap_prf : Pmap_wf pmap_car }.
+Arguments PMap {_} _ _.
+Arguments pmap_car {_} _.
+Arguments pmap_prf {_} _.
+Lemma Pmap_eq {A} (m1 m2 : Pmap A) : m1 = m2 ↔ pmap_car m1 = pmap_car m2.
 Proof.
-  revert t2 i. induction t1 as [|l1 IHl1 o1 r1 IHr1]; intros t2 i.
-  { unfold merge; simpl. rewrite Pomap_lookup. by destruct (t2 !! i). }
-  destruct t2 as [|l2 o2 r2].
-  * unfold merge, Pmerge_raw. rewrite Pomap_lookup.
-    by destruct (PNode _ _ _ !! i).
-  * destruct i; simpl; by PNode_canon_rewrite.
+  split; [by intros ->|intros]; destruct m1 as [t1 ?], m2 as [t2 ?].
+  simplify_equality'; f_equal; apply proof_irrel.
 Qed.
+Instance Pmap_eq_dec `{∀ x y : A, Decision (x = y)}
+    (m1 m2 : Pmap A) : Decision (m1 = m2) :=
+  match Pmap_raw_eq_dec (pmap_car m1) (pmap_car m2) with
+  | left H => left (proj2 (Pmap_eq m1 m2) H)
+  | right H => right (H ∘ proj1 (Pmap_eq m1 m2))
+  end.
+Instance Pempty {A} : Empty (Pmap A) := PMap ∅ I.
+Instance Plookup {A} : Lookup positive A (Pmap A) := λ i m, pmap_car m !! i.
+Instance Ppartial_alter {A} : PartialAlter positive A (Pmap A) := λ f i m,
+  PMap (partial_alter f i (pmap_car m)) (Ppartial_alter_wf f i _ (pmap_prf m)).
+Instance Pfmap : FMap Pmap := λ A B f m,
+  PMap (f <$> pmap_car m) (Pfmap_wf f _ (pmap_prf m)).
+Instance Pto_list {A} : FinMapToList positive A (Pmap A) := λ m,
+  Pto_list_raw 1 (pmap_car m) [].
+Instance Pomap : OMap Pmap := λ A B f m,
+  PMap (omap f (pmap_car m)) (Pomap_wf f _ (pmap_prf m)).
+Instance Pmerge : Merge Pmap := λ A B C f m1 m2,
+  PMap _ (Pmerge_wf f _ _ (pmap_prf m1) (pmap_prf m2)).
 
-(** * Instantiation of the finite map interface *)
-Global Instance: FinMap positive Pmap.
+Instance Pmap_finmap : FinMap positive Pmap.
 Proof.
   split.
-  * intros ? [t1 ?] [t2 ?] ?. apply Pmap_eq; simpl.
-    apply Pmap_wf_eq_get; trivial; by apply (bool_decide_unpack _).
+  * by intros ? [t1 ?] [t2 ?] ?; apply Pmap_eq, Pmap_wf_eq.
   * by intros ? [].
   * intros ?? [??] ?. by apply Plookup_alter.
   * intros ?? [??] ??. by apply Plookup_alter_ne.
@@ -382,7 +298,7 @@ Proof.
     rewrite Pelem_of_to_list, elem_of_nil.
     split. by intros [(?&->&?)|]. by left; exists i.
   * intros ?? ? [??] ?. by apply Pomap_lookup.
-  * intros ??? ?? [??] [??] ?. by apply Pmerge_spec.
+  * intros ??? ?? [??] [??] ?. by apply Pmerge_lookup.
 Qed.
 
 (** * Finite sets *)
@@ -394,12 +310,12 @@ Instance: FinMapDom positive Pmap Pset := mapset_dom_spec.
 (** * Fresh numbers *)
 Fixpoint Pdepth {A} (m : Pmap_raw A) : nat :=
   match m with
-  | PLeaf | PNode _ None _ => O | PNode l _ _ => S (Pdepth l)
+  | PLeaf | PNode None _ _ => O | PNode _ l _ => S (Pdepth l)
   end.
 Fixpoint Pfresh_at_depth {A} (m : Pmap_raw A) (d : nat) : option positive :=
   match d, m with
-  | O, (PLeaf | PNode _ None _) => Some 1
-  | S d, PNode l _ r =>
+  | O, (PLeaf | PNode None _ _) => Some 1
+  | S d, PNode _ l r =>
      match Pfresh_at_depth l d with
      | Some i => Some (i~0) | None => (~1) <$> Pfresh_at_depth r d
      end
@@ -423,8 +339,8 @@ Lemma Pfresh_at_depth_fresh {A} (m : Pmap_raw A) d i :
   Pfresh_at_depth m d = Some i → m !! i = None.
 Proof.
   revert i m; induction d as [|d IH].
-  { intros i [|l [] r] ?; naive_solver. }
-  intros i [|l o r] ?; simplify_equality'.
+  { intros i [|[] l r] ?; naive_solver. }
+  intros i [|o l r] ?; simplify_equality'.
   destruct (Pfresh_at_depth l d) as [i'|] eqn:?,
     (Pfresh_at_depth r d) as [i''|] eqn:?; simplify_equality'; auto.
 Qed.
@@ -436,7 +352,7 @@ Proof.
 Qed.
 Lemma Pfresh_depth {A} (m : Pmap_raw A) :
   m !! Pos.shiftl_nat 1 (Pdepth m) = None.
-Proof. induction m as [|l IHl [x|] r IHr]; auto. Qed.
+Proof. induction m as [|[x|] l IHl r IHr]; auto. Qed.
 Lemma Pfresh_fresh {A} (m : Pmap A) : m !! Pfresh m = None.
 Proof.
   destruct m as [m ?]; unfold lookup, Plookup, Pfresh; simpl.