4.3.1. Untyped to typed🔗
Untyped.Term.toTypedAs checks, at runtime, an untyped term against (the sort associated to) a static type to produce a typed term.
🔗def
Documentation
Types a sort-erased term at α, checking its sort against α's.
toTyped infers α from the expected type; typeCheckAs and typeCheck are the same two
functions under the names that say what they do.
If the term's type can be inferred from context, Untyped.Term.toTyped is a more concise alternative.
🔗def
Documentation
Types a sort-erased term at α, checking its sort against α's.
toTyped infers α from the expected type; typeCheckAs and typeCheck are the same two
functions under the names that say what they do.
Under their aliases, Untyped.Term.typeCheckAs and Untyped.Term.typeCheck, the same two functions say what they do. For example:
open Untyped in
boolTerm: (or x false)
typedTerm: (or x false)
iteTerm: (ite (or x false) 1 0)
cannot type the following term as `Int`, term has sort `Bool`:
(or x false)
#eval Env.runIO do
let bool ← Srt.bool
let x ← Term.mkSymbol bool "x"
let boolTerm ← smt! x ∨ false
println! "boolTerm: {boolTerm}"
let typedTerm ← boolTerm.toTypedAs Bool
println! "typedTerm: {typedTerm}"
let boolToInt (t : Typed.Term Bool) :=
smt! if t then 1 else 0
let iteTerm ← boolTerm.typeCheck >>= boolToInt
println! "iteTerm: {iteTerm}"
println! ""
try
let illTyped ← boolTerm.typeCheckAs Int
println! "unexpected: {illTyped}"
catch e =>
println! "{e}"
boolTerm: (or x false)
typedTerm: (or x false)
iteTerm: (ite (or x false) 1 0)
cannot type the following term as `Int`, term has sort `Bool`:
(or x false)
4.3.3. Every conversion🔗
Going down is always free. Going up checks sorts at runtime, except for solvers and proofs, where there is nothing to check: a solver is the same type in both layers, and a typed proof is a sort-erased one under a type of its own. Where the sort-erased counterpart has no type of its own, there is no way back up.
| typed | sort-erased | down | up |
|---|---|---|---|
| Term α | Term | toUntyped, erase | toTyped(As), typeCheck(As) |
| BVar α | BVar | toUntyped, erase | toTyped(As), typeCheck(As) |
| NT α | NT | toUntyped, erase | toTyped(As), typeCheck(As) |
| Grammar σ | Grammar | toUntyped, erase | toTyped(As), typeCheck(As) |
| Solver.Heap s α β | Solver.Heap s | toUntyped, erase | toTyped(As), typeCheck(As) |
| Datatype.Ctor α | Datatype.Ctor | toUntyped, erase | toTyped(As), typeCheck(As) |
| Datatype.Field α β | Datatype.Selector | toUntyped, erase | toTyped(As), typeCheck(As) |
| record Fields fields | Fields names | toUntyped, erase | toTyped(As), typeCheck(As) |
| Solver | Solver | toUntyped, relax | toTyped |
| Solver.Proof s pc | Solver.Proof s pc | toUntyped, relax | toTyped |
| BVars, NTs | BVars, NTs | toUntyped, erase | none |
| datatype Args, tuple and application spines | Terms | toUntyped, erase | none |
| Datatype.Case α β | Term | toUntyped, erase | none |
The value classes convert too: a typed TermToValue or ValueToTerm instance gives a sort-erased one and the other way round, so a Lean type given conversions in one layer is usable in both.