项精译器可以访问期望类型以及局部上下文。
这可用于构造一个与 assumption 策略对应的项版本。
第一步是使用 getLocalHyps 访问局部上下文。
它返回的上下文中,最外层绑定在左侧,因此这里按逆序遍历。
对于每个局部假设,都用 Meta.inferType 推断其类型。
如果它有可能与期望类型相等,就返回该假设;若没有任何假设合适,则产生错误。
syntax "anything!" : term
elab_rules <= expected
| `(anything!) => do
let hyps ← getLocalHyps
for h in hyps.reverse do
let t ← Meta.inferType h
if (← Meta.isDefEq t expected) then return h
throwError m!"No assumption in {hyps} has type {expected}"
这个新语法会找到函数的绑定变量:
7#eval (fun (n : Nat) => 2 + anything!) 5
7
它会按预期选择最近的合适变量:
"It was y"#eval
let x := "x"
let y := "y"
"It was " ++ y
"It was y"
当没有合适的假设时,它会返回一个描述此次尝试的错误:
#eval
let x := Nat.zero
let y := "hello"
fun (f : Nat → Nat) =>
(No assumption in [x, y, f] has type Int → Intanything! : Int → Int)
No assumption in [x, y, f] has type Int → Int
由于这里使用了合一,精译器会选择自然数字面量,因为数值字面量可以拥有任何带有 OfNat 实例的类型。
遗憾的是,函数并没有 OfNat 实例,因此后续的实例合成会失败。
#eval
let x := failed to synthesize instance of type class
OfNat (Int → Int) 5
numerals are polymorphic in Lean, but the numeral `5` cannot be used in a context where the expected type is
Int → Int
due to the absence of the instance above
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.5
let y := "hello"
(anything! : Int → Int)
failed to synthesize instance of type class
OfNat (Int → Int) 5
numerals are polymorphic in Lean, but the numeral `5` cannot be used in a context where the expected type is
Int → Int
due to the absence of the instance above
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.