Ltac SepOpSolve :=
match goal with
| H : (match ?f ?x with | Some _ => _ | None => _ end) |- _ =>
let e := fresh "e" in let y := fresh "y" in remember (f x) as e;
destruct e as [y |]; SepOpSolve
| H : _ \/ _ |- _ => destruct H as [H | H]; SepOpSolve
| H : _ /\ _ |- _ => let H1 := fresh "H" in destruct H as [H H1]; SepOpSolve
| H : ?f ?x = _ |- context [match ?f ?x with | Some _ => _ | None => _ end] =>
rewrite H; SepOpSolve
| H : forall x : X, _ |- _ =>
match goal with
| x : X |- _ => specialize (H x)
end; SepOpSolve
| _ => subst; try intuition congruence
end.
(* We can create a separation algebra for partial functions with the following definitions for sa_unit and sa_mul *)
Global Instance PFunSepAlgOps : SepAlgOps (X -> option Y) := {
sa_unit f := pfun_eq f emptyFun;
sa_mul    := fun a b c => forall x,
match c x with
| Some y => (a x = Some y /\ b x = None) \/
(b x = Some y /\ a x = None)
| None => a x = None /\ b x = None
end
}.
(* Proving that partial functions actually form a separation algebra is straightforward modulo some LTac magic. *)
Global Instance PFunSepAlg : SepAlg (rel := pfun_eq) (X -> option Y).

(* Specifications: *)
Lemma pfun_in_sa_mulR (a b c : X -> option Y) (x : X) (H : sa_mul a b c) (Hin : pfun_in c x) : pfun_in a x \/ pfun_in b x.
Lemma pfun_mapsto_sa_mulR (a b c : X -> option Y) (x : X) (y : Y) (H : sa_mul a b c) (Hmap : c x = Some y) : a x = Some y \/ b x = Some y.
End PartialFun.