我如何检查策略生成条款的可兑换性?
How do I check for convertibility in a tactic producing terms?
假设我有以下策略来检查一个术语是否为零:
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
中的值匹配的键,该 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
,则该策略将不正确 return None
.
您可以尝试构造一个触发转换检查的术语;例如:
Goal 2 + 2 = 4.
match goal with
| |- ?a = ?b =>
let e := constr:(eq_refl a : a = b) in
idtac "equal"
| |- _ => idtac "not equal"
end.
通常,这会打印 "equal"。但是,如果您在上面的目标中将 4
替换为 3
,内部分支将失败,打印 "not equal".
假设我有以下策略来检查一个术语是否为零:
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
中的值匹配的键,该 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
,则该策略将不正确 return None
.
您可以尝试构造一个触发转换检查的术语;例如:
Goal 2 + 2 = 4.
match goal with
| |- ?a = ?b =>
let e := constr:(eq_refl a : a = b) in
idtac "equal"
| |- _ => idtac "not equal"
end.
通常,这会打印 "equal"。但是,如果您在上面的目标中将 4
替换为 3
,内部分支将失败,打印 "not equal".