我正在尝试在Coq中的弱指定类型上定义一个函数。具体来说,我有一个由一组递归构造函数归纳定义的类型,我想定义一个仅在使用这些构造的子集构造参数时定义的函数。
更具体地说,我有以下类型定义:
Inductive Example : Set :=
| Example_cons0 : nat -> Example
| Example_cons1 : Example -> Example
.
现在,我有一个仅适用于地面情况的功能。 (以下定义显然不起作用,但意在暗示我的意图。)
Definition example (x:Example) : nat :=
match x with
| Example_cons0 n => n
end.
理想情况下,我想告诉我,我的参数x是使用一般类型构造函数的子集构造的,在本例中是Example_cons0。我认为我可以通过定义一个谓词来说明这一事实,并将谓词的证明作为参数传递。例如:
Definition example_pred (x:Example) : Prop :=
match x with
| Example_cons0 _ => True
| _ => False
end.
然后(遵循Robin Green的建议),像
Definition example2 (x:Example) : example_pred x -> nat :=
(use proof to define example2?)
不幸的是,我不确定如何做这件事。我甚至不确定这是在弱指定类型上定义受限函数的正确方法。
我们非常感谢任何指导,提示或建议! - 李
更新
根据jozefg的建议,示例函数可以定义为:
Definition example (x:Example) : example_pred x -> nat :=
match x with
| Example_cons0 n => fun _ => n
| _ => fun proof => match proof with end
end.
详情请见他的评论。可以使用以下语法评估此函数,该语法还演示了如何在Coq中表示证明项:
Coq < Eval compute in Example.example (Example.Example_cons0 0) (I : Example.example_pred (Example.Example_cons0 0)).
= 0
: nat
答案 0 :(得分:2)
以下是我将其作为简化示例编写的方法
考虑一个简单的数据类型
Inductive Foo :=
| Bar : nat -> Foo
| Baz.
现在我们定义一个有用的功能
Definition bar f :=
match f with
| Bar _ => True
| Baz => False
end.
最后你要写的是什么:
Definition example f :=
match f return bar f -> nat with
| Bar n => fun _ => n
| Baz => fun p => match p with end
end.
这种类型为forall f : Foo, bar f -> nat
。这可以确保在example
未提供Bar
的情况下,用户必须提供虚假证明(不可能)。
这可以像这样调用
example (Bar n) I
但问题是,您可能需要手动证明某些术语是由Bar
构建的,否则Coq应该如何知道?
答案 1 :(得分:1)
是的,你是对的。你想要:
Definition example2 (x:Example) (example_pred x) : nat :=
以及如何进一步取决于你想要证明什么。
您可能会发现通过使用Curry-Howard信函证明战术来制定定义很有帮助:
Definition example2 (x:Example) (example_pred x) : nat.
Proof.
some proof
Defined.
另外,我想指出sig
和sigT
类型通常用于将“弱指定类型”与谓词结合起来约束它们。