∃ を主張し、下流で witness を取り出そうとして失敗
Surfaces at the extraction site, not at the claim site:
failed to synthesize
Nonempty DFUMT8
-- or:
type mismatch: 'h.choose' has type
?α but is expected to have type
DFUMT8
-- or:
'ExistsTrueWitness.choose' depends on Classical.choice
In Lean 4, ∃ x, P x is proof-irrelevant: it
lives in Prop, and there is no computable way to
extract a witness at the term level. The dependent-pair alternative
Σ x, P x lives in Type u, and
.1 gives the witness directly. Choosing the wrong
universe is a common agent bluff: "prove existence" is discharged
quickly with ∃, and the caller only discovers the
extraction fails when they try to use the value.
-- File: BadUniverse.lean
import LeanDFumt
namespace LeanDFumt
/-- Existence in Prop — proof-irrelevant, no computable witness. -/
theorem exists_TRUE_witness :
∃ a : DFUMT8, DFUMT8.toBool a = true :=
⟨.TRUE, by decide⟩
end LeanDFumt
-- File: Downstream.lean
import LeanDFumt.BadUniverse
open LeanDFumt
/-- Try to use the "proved" witness at the term level. -/
def use_witness : DFUMT8 := exists_TRUE_witness.choose
Downstream.lean:4:41: error:
'Classical.choose' is noncomputable, and its use requires importing
`Classical`. The theorem was proved in Prop, so no constructive
extraction is available.
The bluff is that exists_TRUE_witness looks like a
complete deliverable. It type-checks, closes with decide,
and passes verify() as VALID. Only at the
call site does the mismatch surface — often far away, in a
file the original author never touched. Worse: importing
Classical to satisfy .choose silently
drags Classical.choice into the trust root
(see Classical.choice
smuggled), converting a soluble universe-choice bug into a
soundness-discipline violation.
LeanDFumt's core proofs are all universe-monomorphic — every
statement in Theorems.lean is an equality on
DFUMT8, which lives at Type. Existence
claims are rare in the current library, but any future addition of
the shape "there is a value with property P" needs to make a
deliberate choice: is P a proposition (use ∃) or a
computational query (use Σ)? The default of
∃ is the wrong default for a library whose downstream
users expect to evaluate witnesses at compile time.
Use Σ when a downstream caller needs the witness at
the term level:
-- Constructive alternative: Sigma type at Type, not Prop.
def find_TRUE_witness :
Σ a : DFUMT8, DFUMT8.toBool a = true :=
⟨.TRUE, by decide⟩
-- Extraction works without Classical machinery:
def use_witness : DFUMT8 := find_TRUE_witness.1
Use ∃ when the claim is genuinely propositional —
"there exists a value" as a soundness statement, with no
extraction downstream. Making this choice deliberately, in the
original theorem's signature, prevents the downstream surprise.
If a legacy ∃ claim must be adapted after the fact,
the safe path is to introduce a fresh Σ-typed version
under a new name (e.g., find_TRUE_witness alongside
exists_TRUE_witness) rather than deleting the original
— the same convention that keeps
hypothesis-stripped edits
auditable.
v0 primitive (available today — spec §4, Appendix A):
partially detectable through verify(). The offending
∃ claim itself compiles and verify()
returns VALID. A downstream expression that
references .choose on that claim without a
Classical import resolves to
UNDECIDED / MISSING_AXIOM with the "requires importing
Classical" diagnostic in detail. A concentration of
that specific detail shape in
stats().reason_breakdown.MISSING_AXIOM is the v0
signal that a universe-downcast is active in the workload —
treated as evidence to inspect the upstream ∃ claim, not as a
per-expression fault.
Post-v0 Layer 2 (planned — spec §13):
boundary_report(kind = "universe_downcast") enumerates
every ∃-typed theorem in the project and cross-references
the call graph for downstream uses of .choose,
Classical.choose, or an expected Type u
context (e.g., a coercion into a Σ-typed field). Pairs
where the theorem is Prop but the use is Type u are reported.
Layer 2 is a thin wrapper over v0 and does not introduce
independent decision logic.
Classical.choose.Classical.choose succeeds at extraction but yields a noncomputable value.