我正在考虑编写一个Coq程序来验证relational algebra的某些属性。我有一些基本的数据类型可以工作,但连接元组给我带来了一些麻烦。
以下是相关的代码部分:
Require Import List.
Require Import String.
(* An enum representing SQL types *)
Inductive sqlType : Set := Nat | Bool.
(* Defines a map from SQL types (which are just enum values) to Coq types. *)
Fixpoint toType (t : sqlType) : Set :=
match t with
| Nat => nat
| Bool => bool
end.
(* A column consists of a name and a type. *)
Inductive column : Set :=
| Col : string -> sqlType -> column.
(* A schema is a list of columns. *)
Definition schema : Set := list column.
(* Concatenates two schema together. *)
Definition concatSchema (r : schema) (s : schema) : schema := app r s.
(* Sends a schema to the corresponding Coq type. *)
Fixpoint tuple (s : schema) : Set :=
match s with
| nil => unit
| cons (Col str t) sch => prod (toType t) (tuple sch)
end.
Fixpoint concatTuples {r : schema} {s : schema} (a : tuple r) (b : tuple s) : tuple (concatSchema r s) :=
match r with
| nil => b
| cons _ _ => (fst a , concatTuples (snd a) b)
end.
在函数concatTuples中,在零的情况下,CoqIDE给出了一个错误:
"The term "b" has type "tuple s" while it is expected to have type "tuple (concatSchema ?8 s)"."
我想我明白那里发生了什么;类型检查器无法确定s
和concatSchema nil s
是否相等。但我发现更奇怪的是当我添加以下行时:
Definition stupid {s : schema} (b : tuple s) : tuple (concatSchema nil s) := b .
并将案例更改为nil => stupid b
,它有效。 (好吧,它仍然在利弊案件中抱怨,但我认为这意味着它接受了无案件。)
我有三个问题:
stupid
?似乎Coq知道类型是相等的,它只需要某种暗示。stupid
的函数时遇到了很多麻烦。答案 0 :(得分:3)
这是Coq新手最常见的问题之一:无法向Coq展示如何使用match
声明分支中获得的其他信息。
解决方案是使用所谓的convoy pattern,重新抽象依赖于您的详细检查并使match
返回函数的参数:
Fixpoint concatTuples {r : schema} {s : schema} : tuple r -> tuple s -> tuple (concatSchema r s) :=
match r return tuple r -> tuple s -> tuple (concatSchema r s) with
| nil => fun a b => b
| cons (Col _ t) _ => fun a b => (fst a, concatTuples (snd a) b)
end.
在这种特殊情况下,实际上并不需要return
注释,因为Coq可以推断它。但是,当事情有点不对时,省略它通常会导致难以理解的错误消息,因此将它们留在其中是个好主意。请注意,我们还必须在列表的第一个元素上包含嵌套匹配( Col _ t
模式),以模仿tuple
定义中的模式。再一次,CPDT详细解释了这里发生了什么,以及如何在Coq中编写这种函数。
要回答你的上一个问题,异构列表的许多发展或多或少都与你在这里做的一样(例如我有one development非常类似于这个)。如果我必须更改任何内容,我会删除tuple
定义中的嵌套模式,这允许您在使用较少的match
es和注释时编写此类代码。比较:
Definition typeOfCol c :=
match c with
| Col _ t => t
end.
(* Sends a schema to the corresponding Coq type. *)
Fixpoint tuple (s : schema) : Set :=
match s with
| nil => unit
| cons col sch => prod (toType (typeOfCol col)) (tuple sch)
end.
Fixpoint concatTuples {r : schema} {s : schema} : tuple r -> tuple s -> tuple (concatSchema r s) :=
match r return tuple r -> tuple s -> tuple (concatSchema r s) with
| nil => fun a b => b
| cons _ _ => fun a b => (fst a, concatTuples (snd a) b)
end.