[英]Check for evars in a tactic that returns a value
我正在嘗試編寫一個返回值的策略,並且在這樣做的過程中需要檢查某些東西是否為evar。
不幸的是,我不能使用is_evar
因為這樣的策略不會被視為返回值(而是另一種策略)。 一個例子如下。
有什么建議?
Ltac reify_wrt values ls :=
match ls with
| nil => constr:(@nil nat)
| ?a :: ?ls' => let i := lookup a values in
let idx := reify_wrt values ls' in
constr:(i :: idx)
| ?e :: ?ls' => is_evar e;
let i := constr:(100) in
let idx := reify_wrt values ls' in
constr:(i :: idx)
end.
這是Ltac的一個眾所周知的限制:你不能寫一個有時會返回一個值的策略,有時會返回另一個策略。 解決方案是以連續傳遞方式重寫你的策略。 不幸的是,我無法詳細解釋如何做到這一點,但Adam Chlipala的CDPT有一章關於Ltac描述了這個問題; 只需在文中尋找“延續”。
有一個整潔(或討厭)的小技巧,您可以使用它來將策略執行插入到Coq> = 8.5中的constr構造中:將其包裝在match goal
。
Ltac reify_wrt values ls := match ls with | nil => constr:(@nil nat) | ?a :: ?ls' => let i := lookup a values in let idx := reify_wrt values ls' in constr:(i :: idx) | ?e :: ?ls' => let check := match goal with _ => is_evar e end in let i := constr:(100) in let idx := reify_wrt values ls' in constr:(i :: idx) end.
因為編程語言奧秘讓我着迷,我現在告訴你的不僅僅是你想知道Ltac的現在和過去的執行模型。
戰術評估分為兩個階段:策略表達評估和戰術運行。 在戰術運行期間,執行排序,細化,重寫等。 在戰術表達評估期間,如果在戰術表達的頭部位置找到,則評估以下構造:
let ... in ...
將它的參數的表達式 - 評估與名稱綁定,並進行替換 constr:(...)
進行評估和類型檢查 lazymaytch ... with ... end
被評估(帶后向跟蹤),並返回第一個匹配的分支,該分支成功進行表達式評估 match ... with ... end
評估(使用回溯) 並且急切地執行分支 。 請注意,在這張圖片中, match
很奇怪,因為它迫使戰術的執行提前到來。 如果您曾在Coq <8.5中看到“本地定義中不允許立即匹配生成策略”,那么這是一條明確禁止我正在利用上述行為的錯誤消息。 我猜這是因為這種奇怪的match
行為是原始開發者實施Ltac想要隱藏的疣。 因此,你可以在Coq 8.4中注意到的唯一一個地方就是如果你在lazymatch
match
並使用失敗級別,並注意到lazymatch
會在你通常期望它失敗的情況下回溯內部match
中戰術執行的失敗。 在Coq 8.5中,戰術引擎被重寫以處理依賴的子目標。 這引起了語義的細微變化;
這只能在使用多個目標之間共享的evars時才能觀察到。 在重寫中,開發者將lazymatch
的語義改為“ match
無回溯”,並解除了對“即時匹配生成策略”的限制。 因此你可以做一些奇怪的事情:
let dummy := match goal with _ => rewrite H end in
constr:(true)
並制定具有副作用的制定策略。 但是,你不能再做了:
let tac := lazymatch b with
| true => tac1
| false => tac2
end in
tac long args.
因為在Coq> = 8.5中, lazymatch
也急切地評估它的分支。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.