exercises.later
From iris.heap_lang Require Import lang proofmode notation.
(* ################################ *)
(* ################################ *)
Section later.
Context `{!heapGS Σ}.
(* ================================================================= *)
Basics
Lemma later_mono (P Q : iProp Σ) : (Q ⊢ P) → (▷ Q ⊢ ▷ P).
Proof.
intros HQP.
iIntros "HQ".
iNext.
by iApply HQP.
Qed.
The iNext tactic is actually a specialisation of the more general
iModIntro tactic, which works with all modalities. The iModIntro
tactic can be invoked with the introduction pattern "!>", making it
less verbose to handle the later modality.
Lemma later_mono' (P Q : iProp Σ) : (Q ⊢ P) → (▷ Q ⊢ ▷ P).
Proof.
intros HQP.
iIntros "HQ !>".
by iApply HQP.
Qed.
The later modality weakens propositions; owning resources now is
stronger than owning them later. In other words, P ⊢ ▷ P. This means
that we can always remove a later from the goal, regardless of whether
our hypotheses have a later.
The later modality distributes over ∧, ∨, ∗, and is preserved
by ∃ and ∀. This means we can destruct these constructs
regardless of being prefaced by any laters.
Lemma later_sep (P Q : iProp Σ) : ▷ (P ∗ Q) ⊣⊢ ▷ P ∗ ▷ Q.
Proof.
iSplit.
- iIntros "[HP HQ]".
iFrame.
- iIntros "[HP HQ] !>".
iFrame.
Qed.
As a consequence of monotonicity, weakening, and distribution over
∗, the iNext tactic can simply ignore hypotheses in the context
that do not have a later on them.
Lemma later_impl (P Q : iProp Σ) : P ∗ ▷ (P -∗ Q) -∗ ▷ Q.
Proof.
(* exercise *)
Admitted.
(* ================================================================= *)
Tying Later to Program Steps
Lemma take_2_steps (P : iProp Σ) : ▷ ▷ P -∗ WP #1 + #2 + #3 {{_, P}}.
Proof.
iIntros "HP".
wp_pure.
wp_pure.
done.
Qed.
The reason this works is that under the hood of WP, there is a later
for every step of the program. Thus, the `wp' tactics can use the
properties mentioned in the previous section to remove laters from the
context, similarly to iNext.
Further, it turns out that in many cases, a ▷ on an assumption can
be safely ignored. For instance, in the example below, we only own the
points-to predicate later, yet we can still perform the load.
Lemma later_points_to (l : loc) : ▷ (l ↦ #5) -∗ WP !#l + #1 {{v, ⌜v = #6⌝}}.
Proof.
iIntros "Hl".
wp_load.
by wp_pures.
Qed.
The technical reason for this is that points-to predicates are
so-called timeless propositions, and the `wp' tactics are aware of
this fact. We study timeless propositions further in a separate
chapter.
(* ================================================================= *)
Löb Induction
This function never terminates for any input as it will keep calling
itself with larger and larger inputs. To show this, we pick the
postcondition False. We can now use Löb induction, along with
wp_rec, to prove this specification.
The tactic for Löb induction, iLöb, requires us to specify the
name of the induction hypothesis, which we here call "IH".
Optionally, it can also universally quantify over any of our variables
before performing induction. We here universally quantify over x as it
changes for every recursive call.
(* Mansky: since we usually only need to generlise varible in
Lob induction/iInduction, it should suffice to only do it
under iLob/iInudction. *)
iLöb as "IH" forall (x).
Lob induction/iInduction, it should suffice to only do it
under iLob/iInudction. *)
iLöb as "IH" forall (x).
iLöb automatically introduces the universally quantified variables in
the goal, so we can proceed to execute the function.
wp_rec.
wp_pure.
wp_pure.
Since we have taken steps, the ▷ in our induction hypothesis has
been stripped, allowing us to apply the hypothesis for the recursive
call.