Suppose I have the following tactic to check if a term is the literal zero:
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 *)
Now imagine that I want the tactic to accept a bit more; maybe any term that is convertible with zero. If this was a tactic acting on the goal, I would do
Ltac isZero x :=
match x with
| ?v => unify v 0; constr:true
| _ => constr:false
end.
but this fails for a tactic producing terms:
Error: Value is a term. Expected a tactic.
How can I check for convertibility in a tactic producing terms? In this specific example reducing x
or computing it (let xx := eval compute in x
) may work, but in more complex example the cost of computing could be prohibitive, especially as I would need to reduce the two terms of the comparison.
PS: For reference, the unsimplified issue is that I'm trying to efficiently lookup a key probably matching a value in an FMap
built by sequences of calls to add
, and the tactic looks like
Ltac find_key value :=
match fmap with
| add ?k value _ => constr:(Some k)
| add _ _ ?m => find_key value m
| _ => constr:None
end
With this implementation, if instead of value
the map contains a term convertible to value
but not syntactically equal to it, the tactic will incorrectly return None
.