簡體   English   中英

如何為構造函數設置隱式參數

[英]How to set implicit parameters for constructor

與nostutter excersizes一起玩我發現了另一種奇怪的行為。 這是代碼:

Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).

Example test_nostutter_manual: not (nostutter [3;1;1;4]).
Proof.
  intro.
  inversion_clear H.
  inversion_clear H0.
  unfold not in H2.
  (* We are here *)
  specialize (H2 eq_refl).
  apply H2.
Qed.

展開后的狀態是這樣的:

1 subgoal (ID 229)

H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False

當我運行specialize (H2 eq_refl). 在IndProp.v中加載其他邏輯基礎文件,它可以工作。 不知何故,它理解它需要將“1”作為參數。 IndProp.v的標題是這樣的:

Set Warnings "-notation-overridden,-parsing".
From LF Require Export Logic.
Require Import String.
Require Coq.omega.Omega.

當我將代碼移動到另一個文件“nostutter.v”時,這個相同的代碼給出了一個預期的錯誤:

術語“eq_refl”具有類型“RelationClasses.Reflexive Logic.eq”,而期望它具有類型“1 = 1”。

nostutter.v的標題:

Set Warnings "-notation-overridden,-parsing".
Require Import List.
Import ListNotations.
Require Import PeanoNat.
Import Nat.
Local Open Scope nat_scope.

我必須明確地向eq_refl添加一個參數: specialize (H2 (eq_refl 1)).

我認為這與專業化無關。 它是什么? 怎么修?

問題是導入PeanoNat.Nat

當您導入PeanoNat ,模塊類型Nat進入范圍,因此導入NatPeanoNat.Nat 如果您要導入Coq.Init.Nat ,則必須在導入PeanoNat之前導入PeanoNat ,或者使用Import Init.Nat.導入它Import Init.Nat.

為什么導入PeanoNat.Nat會導致這種情況的麻煩?

Arith / PeanoNat.v靜態鏈接 )包含模塊1 Nat 在該模塊中,我們發現2個不尋常的外觀

Include NBasicProp <+ UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties.

所有這些意味着包括NBasicPropUsualMinMaxLogicalPropertiesUsualMinMaxDecProperties中的每一個,這反過來意味着在那些模塊中定義的所有內容都包含在當前模塊中。 將這一行分成三個Include命令,我們可以找出哪一個正在重新定義eq_refl 原來是NBasicProp ,可以在這個文件中找到( 靜態鏈接 )。 我們還沒到那里:eq_refl的重新定義不在這里。 然而,我們看到的定義NBasicProp來講NMaxMinProp

這導致我們進入NMaxMin.v,后者又將我們帶到NSub.v,它將我們帶到NMulOrder.v,它將我們帶到NAddOrder.v,它將我們帶到NOrder.v,它將我們帶到NAdd.v,這導致我們到NBase.v,...

我會切到這里追逐。 最后,我們在最終結構/ Equality.v靜態鏈接 )與模塊BackportEq並最終賦予我們的重新定義eq_refl

Module BackportEq (E:Eq)(F:IsEq E) <: IsEqOrig E.
 Definition eq_refl := @Equivalence_Reflexive _ _ F.eq_equiv.
 Definition eq_sym := @Equivalence_Symmetric _ _ F.eq_equiv.
 Definition eq_trans := @Equivalence_Transitive _ _ F.eq_equiv.
End BackportEq.

這個定義的方式, eq_refl (沒有任何參數)有類型Reflexive eq ,其中Reflexive是類

Class Reflexive (R : relation A) :=
  reflexivity : forall x : A, R x x.

(在Classes / RelationClasses.v中找到)

所以這意味着我們總是需要提供額外的參數來獲得x = x類型的東西。 這里沒有定義隱式參數。

為什么導入像PeanoNat.Nat這樣的模塊通常是個壞主意?

如果上面的野鵝追逐不夠令人信服,那么我只想說像這樣擴展和導入其他模塊和模塊類型的模塊通常不是要導入的。 它們通常具有短名稱(如NZNat ),因此您可以輕松訪問要從中使用的任何定理,而無需鍵入長名稱。 它們通常具有長鏈進口,因此包含大量物品。 如果您導入它們,那么現在大量的項目正在污染您的全局命名空間。 正如您在eq_refl看到的eq_refl ,這會導致您認為常見的常見事件。


  1. 在這次冒險中遇到的大多數模塊都屬於“模塊類型/仿函數”。 可以說,他們很難完全理解,但可以在這里找到一個簡短的指南。

  2. 我的調查是通過在CoqIDE中打開文件並運行命令Locate eq_refl. (或者更好的是,ctrl + shift + L)在可能從其他地方導入的任何東西之后。 Locate還可以告訴您從哪里導入常量。 我希望有一種更簡單的方法來查看模塊類型中的導入路徑,但我不這么認為。 您可能會猜測我們最終會根據覆蓋的eq_refl的類型進入eq_refl ,但這並不精確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM