如何在策略生成条款中检查可兑换性?

时间:2015-10-10 00:46:31

标签: coq coq-tactic

假设我有以下策略来检查术语是否为字面零:

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

1 个答案:

答案 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,则内部分支会失败,打印"不等于"。