如何定义单例集?

时间:2014-01-25 14:39:58

标签: agda

假设我有一个值x : A,我想定义一个只包含x的集合。

这就是我的尝试:

open import Data.Product
open import Relation.Binary.PropositionalEquality

-- Singleton x is the set that only contains x. Its values are tuples containing
-- a value of type A and a proof that this value is equal to x.
Singleton : ∀ {ℓ} {A : Set ℓ} → (x : A) → Set ℓ
Singleton {A = A} x = Σ[ y ∈ A ] (y ≡ x)

-- injection
singleton : ∀ {ℓ} {A : Set ℓ} → (x : A) → Singleton x
singleton x = x , refl

-- projection
fromSingleton : ∀ {ℓ} {A : Set ℓ} {x : A} → Singleton x → A
fromSingleton s = proj₁ s

有更好的方法吗?


我想要这个的例子:如果你在某个集合A上有一个幺半群,那么你可以形成一个以A作为唯一对象的类别。要在Agda中表达,您需要一种方法来编写“仅包含A的集合”。

3 个答案:

答案 0 :(得分:4)

我认为这是一个非常好的方法。通常,当您想要创建类型的“子集”时,它看起来像:

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

然而,这更像是一个指导原则,因为你的代表不会遇到这个问题。这是因为在Agda中实现模式匹配意味着 axiom K

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

这告诉我们,只有一种方法可以使两个元素相等,即refluip表示身份证明的唯一性)。

这意味着当你使用命题相等来制作一个子集时,你就得到了一个真正的子集。


让我们明确指出:

isSingleton : ∀ {ℓ} → Set ℓ → Set _
isSingleton A = Σ[ x ∈ A ] (∀ y → x ≡ y)

isSingleton A表示A只包含一个元素,直到提议性相等。事实上,Singleton x是一个单身人士:

Singleton-isSingleton : ∀ {ℓ} {A : Set ℓ} (x : A) →
  isSingleton (Singleton x)
Singleton-isSingleton x = (x , refl) , λ {(.x , refl) → refl}

有趣的是,这也可以在没有公理K的情况下工作。如果你将{-# OPTIONS --without-K #-} pragma放在文件的顶部,它仍然会编译。

答案 1 :(得分:1)

您可以定义没有投影的记录:

record Singleton {α} {A : Set α} (x : A) : Set α where

fromSingleton : ∀ {α} {A : Set α} {x : A} -> Singleton x -> A
fromSingleton {x = x} _ = x

singleton : ∀ {α} {A : Set α} -> (x : A) -> Singleton x
singleton _ = _

或等同

record Singleton {α} {A : Set α} (x : A) : Set α where

  fromSingleton = x
open Singleton public

singleton : ∀ {α} {A : Set α} -> (x : A) -> Singleton x
singleton _ = _

现在您可以像这样使用它:

open import Relation.Binary.PropositionalEquality
open import Data.Nat

f : Singleton 5 -> ℕ
f x = fromSingleton x

test : f (singleton 5) ≡ 5
test = refl

test' : f _ ≡ 5
test' = refl

这被拒绝了:

fail : f (singleton 4) ≡ 4
fail = ?

错误:

4 != 5 of type ℕ
when checking that the expression singleton 4 has type Singleton 5

答案 2 :(得分:1)

可以将其定义为indexed datatype

data Singleton {ℓ : _} {A : Set ℓ} : A -> Set where
  singleton : (a : A) -> Singleton a

这类似于命题平等a ≡ b如何被两个特定元素ab编入索引,或者Vector X n如何被特定n ∈ ℕ编入索引