bedrock.lang.bi.spec.frac_splittable
(*
* Copyright (C) BlueRock Security Inc. 2020-2022
*
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
Require Export bedrock.lang.bi.fractional.
Require Import bedrock.lang.bi.prelude.
Require Import bedrock.lang.bi.observe.
Require Import bedrock.lang.bi.spec.exclusive.
Require Import bedrock.lang.proofmode.proofmode.
#[local] Set Primitive Projections.
#[local] Set Default Proof Using "Type*".
* Copyright (C) BlueRock Security Inc. 2020-2022
*
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
Require Export bedrock.lang.bi.fractional.
Require Import bedrock.lang.bi.prelude.
Require Import bedrock.lang.bi.observe.
Require Import bedrock.lang.bi.spec.exclusive.
Require Import bedrock.lang.proofmode.proofmode.
#[local] Set Primitive Projections.
#[local] Set Default Proof Using "Type*".
Spec building block: fractional ownership
- FracVadidN, Frac2ValidN, FracSplittable_N R
- Tactic solve_frac for solving FracSplittable_N
- FracLaterAgree1 for higher-order predicates
- R is timeless, meaning it represents ownership;
- R is fractional, meaning it can be split and combined using
- the fraction in R is valid, meaning ≤ 1.
Notation FracValid0 P := (∀ q, Observe [| q ≤ 1 |]%Qp (P q)) (only parsing).
Notation FracValid1 P := (∀ q a, Observe [| q ≤ 1 |]%Qp (P q a)) (only parsing).
Notation FracValid2 P := (∀ q a b, Observe [| q ≤ 1 |]%Qp (P q a b)) (only parsing).
Notation FracValid3 P := (∀ q a b c, Observe [| q ≤ 1 |]%Qp (P q a b c)) (only parsing).
Notation FracValid4 P := (∀ q a b c d, Observe [| q ≤ 1 |]%Qp (P q a b c d)) (only parsing).
Notation FracValid5 P := (∀ q a b c d e, Observe [| q ≤ 1 |]%Qp (P q a b c d e)) (only parsing).
Notation FracValid1 P := (∀ q a, Observe [| q ≤ 1 |]%Qp (P q a)) (only parsing).
Notation FracValid2 P := (∀ q a b, Observe [| q ≤ 1 |]%Qp (P q a b)) (only parsing).
Notation FracValid3 P := (∀ q a b c, Observe [| q ≤ 1 |]%Qp (P q a b c)) (only parsing).
Notation FracValid4 P := (∀ q a b c d, Observe [| q ≤ 1 |]%Qp (P q a b c d)) (only parsing).
Notation FracValid5 P := (∀ q a b c d e, Observe [| q ≤ 1 |]%Qp (P q a b c d e)) (only parsing).
Frac2ValidN P is a useful corollary of FracValidN, observing q1 +
q2 ≤ 1 given P q1 a1 .. aN ** P q2 b1 .. bN.
Notation Frac2Valid0 P := (∀ q1 q2, Observe2 [| q1 + q2 ≤ 1 |]%Qp (P q1) (P q2)) (only parsing).
Notation Frac2Valid1 P := (∀ q1 q2 a1 a2, Observe2 [| q1 + q2 ≤ 1 |]%Qp (P q1 a1) (P q2 a2)) (only parsing).
Ltac solve_frac := solve [intros; split; apply _].
Class FracSplittable_0 {PROP : bi} (R : Qp → PROP) : Prop := {
#[global] frac_splittable_0_fractional :: Fractional R;
#[global] frac_splittable_0_timeless :: Timeless1 R;
#[global] frac_splittable_0_frac_valid :: FracValid0 R;
}.
Section frac_0.
Context {PROP : bi} (R : Qp → PROP) `{!FracSplittable_0 R}.
Global Instance frac_splittable_0_as_fractional : AsFractional0 R.
Proof. solve_as_frac. Qed.
Global Instance frac_splittable_0_frac_valid_2 : Frac2Valid0 R.
Proof.
intros. iIntros "R1 R2". iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
End frac_0.
Section frac_1_gen.
Context {A} {PROP : bi} (R : Qp → A → PROP).
Context {frac_splittable_1_frac_valid : FracValid1 R}.
Context {frac_splittable_1_as_fractional : AsFractional1 R}.
Global Instance frac_splittable_1_frac_valid_2 : AgreeF1 R -> Frac2Valid1 R.
Proof.
intros Ha *. iIntros "R1 R2".
iDestruct (Ha with "R1 R2") as %->.
iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
Global Instance frac_splittable_1_agreef_excl_gen q v1 v2 `{!AgreeF1 R} :
Observe2 False (R 1%Qp v1) (R q v2).
Proof.
iIntros "R1 R2".
by iDestruct (observe_2 [| _ + _ ≤ _ |]%Qp with "R1 R2") as %?%Qp.not_add_le_l.
Qed.
Goal AgreeF1 R → Exclusive1 (R 1).
Proof. apply _. Abort.
End frac_1_gen.
Class FracSplittable_1 {A} {PROP : bi} (R : Qp → A → PROP) : Prop := {
#[global] frac_splittable_1_fractional :: Fractional1 R;
#[global] frac_splittable_1_timeless :: Timeless2 R;
#[global] frac_splittable_1_frac_valid :: FracValid1 R;
}.
Section frac_1.
Context {A} {PROP : bi} (R : Qp → A → PROP) `{!FracSplittable_1 R}.
Global Instance frac_splittable_1_as_fractional : AsFractional1 R.
Proof. solve_as_frac. Qed.
Goal AgreeF1 R -> Frac2Valid1 R.
Proof. apply _. Abort.
Goal AgreeF1 R → Exclusive1 (R 1).
Proof. apply _. Abort.
End frac_1.
Class FracSplittable_2 {A B} {PROP : bi} (R : Qp → A → B → PROP) : Prop := {
#[global] frac_splittable_2_fractional :: Fractional2 R;
#[global] frac_splittable_2_timeless :: Timeless3 R;
#[global] frac_splittable_2_frac_valid :: FracValid2 R;
}.
Section frac_2.
Context {A B} {PROP : bi} (R : Qp → A → B → PROP) `{!FracSplittable_2 R}.
Global Instance frac_splittable_2_as_fractional : AsFractional2 R.
Proof. solve_as_frac. Qed.
End frac_2.
Class FracSplittable_3 {A B C} {PROP : bi}
(R : Qp → A → B → C → PROP) : Prop := {
#[global] frac_splittable_3_fractional :: Fractional3 R;
#[global] frac_splittable_3_timeless :: Timeless4 R;
#[global] frac_splittable_3_frac_valid :: FracValid3 R;
}.
Section frac_3.
Context {A B C} {PROP : bi} (R : Qp → A → B → C → PROP) `{!FracSplittable_3 R}.
Global Instance frac_splittable_3_as_fractional : AsFractional3 R.
Proof. solve_as_frac. Qed.
End frac_3.
Class FracSplittable_4 {A B C D} {PROP : bi}
(R : Qp → A → B → C → D → PROP) : Prop := {
#[global] frac_splittable_4_fractional :: Fractional4 R;
#[global] frac_splittable_4_timeless :: Timeless5 R;
#[global] frac_splittable_4_frac_valid :: FracValid4 R;
}.
Section frac_4.
Context {A B C D} {PROP : bi} (R : Qp → A → B → C → D → PROP).
Context `{!FracSplittable_4 R}.
Global Instance frac_splittable_4_as_fractional : AsFractional4 R.
Proof. solve_as_frac. Qed.
End frac_4.
Class FracSplittable_5 {A B C D E} {PROP : bi}
(R : Qp → A → B → C → D → E → PROP) : Prop := {
#[global] frac_splittable_5_fractional :: Fractional5 R;
#[global] frac_splittable_5_timeless :: Timeless6 R;
#[global] frac_splittable_5_frac_valid :: FracValid5 R;
}.
Section frac_5.
Context {A B C D E} {PROP : bi} (R : Qp → A → B → C → D → E → PROP).
Context `{!FracSplittable_5 R}.
Global Instance frac_splittable_5_as_fractional : AsFractional5 R.
Proof. solve_as_frac. Qed.
End frac_5.
Class FracSplittable_6 {A B C D E F} {PROP : bi}
(R : Qp → A → B → C → D → E → F → PROP) : Prop := {
#[global] frac_splittable_6_fractional a b c d e f :: Fractional (λ q, R q a b c d e f);
#[global] frac_splittable_6_timeless q a b c d e f :: Timeless (R q a b c d e f);
#[global] frac_splittable_6_frac_valid (q : Qp) a b c d e f ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f);
}.
Section frac_6.
Context {A B C D E F} {PROP : bi} (R : Qp → A → B → C → D → E → F → PROP).
Context `{!FracSplittable_6 R}.
Global Instance frac_splittable_6_as_fractional q a b c d e f :
AsFractional (R q a b c d e f) (λ q, R q a b c d e f) q.
Proof. solve_as_frac. Qed.
End frac_6.
Class FracSplittable_7 {A B C D E F G} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → PROP) : Prop := {
#[global] frac_splittable_7_fractional a b c d e f g ::
Fractional (λ q, R q a b c d e f g);
#[global] frac_splittable_7_timeless q a b c d e f g :: Timeless (R q a b c d e f g);
#[global] frac_splittable_7_frac_valid (q : Qp) a b c d e f g ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g);
}.
Section frac_7.
Context {A B C D E F G} {PROP : bi} (R : Qp → A → B → C → D → E → F → G → PROP).
Context `{!FracSplittable_7 R}.
Global Instance frac_splittable_7_as_fractional q a b c d e f g :
AsFractional (R q a b c d e f g) (λ q, R q a b c d e f g) q.
Proof. solve_as_frac. Qed.
End frac_7.
Class FracSplittable_8 {A B C D E F G H} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → PROP) : Prop := {
#[global] frac_splittable_8_fractional a b c d e f g h ::
Fractional (λ q, R q a b c d e f g h);
#[global] frac_splittable_8_timeless q a b c d e f g h ::
Timeless (R q a b c d e f g h);
#[global] frac_splittable_8_frac_valid (q : Qp) a b c d e f g h ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g h);
}.
Section frac_8.
Context {A B C D E F G H} {PROP : bi} (R : Qp → A → B → C → D → E → F → G → H → PROP).
Context `{!FracSplittable_8 R}.
Global Instance frac_splittable_8_as_fractional q a b c d e f g h :
AsFractional (R q a b c d e f g h) (λ q, R q a b c d e f g h) q.
Proof. solve_as_frac. Qed.
End frac_8.
Class FracSplittable_9 {A B C D E F G H I} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → I → PROP) : Prop := {
#[global] frac_splittable_9_fractional a b c d e f g h i ::
Fractional (λ q, R q a b c d e f g h i);
#[global] frac_splittable_9_timeless q a b c d e f g h i ::
Timeless (R q a b c d e f g h i);
#[global] frac_splittable_9_frac_valid (q : Qp) a b c d e f g h i ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g h i);
}.
Section frac_9.
Context {A B C D E F G H I} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → I → PROP).
Context `{!FracSplittable_9 R}.
Global Instance frac_splittable_9_as_fractional q a b c d e f g h i :
AsFractional (R q a b c d e f g h i) (λ q, R q a b c d e f g h i) q.
Proof. solve_as_frac. Qed.
End frac_9.
Notation Frac2Valid1 P := (∀ q1 q2 a1 a2, Observe2 [| q1 + q2 ≤ 1 |]%Qp (P q1 a1) (P q2 a2)) (only parsing).
Ltac solve_frac := solve [intros; split; apply _].
Class FracSplittable_0 {PROP : bi} (R : Qp → PROP) : Prop := {
#[global] frac_splittable_0_fractional :: Fractional R;
#[global] frac_splittable_0_timeless :: Timeless1 R;
#[global] frac_splittable_0_frac_valid :: FracValid0 R;
}.
Section frac_0.
Context {PROP : bi} (R : Qp → PROP) `{!FracSplittable_0 R}.
Global Instance frac_splittable_0_as_fractional : AsFractional0 R.
Proof. solve_as_frac. Qed.
Global Instance frac_splittable_0_frac_valid_2 : Frac2Valid0 R.
Proof.
intros. iIntros "R1 R2". iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
End frac_0.
Section frac_1_gen.
Context {A} {PROP : bi} (R : Qp → A → PROP).
Context {frac_splittable_1_frac_valid : FracValid1 R}.
Context {frac_splittable_1_as_fractional : AsFractional1 R}.
Global Instance frac_splittable_1_frac_valid_2 : AgreeF1 R -> Frac2Valid1 R.
Proof.
intros Ha *. iIntros "R1 R2".
iDestruct (Ha with "R1 R2") as %->.
iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
Global Instance frac_splittable_1_agreef_excl_gen q v1 v2 `{!AgreeF1 R} :
Observe2 False (R 1%Qp v1) (R q v2).
Proof.
iIntros "R1 R2".
by iDestruct (observe_2 [| _ + _ ≤ _ |]%Qp with "R1 R2") as %?%Qp.not_add_le_l.
Qed.
Goal AgreeF1 R → Exclusive1 (R 1).
Proof. apply _. Abort.
End frac_1_gen.
Class FracSplittable_1 {A} {PROP : bi} (R : Qp → A → PROP) : Prop := {
#[global] frac_splittable_1_fractional :: Fractional1 R;
#[global] frac_splittable_1_timeless :: Timeless2 R;
#[global] frac_splittable_1_frac_valid :: FracValid1 R;
}.
Section frac_1.
Context {A} {PROP : bi} (R : Qp → A → PROP) `{!FracSplittable_1 R}.
Global Instance frac_splittable_1_as_fractional : AsFractional1 R.
Proof. solve_as_frac. Qed.
Goal AgreeF1 R -> Frac2Valid1 R.
Proof. apply _. Abort.
Goal AgreeF1 R → Exclusive1 (R 1).
Proof. apply _. Abort.
End frac_1.
Class FracSplittable_2 {A B} {PROP : bi} (R : Qp → A → B → PROP) : Prop := {
#[global] frac_splittable_2_fractional :: Fractional2 R;
#[global] frac_splittable_2_timeless :: Timeless3 R;
#[global] frac_splittable_2_frac_valid :: FracValid2 R;
}.
Section frac_2.
Context {A B} {PROP : bi} (R : Qp → A → B → PROP) `{!FracSplittable_2 R}.
Global Instance frac_splittable_2_as_fractional : AsFractional2 R.
Proof. solve_as_frac. Qed.
End frac_2.
Class FracSplittable_3 {A B C} {PROP : bi}
(R : Qp → A → B → C → PROP) : Prop := {
#[global] frac_splittable_3_fractional :: Fractional3 R;
#[global] frac_splittable_3_timeless :: Timeless4 R;
#[global] frac_splittable_3_frac_valid :: FracValid3 R;
}.
Section frac_3.
Context {A B C} {PROP : bi} (R : Qp → A → B → C → PROP) `{!FracSplittable_3 R}.
Global Instance frac_splittable_3_as_fractional : AsFractional3 R.
Proof. solve_as_frac. Qed.
End frac_3.
Class FracSplittable_4 {A B C D} {PROP : bi}
(R : Qp → A → B → C → D → PROP) : Prop := {
#[global] frac_splittable_4_fractional :: Fractional4 R;
#[global] frac_splittable_4_timeless :: Timeless5 R;
#[global] frac_splittable_4_frac_valid :: FracValid4 R;
}.
Section frac_4.
Context {A B C D} {PROP : bi} (R : Qp → A → B → C → D → PROP).
Context `{!FracSplittable_4 R}.
Global Instance frac_splittable_4_as_fractional : AsFractional4 R.
Proof. solve_as_frac. Qed.
End frac_4.
Class FracSplittable_5 {A B C D E} {PROP : bi}
(R : Qp → A → B → C → D → E → PROP) : Prop := {
#[global] frac_splittable_5_fractional :: Fractional5 R;
#[global] frac_splittable_5_timeless :: Timeless6 R;
#[global] frac_splittable_5_frac_valid :: FracValid5 R;
}.
Section frac_5.
Context {A B C D E} {PROP : bi} (R : Qp → A → B → C → D → E → PROP).
Context `{!FracSplittable_5 R}.
Global Instance frac_splittable_5_as_fractional : AsFractional5 R.
Proof. solve_as_frac. Qed.
End frac_5.
Class FracSplittable_6 {A B C D E F} {PROP : bi}
(R : Qp → A → B → C → D → E → F → PROP) : Prop := {
#[global] frac_splittable_6_fractional a b c d e f :: Fractional (λ q, R q a b c d e f);
#[global] frac_splittable_6_timeless q a b c d e f :: Timeless (R q a b c d e f);
#[global] frac_splittable_6_frac_valid (q : Qp) a b c d e f ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f);
}.
Section frac_6.
Context {A B C D E F} {PROP : bi} (R : Qp → A → B → C → D → E → F → PROP).
Context `{!FracSplittable_6 R}.
Global Instance frac_splittable_6_as_fractional q a b c d e f :
AsFractional (R q a b c d e f) (λ q, R q a b c d e f) q.
Proof. solve_as_frac. Qed.
End frac_6.
Class FracSplittable_7 {A B C D E F G} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → PROP) : Prop := {
#[global] frac_splittable_7_fractional a b c d e f g ::
Fractional (λ q, R q a b c d e f g);
#[global] frac_splittable_7_timeless q a b c d e f g :: Timeless (R q a b c d e f g);
#[global] frac_splittable_7_frac_valid (q : Qp) a b c d e f g ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g);
}.
Section frac_7.
Context {A B C D E F G} {PROP : bi} (R : Qp → A → B → C → D → E → F → G → PROP).
Context `{!FracSplittable_7 R}.
Global Instance frac_splittable_7_as_fractional q a b c d e f g :
AsFractional (R q a b c d e f g) (λ q, R q a b c d e f g) q.
Proof. solve_as_frac. Qed.
End frac_7.
Class FracSplittable_8 {A B C D E F G H} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → PROP) : Prop := {
#[global] frac_splittable_8_fractional a b c d e f g h ::
Fractional (λ q, R q a b c d e f g h);
#[global] frac_splittable_8_timeless q a b c d e f g h ::
Timeless (R q a b c d e f g h);
#[global] frac_splittable_8_frac_valid (q : Qp) a b c d e f g h ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g h);
}.
Section frac_8.
Context {A B C D E F G H} {PROP : bi} (R : Qp → A → B → C → D → E → F → G → H → PROP).
Context `{!FracSplittable_8 R}.
Global Instance frac_splittable_8_as_fractional q a b c d e f g h :
AsFractional (R q a b c d e f g h) (λ q, R q a b c d e f g h) q.
Proof. solve_as_frac. Qed.
End frac_8.
Class FracSplittable_9 {A B C D E F G H I} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → I → PROP) : Prop := {
#[global] frac_splittable_9_fractional a b c d e f g h i ::
Fractional (λ q, R q a b c d e f g h i);
#[global] frac_splittable_9_timeless q a b c d e f g h i ::
Timeless (R q a b c d e f g h i);
#[global] frac_splittable_9_frac_valid (q : Qp) a b c d e f g h i ::
Observe [| q ≤ 1 |]%Qp (R q a b c d e f g h i);
}.
Section frac_9.
Context {A B C D E F G H I} {PROP : bi}
(R : Qp → A → B → C → D → E → F → G → H → I → PROP).
Context `{!FracSplittable_9 R}.
Global Instance frac_splittable_9_as_fractional q a b c d e f g h i :
AsFractional (R q a b c d e f g h i) (λ q, R q a b c d e f g h i) q.
Proof. solve_as_frac. Qed.
End frac_9.
To accomodate arguments before a fraction, universally quantify
over those arguments and cover the remaining arguments using a
Frac_i. Here's an example.
Module example.
Class Res {PROP : bi} : Type := {
my_thing (x : nat) (q : Qp) (y : nat) : PROP;
#[global] my_thing_frac x :: FracSplittable_1 (my_thing x);
}.
Lemma my_thing_example `{Res} q1 q2 x y :
my_thing x (q1 + q2) y ⊣⊢ my_thing x q1 y ∗ my_thing x q2 y.
Proof. exact: fractional. Qed.
End example.
Class Res {PROP : bi} : Type := {
my_thing (x : nat) (q : Qp) (y : nat) : PROP;
#[global] my_thing_frac x :: FracSplittable_1 (my_thing x);
}.
Lemma my_thing_example `{Res} q1 q2 x y :
my_thing x (q1 + q2) y ⊣⊢ my_thing x q1 y ∗ my_thing x q2 y.
Proof. exact: fractional. Qed.
End example.
Fractional ghost state with agreement on one higher-order argument.
Compared to FracSplittable_1, we
- drop Timeless because higher-order ghost state depends on the
- add Contractive and LaterAgreeF1 to enable agreement lemmas.
Class FracLaterAgree1 {A : ofe} {PROP} `{!BiInternalEq PROP}
(R : Qp -> A -> PROP) : Prop := {
#[global] frac_later_agree_1_fractional a :: Fractional (fun q => R q a);
#[global] frac_later_agree_1_valid q a :: Observe [| q ≤ 1 |]%Qp (R q a);
#[global] frac_later_agree_1_contractive q :: Contractive (R q);
#[global] frac_later_agree_1_agree :: LaterAgreeF1 R;
}.
#[global] Hint Mode FracLaterAgree1 - - - ! : typeclass_instances.
Section frac_later_agree.
Context {A : ofe} `{!BiInternalEq PROP}.
Context (R : Qp -> A -> PROP).
Context `{!frac_splittable.FracLaterAgree1 R}.
#[local] Set Default Proof Using "Type*".
#[local] Notation PROPO := (bi_ofeO PROP).
#[global] Instance frac_later_agree_1_ne q : NonExpansive (R q).
Proof. exact: contractive_ne. Qed.
#[global] Instance frac_later_agree_1_proper q :
Proper (equiv ==> equiv) (R q).
Proof. exact: ne_proper. Qed.
#[global] Instance frac_later_agree_1_as_fractional q a :
AsFractional (R q a) (fun q => R q a) q.
Proof. exact: Build_AsFractional. Qed.
#[global] Instance frac_later_agree_1_equivI q1 q2 a1 a2 :
Observe2 (R q1 a1 ≡@{PROPO} R q1 a2) (R q1 a1) (R q2 a2).
Proof.
iIntros "R1 R2". iDestruct (observe_2 (▷ (_ ≡ _)) with "R1 R2") as "#Eq".
rewrite (f_equivI_contractive (R q1)). auto.
Qed.
#[global] Instance frac_later_agree_1_valid_2 q1 q2 a1 a2 :
Observe2 [| q1 + q2 ≤ 1 |]%Qp (R q1 a1) (R q2 a2).
Proof.
iIntros "R1 R2". iDestruct (observe_2 (_ ≡ _) with "R1 R2") as "#Eq".
iRewrite "Eq" in "R1". iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
#[global] Instance frac_later_agree_1_exclusive : Exclusive1 (R 1).
Proof.
intros. iIntros "R1 R2".
by iDestruct (frac_later_agree_1_valid_2 with "R1 R2") as %?.
Qed.
End frac_later_agree.
(R : Qp -> A -> PROP) : Prop := {
#[global] frac_later_agree_1_fractional a :: Fractional (fun q => R q a);
#[global] frac_later_agree_1_valid q a :: Observe [| q ≤ 1 |]%Qp (R q a);
#[global] frac_later_agree_1_contractive q :: Contractive (R q);
#[global] frac_later_agree_1_agree :: LaterAgreeF1 R;
}.
#[global] Hint Mode FracLaterAgree1 - - - ! : typeclass_instances.
Section frac_later_agree.
Context {A : ofe} `{!BiInternalEq PROP}.
Context (R : Qp -> A -> PROP).
Context `{!frac_splittable.FracLaterAgree1 R}.
#[local] Set Default Proof Using "Type*".
#[local] Notation PROPO := (bi_ofeO PROP).
#[global] Instance frac_later_agree_1_ne q : NonExpansive (R q).
Proof. exact: contractive_ne. Qed.
#[global] Instance frac_later_agree_1_proper q :
Proper (equiv ==> equiv) (R q).
Proof. exact: ne_proper. Qed.
#[global] Instance frac_later_agree_1_as_fractional q a :
AsFractional (R q a) (fun q => R q a) q.
Proof. exact: Build_AsFractional. Qed.
#[global] Instance frac_later_agree_1_equivI q1 q2 a1 a2 :
Observe2 (R q1 a1 ≡@{PROPO} R q1 a2) (R q1 a1) (R q2 a2).
Proof.
iIntros "R1 R2". iDestruct (observe_2 (▷ (_ ≡ _)) with "R1 R2") as "#Eq".
rewrite (f_equivI_contractive (R q1)). auto.
Qed.
#[global] Instance frac_later_agree_1_valid_2 q1 q2 a1 a2 :
Observe2 [| q1 + q2 ≤ 1 |]%Qp (R q1 a1) (R q2 a2).
Proof.
iIntros "R1 R2". iDestruct (observe_2 (_ ≡ _) with "R1 R2") as "#Eq".
iRewrite "Eq" in "R1". iCombine "R1 R2" as "R". iApply (observe with "R").
Qed.
#[global] Instance frac_later_agree_1_exclusive : Exclusive1 (R 1).
Proof.
intros. iIntros "R1 R2".
by iDestruct (frac_later_agree_1_valid_2 with "R1 R2") as %?.
Qed.
End frac_later_agree.