Предположим, у меня есть следующая тактика, чтобы проверить, если термин является буквальным нулю:Как проверить конвертируемость в тактиковом выражении?
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: Для справки, unsimplified проблема в том, что я пытаюсь эффективно поиском ключа, вероятно, соответствующие значения в качестве 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
.
Вы не можете использовать тактику 'unify'? https://coq.inria.fr/refman/Reference-Manual010.html#hevea_tactic155 – Ptival
@Ptival, мой вопрос показал пример с использованием унификации, который не работает :) (в примере Артура это было бы, однако, но оно побочные эффекты) –
Это решение замечательно; большое спасибо! –