我如何说服Coq我的函数实际上是递归的?

时间:2016-05-26 23:34:27

标签: recursion coq termination

我正在尝试在Coq中编写一个程序来解析一个相对简单的无上下文语法(一种括号),而我的通用算法是让解析器可能返回字符串的其余部分。例如,解析"++]>><<"应返回CBTerminated [Incr Incr] ">><<",然后说解析“[++]&gt;&gt;&lt;&lt;&lt;”能够拿起“&gt;&gt;&lt;&lt;”并继续。

很明显,字符串较小,但令人信服的Coq是另一回事。它给了我错误

  

parseHelper的递归定义是不正确的。 [...]对parseHelper的递归调用具有等于“rest”的主要参数   “休息”。

我认为这意味着它不相信rest' < input确信rest < input<。 (其中Require Import Coq.Strings.String. Require Import Coq.Strings.Ascii. Require Import Coq.Lists.List. Require Import ZArith. Open Scope char_scope. Open Scope list_scope. Notation " [ ] " := nil (format "[ ]") : list_scope. Notation " [ x ] " := (cons x nil) : list_scope. Notation " [ x ; y ; .. ; z ] " := (cons x (cons y .. (cons z nil) ..)) : list_scope. Inductive BF := | Incr : BF | Decr : BF | Left : BF | Right : BF | In : BF | Out : BF | Sequence : list BF -> BF | While : BF -> BF. Inductive BF_Parse_Result := | UnmatchedOpen | EOFTerminated (u : list BF) | CBTerminated (u : list BF) (rest : string). Definition bind (val : BF) (onto : BF_Parse_Result) := match onto with | UnmatchedOpen => UnmatchedOpen | EOFTerminated values => EOFTerminated (cons val values) | CBTerminated values rest => CBTerminated (cons val values) rest end. Fixpoint parseHelper (input : string) : BF_Parse_Result := match input with | EmptyString => EOFTerminated nil | String first rest => match first with | "+" => bind Incr (parseHelper rest) | "-" => bind Decr (parseHelper rest) | "<" => bind Left (parseHelper rest) | ">" => bind Right (parseHelper rest) | "," => bind In (parseHelper rest) | "." => bind Out (parseHelper rest) | "]" => CBTerminated nil rest | "[" => match parseHelper rest with | UnmatchedOpen => UnmatchedOpen | EOFTerminated _ => UnmatchedOpen | CBTerminated vals rest' => bind (While (Sequence vals)) (parseHelper rest') end | _ => parseHelper rest end end. 表示“小于”)。

我想到的是返回一个要跳过多少个字符的计数,但这看起来相当不优雅和不必要。

addView

1 个答案:

答案 0 :(得分:8)

您是否考虑过使用well-founded recursion? Coq的标准库有一系列有用的组合器,用于定义功能良好的关系。参考1显示了一般递归的两种技术(有根据的递归和monad)。

在Agda的上下文中也非常有用的其他技术是所谓的Bove-Capretta method,它定义了一个模仿定义函数的调用图的归纳谓词。

Coq还有Function命令,可用于定义更一般的递归函数。每当我需要定义非结构递归函数时,我都使用了有根据的递归。

希望这会对你有所帮助。