State-separating cell references #
Heap Ident stores typed cells at stable identifiers. CellRef Ident packages
one identifier as a typed reference, so heap programs can say explicitly which
cell they read or write.
The main purpose of this file is frame reasoning. A program that writes only a
known footprint preserves every cell outside that footprint, and the same idea
lifts from deterministic state programs to support-based effectful programs and
to oracle handlers interpreted by simulateQ.
The file is organized around four small layers:
Cell references #
A capability naming one typed cell in a Heap Ident. The value type of
the reference is dependent: r.Value = CellSpec.type r.id.
- id : Ident
The underlying heap cell identifier.
Instances For
Write a referenced cell in a heap.
Instances For
Deterministic state operations #
Deterministically write a referenced cell.
Instances For
Effectful state operations #
Effectfully read a referenced cell. This is the monadic version of
CellRef.read: it works in any ambient monad, not just Id.
Instances For
Effectfully write a referenced cell. This is the monadic version of
CellRef.write: it updates only the selected heap cell and performs no other
ambient effects.
Instances For
Support-based frame predicates #
An effectful heap program preserves a cell reference when every
support-reachable final heap has the same value at that reference as the
initial heap. This is the right generalization of Preserves beyond Id:
for probabilistic/oracle computations there may be many possible final states.
Instances For
An effectful heap program writes only a set of identifiers when every cell outside the set is support-preserved.
Instances For
Dependent effectful bind form: the continuation's write set may depend on the first result.
A support-based write footprint packages a program with the set of cells it may write and the proof that every other cell is preserved.
- writes : Set Ident
Cells that the effectful program may write.
- sound : SupportWritesOnly c self.writes
Soundness: every cell outside
writesis support-framed through.
Instances For
Instances For
Instances For
Instances For
Instances For
Probability corollaries for cell frames #
A support-level frame implies that the cell-change event has probability zero. This is the probability-facing corollary most proofs want after a generic frame theorem has done the support-level work.
If a cell is support-preserved, then the probability of reading the initial value at the end is exactly one minus the failure probability.
Failure-free specialization of prob_unchanged_eq_sub_probFailure.
If the ambient monad has total probability semantics, support preservation gives probability-one preservation directly.
If the initial cell value is not x, then a support-preserved cell has
final value x with probability zero.
Preservation except an event #
A computation preserves a cell except on an event when every support-reachable outcome outside that event has the initial cell value. The event may depend on the initial heap.
Instances For
If a cell can change only when event occurs, then the change probability
is bounded by the event probability.
Relational and measured cell effects #
A support-level relation between the initial and final value of one cell.
This is the general qualitative layer underneath preservation (rel := Eq) and
monotonicity/growth assertions.
Instances For
A support-level cell relation makes violations of the relation a probability-zero event.
A measured cell bound says a numeric measure of a cell can increase by at
most δ on every support-reachable execution path. Binds compose by adding
their deltas.
Instances For
A measured support bound gives probability zero to exceeding the bound.
Deterministic specialization #
A deterministic heap program preserves a cell reference when the final heap has the same value at that reference as the initial heap.
This exact Id-specific predicate is equivalent to SupportPreserves, whose
support contains exactly the single deterministic output. The exact form keeps
deterministic examples pleasant to use, while the combinator proofs below are
derived from the generic support-based API.
Instances For
Dependent bind form: the continuation's write set may depend on the first result. The resulting write set is the union of the first write set and all possible continuation write sets.
Read agreement and result-dependence footprints #
A deterministic heap program's result depends only on a set of cells when heaps agreeing on those cells produce equal return values. This intentionally tracks only the returned value, not the final heap.
Instances For
Compositional write footprints #
A compositional write footprint packages a deterministic heap program with the set of cells it may write and the proof that all other cells are preserved.
- writes : Set Ident
Cells that the program may write.
- sound : WritesOnly c self.writes
Soundness: every cell outside
writesis framed through.
Instances For
Instances For
Instances For
Instances For
Instances For
Query-implementation cell frames #
A QueryImpl preserves a heap cell when each single query step leaves
that cell unchanged on every support-reachable post-state. This is the
support-level analogue of CellRef.Preserves for probabilistic handlers.
Instances For
A QueryImpl writes only the cells named by a per-query footprint when
each query step support-preserves every cell outside its footprint.
Instances For
A compositional cell-write footprint for a whole query implementation: every domain element gets a set of cells it may write, plus a support-level proof that no other cells change.
Per-query cells that may be written by the handler branch.
- sound : WritesOnlyCells impl self.writes
Soundness of the footprint.
Instances For
If every handler query preserves a cell, then interpreting any
OracleComp through that handler preserves the cell.
A query-implementation cell-write footprint lifts through interpretation: if a cell is outside every per-query footprint, the interpreted computation preserves that cell.
Examples #
Query-handler write footprints #
Every demo query returns unit; the interesting part is the heap effect.
Instances For
The handler writes only the cells declared by demoWrites.
Pack the handler-level footprint once, so later proofs need not unfold every query branch.
Instances For
The flag is outside every branch footprint, so each handler step preserves it.
A tiny client computation that calls several branches of the demo handler.
Instances For
The previous theorem as a reusable support-preservation predicate.
A compositional footprint for cacheAndLogStep. Reads contribute no writes,
writes contribute singleton footprints, and binds union the footprints.
Instances For
The compositional footprint gives flag preservation without unfolding each state update in the final proof.
A compositional footprint for the two-write program. The write set is
computed by WriteFootprint.bind: first {cache}, then {log}.
Instances For
Once the footprint says the write set is {cache, log}, flag preservation
is a one-line frame application plus a membership proof.
As a corollary, flagRef is preserved by cacheAndLogStep.