我認爲這是一個很好的方法來做到這一點。通常情況下,當你想創建一個類型的「子集」,它看起來像:
postulate
A : Set
P : A → Set
record Subset : Set where
field
value : A
prop : P value
然而,這可能不是在這個意義上,它實際上可以包含比原來的類型更多的元素的子集。這是因爲prop
可能有更多的命題上不同的值。例如:
open import Data.Nat
data ℕ-prop : ℕ → Set where
c1 : ∀ n → ℕ-prop n
c2 : ∀ n → ℕ-prop n
record ℕ-Subset : Set where
field
value : ℕ
prop : ℕ-prop value
突然間,該子集的元素數與原始類型相比增加了兩倍。我同意這個例子有點做作,但是可以想象,你在集合上有一個子集關係(來自集合論的集合)。這樣的事情其實是相當可能的:
sub₁ : {1, 2} ⊆ {1, 2, 3, 4}
sub₁ = drop 3 (drop 4 same)
sub₂ : {1, 2} ⊆ {1, 2, 3, 4}
sub₂ = drop 4 (drop 3 same)
通常的方法解決這個問題是使用不相關的參數:
record Subset : Set where
field
value : A
.prop : P value
這意味着Subset
類型的兩個值是相等的,如果他們有value
,prop
字段是無關到平等。事實上:
record Subset : Set where
constructor sub
field
value : A
.prop : P value
prop-irr : ∀ {a b} {p : P a} {q : P b} →
a ≡ b → sub a p ≡ sub b q
prop-irr refl = refl
但是,這更多的是一種指導,因爲你表示不存在這個問題。這是因爲在模式匹配阿格達的實施意味着公理ķ:
K : ∀ {a p} {A : Set a} (x : A) (P : x ≡ x → Set p) (h : x ≡ x) →
P refl → P h
K x P refl p = p
那麼,這並不能告訴你太多。幸運的是,還有另一種屬性,它等同於公理K:
uip : ∀ {a} {A : Set a} {x y : A} (p q : x ≡ y) → p ≡ q
uip refl refl = refl
這告訴我們,只有一個辦法,其中兩個元素可以是相等的,即refl
(uip
意味着獨特身份的樣張)。
這意味着當您使用命題相等來創建子集時,您將獲得一個真正的子集。
讓我們更加明確:
isSingleton : ∀ {ℓ} → Set ℓ → Set _
isSingleton A = Σ[ x ∈ A ] (∀ y → x ≡ y)
isSingleton A
表達了A
僅包含一個元素,最多propositonal平等的事實。事實上,Singleton x
是一個單:
Singleton-isSingleton : ∀ {ℓ} {A : Set ℓ} (x : A) →
isSingleton (Singleton x)
Singleton-isSingleton x = (x , refl) , λ {(.x , refl) → refl}
有趣的是,如果你把{-# OPTIONS --without-K #-}
編譯你的文件的頂部,這也適用無公理K.,它仍然會編譯。