Coq 乘积型上的相互递归函数

Coq 乘积型上的相互递归函数,coq,mutual-recursion,Coq,Mutual Recursion,(初学Coq问题) 与之相关的是,我试图在产品类型上定义一个递归函数。这里的区别是有一个相互递归的定义。我一直遇到这个错误: printObjItem的递归定义格式不正确 对printJson的递归调用的主参数等于“val”,而不是 “项”的子项 从概念上讲,似乎应该进行递归,因为val是item的子项,是items的子项,是x的子项。我理解Coq正在为第一个断言而挣扎,但我不确定如何解决。有没有一种没有明确的良好基础证明的直接方法 Require Import List. Require Im

(初学Coq问题)

与之相关的是,我试图在产品类型上定义一个递归函数。这里的区别是有一个相互递归的定义。我一直遇到这个错误:

printObjItem的递归定义格式不正确

对printJson的递归调用的主参数等于“val”,而不是 “项”的子项

从概念上讲,似乎应该进行递归,因为
val
item
的子项,是
items
的子项,是
x
的子项。我理解Coq正在为第一个断言而挣扎,但我不确定如何解决。有没有一种没有明确的良好基础证明的直接方法

Require Import List.
Require Import String.
Import ListNotations.

Inductive Json :=
  | Atom : Json
  | String : string -> Json
  | Array : nat -> list Json -> Json
  | Object : list (string * Json) -> Json.

Fixpoint printJson (x : Json) :=
  match x with
  | Atom => "atom"
  | String n => "'" ++ n ++ "'"
  | Array _ els => "[" ++ (String.concat ", " (map printJson els)) ++ "]"
  | Object items => "{" ++ (String.concat ", " (map printObjItem items)) ++ "}"
  end%string
with printObjItem (item : string * Json) :=
       let (key, val) := item in key ++ ": " ++ (printJson val).

一种解决方案是将
printObjItem
作为本地定义:

Fixpoint printJson (x : Json) :=
  let printObjItem (item : string * Json) :=
    (let (key, val) := item in key ++ ": " ++ (printJson val))%string
  in
  match x with
  | Atom => "atom"
  | String n => "'" ++ n ++ "'"
  | Array _ els => "[" ++ (String.concat ", " (map printJson els)) ++ "]"
  | Object items => "{" ++ (String.concat ", " (map printObjItem items)) ++ "}"
  end%string.

这成功了!有没有关于为什么这种方法有效而相互递归无效的直觉?相互递归用于相互归纳类型
printObjItem
仅指
printJson
,因此内联它或生成本地定义都可以。希望能有帮助。