为什么 Coq 在对可强制项应用参数时不能推断出我的强制项?

Why can't Coq infer my coercion when applying arguments to coercible term?

我正在尝试将特定 sigma 类型的强制转换写入二元关系。强制转换在使用可强制转换项作为函数参数时起作用,但在将相同术语用作函数时不起作用。

代码如下:

Definition relation A := A -> A -> Prop.

Definition is_serial {A} (R: relation A) := forall x, exists y, R x y.

Definition serial state := {R: relation state | is_serial R}.

Definition serial_to_relation A (s: serial A) : relation A := proj1_sig s.
Coercion serial_to_relation : serial >-> relation.

Parameter foo: serial nat.
Parameter bar: relation nat -> Prop.

(* Succeeds in coercing an argument. *)
Check (bar foo).

(* Fails to coerce when applying arguments to coercible term *)
Fail Check (foo 1 2).

这是该代码段的可执行版本:https://x80.org/collacoq/udutosoher.coq

为什么第二次检查失败了?我的强制定义有误吗?或者这是我不知道的强制推理的一些限制?

我认为最后一种情况的问题是 Coq 试图推断 foo 的函数类型,而 relation A 并不是字面意义上的函数类型(直到展开 relation).

如果按如下方式向 Funclass 添加强制转换(请参阅 doc),则最后一个测试会通过

Definition serial_to_fun A (s: serial A) : A -> A -> Prop := proj1_sig s.
Coercion serial_to_fun : serial >-> Funclass.

嗯。它只是无法“理解”你想让它强制关系 nat。

当你写 Check (bar foo). 时,coq 应该统一 bar 期望的类型(即 relation nat)和 foo 具有的类型(即 serial nat).因此,coq 试图统一 serial natrelation nat,并且由于这些类型不可转换,coq“理解”它需要尝试使用强制转换。因此,它试图找到从 serial natrelation nat 的强制转换。既然你提供了这样的强制,它就成功了。

编辑。 当您编写 Check (foo 1 2). 时,coq 将尝试统一 foo(即 serial nat)的类型和 (nat -> nat -> A) 等函数的类型。所以,再一次,它只是看不到你想让它强制 foorelation nat