最大与非最大隐式参数的目的

时间:2016-05-13 13:55:55

标签: coq

我刚刚发现了最大和非最大参数的存在(参见https://coq.inria.fr/refman/Reference-Manual004.html#sec109)。

但是有没有动力使用一个而不是另一个?一个比另一个更近?最大隐式参数只需要创建{},而必须使用ArgumentsImplicit Arguments来指定非最大值。是否应该首选最大隐式参数?

1 个答案:

答案 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.
  

一个比另一个更新吗?

我不知道我希望有人可以对此有所了解。

  

最大隐式参数只需创建{},而必须使用ArgumentsImplicit Arguments来指定非最大参数。是否应该首选最大隐式参数?

默认情况下,指令Set Implicit Arguments.声明非最大插入的隐式参数。因此,Coq对于隐含性水平是保守的(但不是太多)。我默认情况下坚持使用非MII参数,在适当的位置插入{}