假设我有以下策略来检查术语是否为字面零:
Ltac isZero x :=
match x with
| O => constr:true
| _ => constr:false
end.
Goal Set.
let isz := isZero O in pose isz.
(* adds true to the context *)
现在想象一下,我希望战术能够接受更多;也许任何可以零转换的术语。如果这是一个针对目标的策略,我会做
Ltac isZero x :=
match x with
| ?v => unify v 0; constr:true
| _ => constr:false
end.
但这对于制定术语的策略来说是失败的:
Error: Value is a term. Expected a tactic.
如何检查策略生成条款中的可兑换性?在此特定示例中,减少x
或计算它(let xx := eval compute in x
)可能有效,但在更复杂的示例中,计算成本可能过高,特别是因为我需要减少比较的两个术语。
PS:作为参考,未经简化的问题是我试图有效地查找可能与FMap
的调用序列add
中的值匹配的密钥,以及该策略看起来像
Ltac find_key value :=
match fmap with
| add ?k value _ => constr:(Some k)
| add _ _ ?m => find_key value m
| _ => constr:None
end
通过此实现,如果地图包含可转换为value
但在语法上不等于value
的术语,而不是None
,则该策略将错误地返回Custom Control
。
答案 0 :(得分:1)
您可以尝试构建一个触发转换检查的术语;例如:
Goal 2 + 2 = 4.
match goal with
| |- ?a = ?b =>
let e := constr:(eq_refl a : a = b) in
idtac "equal"
| |- _ => idtac "not equal"
end.
通常,这打印"等于"。但是,如果您在上面的目标中将4
替换为3
,则内部分支会失败,打印"不等于"。