我刚刚发现了最大和非最大参数的存在(参见https://coq.inria.fr/refman/Reference-Manual004.html#sec109)。
但是有没有动力使用一个而不是另一个?一个比另一个更近?最大隐式参数只需要创建{}
,而必须使用Arguments
或Implicit Arguments
来指定非最大值。是否应该首选最大隐式参数?
答案 0 :(得分:6)
......是否有动力使用其中一种?
是的,但是(像往常一样)"它取决于"。让我们先讨论一下它们之间的区别。
最大插入隐式(MII)参数添加了下一级"隐含性"对语言。 仅当函数应用于至少一个参数时,才会插入普通(非MII)参数。此外,Coq仅在之前插入 某些提供的显式参数。
MII参数更多"渴望":Coq认为它们在某些提供的显式参数之后插入。一个极端情况:如果一个函数的签名以一个MII参数开头,那么就足以提到Coq的函数名称(即使没有应用程序)将它变成一个部分应用的函数(它不会发生在非-MII参数)。有时候这种急切的行为有助于编写简洁的代码,有时甚至会产生一些麻烦,因为它迫使我们插入其他多余的@
符号来抑制隐式参数的插入。
让我展示一些简单的例子,主要来自参考手册或标准库。
序言:
Require Import Coq.Lists.List. Import ListNotations.
Section Length.
Variable A:Type.
length
函数具有非MII第一个参数:
Print Implicit length.
(*
Output:
length : forall A : Type, list A -> nat
Argument A is implicit
*)
这就是为什么以下简单代码失败的原因(由于length
未部分应用而导致失败,因此未插入A
):
Fail Check (fun l:list (list A) => map length l).
必须写下这样的东西才能使其发挥作用:
Check (fun l:list (list A) => map (@length _) l).
(* or *)
Check (fun l:list (list A) => map (length (A := _)) l).
(* or *)
Check (fun l:list (list A) => map (fun xs => length xs) l).
另一种方法是使用MII参数。直观地,在这种情况下,Coq用length
替换(@length _)
:
Arguments length {A} _.
Check (fun l:list (list A) => map length l).
End Length.
但是当有人想要以最常见的形式(未部分应用)使用某个函数或构造函数时,有时最大插入的参数会受到影响。来自Coq.Lists.List
模块的非MII参数的工作示例:
Set Implicit Arguments. (* non-MII arguments is the default behavior *)
Inductive Forall2 A B (R:A->B->Prop) : list A -> list B -> Prop :=
| Forall2_nil : Forall2 R [] []
| Forall2_cons : forall x y l l',
R x y -> Forall2 R l l' -> Forall2 R (x::l) (y::l').
Theorem Forall2_refl : forall A B (R:A->B->Prop), Forall2 R [] [].
Proof. exact Forall2_nil. Qed.
但exact Forall2_nil
在MII论证的情况下不起作用。不过,constructor
会对我们有所帮助:
Arguments Forall2_nil {A B} _.
Theorem Forall2_refl' : forall A B (R:A->B->Prop), Forall2 R [] [].
Proof. Fail (exact Forall2_nil). constructor. Qed.
另一个过早隐式参数插入的实例(来自Coq.Init.Logic
)。这适用于非MII参数:
Declare Left Step eq_stepl.
但是,我们必须添加' @':
Arguments eq_stepl {A} _ _ _ _ _.
Fail Declare Left Step eq_stepl.
Declare Left Step @eq_stepl.
有时,<tactic-name> ... with (_ := _).
形式的策略会在存在MII参数时失败。这是来自Coq.Init.Logic
的另一个(工作)示例:
Definition eq_ind_r :
forall (A:Type) (x:A) (P:A -> Prop), P x -> forall y:A, y = x -> P y.
intros A x P H y H0; elim eq_sym with (1 := H0); assumption.
Defined.
但是MII的论点阻碍了我们的进步:
Arguments eq_sym {A x y} _.
Definition eq_ind_r' :
forall (A:Type) (x:A) (P:A -> Prop), P x -> forall y:A, y = x -> P y.
intros A x P H y H0.
Fail elim eq_sym with (1 := H0); assumption.
(* this works *)
elim @eq_sym with (1 := H0); assumption.
(* or this: *)
elim (eq_sym H0); assumption.
Defined.
一个比另一个更新吗?
我不知道我希望有人可以对此有所了解。
最大隐式参数只需创建
{}
,而必须使用Arguments
或Implicit Arguments
来指定非最大参数。是否应该首选最大隐式参数?
默认情况下,指令Set Implicit Arguments.
声明非最大插入的隐式参数。因此,Coq对于隐含性水平是保守的(但不是太多)。我默认情况下坚持使用非MII参数,在适当的位置插入{}
。