互递类型的自定义归纳原理

时间:2018-11-28 18:42:53

标签: coq

对于为某些特定的相互递归类型定义归纳原理,我有些困惑。使用Schema并不能真正解决我的问题,这就是为什么我想自己定义原理(也许我使用相互递归类型的整个方法不合适,这也是一个选择)。

我正在使用Arthur的extructure库(这就是ordType的来源,可能是其他原因)。所以,我的类型是:

From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.


From extructures Require Import ord fmap.

Section R.

Variables Name Vals : ordType.

Inductive ResponseObject : Type :=
  | SingleResponse : Result -> ResponseObject
  | MultipleResponses : Result -> ResponseObject -> ResponseObject
  with Result : Type :=
       | Empty : Result
       | Null : Name -> Result
       | SingleResult : Name -> Vals -> Result
       | ListResult : Name -> seq Vals -> Result
       | NestedResult : Name -> ResponseObject -> Result
       | NestedListResult : Name -> seq ResponseObject -> Result.

它基本上是Result对象的非空列表,它们本身可以保存非空列表(NestedResultNestedListResult)。

我遇到的问题是NestedListResult,因为使用Schema生成的归纳原理不会检查ResponseObject列表中的每个元素。它指出以下内容:

Scheme ResponseObject_ind := Induction for ResponseObject Sort Prop
    with Result_ind := Induction for Result Sort Prop.

Check ResponseObject_ind.
ResponseObject_ind
     : forall (P : ResponseObject -> Prop) (P0 : Result -> Prop),
       (forall r : Result, P0 r -> P (SingleResponse r)) ->
       (forall r : Result, P0 r -> forall r0 : ResponseObject, P r0 -> P (MultipleResponses r r0)) ->
       P0 Empty ->
       (forall s : Name, P0 (Null s)) ->
       (forall (s : Name) (s0 : Vals), P0 (SingleResult s s0)) ->
       (forall (s : Name) (l : seq Vals), P0 (ListResult s l)) ->
       (forall (s : Name) (r : ResponseObject), P r -> P0 (NestedResult s r)) ->
       (forall (s : Name) (l : seq ResponseObject), P0  (NestedListResult s l)) -> forall r : ResponseObject, P r

我尝试遵循SSReflect GenTree中的示例(基本上将其折叠在列表上,并检查每个元素是否满足谓词),但是在尝试定义它时遇到语法错误(我猜这是语法错误吗? ),但不确定如何解决。我的猜测是使用fixwith是不正确的,我应该用其他方式写出来吗?

我的尝试是这样:

Definition ResponseObject_ind P Ps IH_SingleResponse IH_MultipleResponses IH_Empty IH_Null IH_SingleResult IH_ListResult IH_NestedResult IH_NestedListResult :=
    fix loop (r : ResponseObject) : P r : Prop :=
       match r with
       | SingleResponse r' => IH_SingleResponse r' (Result_ind r')
       | MultipleResponses r' rs => IH_MultipleResponses r' (Result_ind r') rs (loop rs)
       end
      with Result_ind (r : Result) : Ps r : Prop :=
       match r with
       | Empty => IH_Empty
       | Null l => IH_Null l
       | SingleResult l v => IH_SingleResult l v
       | ListResult l vals => IH_ListResult l vals
       | NestedResult l r' => IH_NestedResult l r' (Result_ind r')
       | NestedListResult l rs =>
         let fix iter_conj rs : foldr (fun r => and (P r)) True rs :=
             if rs is r :: rs' then conj (loop r) (iter_conj rs') else Logic.I
         in
         IH_NestedListResult l rs (iter_conj rs)
       end.

任何帮助将不胜感激:)

PS。实际上,也许其他方法比使用相互递归类型更好。...在我将ResponseObject用作Result类型的另一个构造函数并检查它是否形成“适当的”列表之前(没有嵌套的{ {1}}形成了怪异的树事物)。上面的这个选项看起来更优雅,但也许不太方便。

1 个答案:

答案 0 :(得分:0)

您的解决方案不遵守语法和类型约束。解决这些约束的一种方法导致以下代码:

Definition ResponseObject_ind' (P : ResponseObject -> Prop) 
 (Ps : Result -> Prop) IH_SingleResponse IH_MultipleResponses IH_Empty IH_Null
IH_SingleResult IH_ListResult
(IH_NestedResult : forall (s : Name) (r : ResponseObject),
   P r -> Ps (NestedResult s r))
IH_NestedListResult :=
fix loop (r : ResponseObject) : P r : Prop :=
   match r with
   | SingleResponse r' => IH_SingleResponse r' (Result_ind r')
   | MultipleResponses r' rs => IH_MultipleResponses r' (Result_ind r') rs (loop rs)
   end
  with Result_ind (r : Result) : Ps r : Prop :=
   match r with
   | Empty => IH_Empty
   | Null l => IH_Null l
   | SingleResult l v => IH_SingleResult l v
   | ListResult l vals => IH_ListResult l vals
   | NestedResult l r' => IH_NestedResult l r' (loop r')
   | NestedListResult l rs =>
     let fix iter_conj rs : foldr (fun r => and (P r)) True rs :=
         if rs is r :: rs' then conj (loop r) (iter_conj rs') else Logic.I
     in
     IH_NestedListResult l rs (iter_conj rs)
   end
 for loop.

我不喜欢您的iter_conj解决方案。

在我看来,您实际上正在生成一堆归纳类型,其中包含三种归纳类型:ResponseObjectResultseq ResponseObject。因此,除了让您的归纳原理采用两个谓词PPs之外,您还应该拥有三个谓词:P用于类型ResponseObjectPs用于{{1 }}和Result的{​​{1}}。以下是我的解决方案:

Pl

此解决方案是通过调用seq ResponseObject命令然后编辑标题(为序列添加Definition RO_ind := fun P P0 P1 (f : forall r : Result, P0 r -> P (SingleResponse r)) (f0 : forall r : Result, P0 r -> forall r0 : ResponseObject, P r0 -> P (MultipleResponses r r0)) (f1 : P0 Empty) (f2 : forall n : Name, P0 (Null n)) (f3 : forall (n : Name) (v : Vals), P0 (SingleResult n v)) (f4 : forall (n : Name) (l : seq Vals), P0 (ListResult n l)) (f5 : forall (n : Name) (r : ResponseObject), P r -> P0 (NestedResult n r)) (f6 : forall (n : Name) (l : seq ResponseObject), P1 l -> P0 (NestedListResult n l)) (f7 : P1 [::]) (f8 : forall (ro : ResponseObject), P ro -> forall (l : seq ResponseObject), P1 l -> (P1 (ro :: l))) (ro : ResponseObject) => fix F (r : ResponseObject) : P r := match r as r0 return (P r0) with | SingleResponse r0 => f r0 (F0 r0) | MultipleResponses r0 r1 => f0 r0 (F0 r0) r1 (F r1) end with F0 (r : Result) : P0 r := match r as r0 return (P0 r0) with | Empty => f1 | Null n => f2 n | SingleResult n v => f3 n v | ListResult n l => f4 n l | NestedResult n r0 => f5 n r0 (F r0) | NestedListResult n l => f6 n l ((fix F1 l' : P1 l' := match l' with | [::] => f7 | ro :: l' => f8 ro (F ro) l' (F1 l') end) l) end for F0. SchemeP1并最终编辑的大小写而产生的) f7构造。