Simulation Semantics for Oracles in a Computation #
Given an implementation of spec in the monad r, convert an OracleComp spec α to a
implementation in r α by substituting impl t for query t throughout.
Instances For
Version of simulateQ that bundles into a monad hom.
Instances For
Specialized form of simulateQ_query for the canonical spec.query t
constructor: simulateQ impl (liftM (spec.query t)) = impl t.
The general simulateQ_query rewrite leaves an id <$> artifact when applied
to spec.query t (because (spec.query t).cont = id). That artifact is
harmless when spec.Range t is concrete (it disappears under definitional
reduction), but in parametric sum-spec contexts ((E₁ + E₂).Range (Sum.inl t)
vs E₁.Range t, both abstract atoms) the type annotations diverge and
id_map no longer fires under simp only. This lemma sidesteps the artifact
entirely and is the canonical entry point for simplifying simulateQ over an
explicit spec.query t.
Companion to simulateQ_query for a query entering the computation through a
query-level lift chain: simulating a query lifted from a sub-spec spec' applies the
implementation to the lifted query.
The (liftM q : OracleComp spec α) on the left elaborates through the canonical
MonadLift (OracleQuery spec) (OracleComp spec) composed (via instMonadLiftTOfMonadLift)
with the given MonadLiftT (OracleQuery spec') (OracleQuery spec) — e.g. a SubSpec
embedding chain such as spec₂ ⊂ₒ spec₁ + spec₂ ⊂ₒ spec + (spec₁ + spec₂). This is the
term shape produced by lifting a query helper (liftM (liftM (spec'.query t))) into a
larger interface, as OracleSpec.SubSpec-based protocol verifiers do. simulateQ_query
itself cannot match it: its query's spec is forced to equal the simulated spec, while here
the query lives in spec'.
The right-hand side is deliberately mapQuery of the single term liftM q rather than
the unbundled (liftM q).cont <$> impl (liftM q).input: the type of .cont depends on
.input, so the unbundled form blocks all further simp rewriting of the lifted query
(the dependent-motive trap). With mapQuery, the lifted query can then be normalized in
place (everything in the SubSpec lift chain is definitional) and landed on the
implementation with mapQuery_mk.
Not @[simp]: for the common sum-spec layouts the specialized routing lemmas
(QueryImpl.simulateQ_add_add_liftM_query_left and friends in SimSemantics/Append.lean)
resolve the routed query in one step; this general form would preempt them and strand the
goal at an un-normalized mapQuery (liftM q). Use it manually for bespoke lift chains.
Evaluate an oracle computation by answering each query with a total answer function.
This is the Id-valued specialization of simulateQ: each query in mx is replaced by the
corresponding value returned by f.
Instances For
Two simulateQ'd binds whose bodies agree up to a pure post-map f agree up to mapping
f over the whole simulation. Companion to simulateQ_bind for establishing map-relations
between two simulations without unfolding the shared leading computation oa.
QueryImpl.id' is an identity for simulateQ with implementation in OracleComp spec.
Lifting queries to their original implementation has no effect on a computation.
List / ForM distributivity #
simulateQ distributes over List.mapM: simulating a mapped list is the same as
mapping the simulated function over the list.
simulateQ distributes over forIn on a list: a monad morphism commutes with forIn.
This is the forIn (early-exit / accumulating loop) sibling of simulateQ_list_mapM and
simulateQ_list_forM. It lets a simulateQ pushed in front of a verifier-style loop
forIn (List.finRange t) init (fun j acc => …) be moved inside the loop body, after which the
individual simulated query steps can be discharged.
Composition of simulations via a per-query bridge #
Two-stage simulation: if a "reduction" red : QueryImpl spec₁ (StateT σ (OracleComp spec₂))
followed by an inner impl : QueryImpl spec₂ n agrees per-query with a "combined" handler
game : QueryImpl spec₁ (StateT σ n), then the agreement extends to every outer computation by
structural induction. This packages the boilerplate induction reused across PRF-style reductions.
Three-layer simulation collapse: if a "reduction" red : QueryImpl spec₁ (StateT σ (OracleComp spec₂)) followed by an inner cached impl : QueryImpl spec₂ (StateT τ n) agrees
per-query with a single "combined" handler combined : QueryImpl spec₁ (StateT (σ × τ) n) up to
the natural reassociation α × σ × τ ≃ (α × σ) × τ, then the agreement extends to every outer
computation. This packages the boilerplate induction used by lazy-random-oracle / cached-PRF
collapses.