---
title: "选择原理"
module: Base.Choice
lang: zh
site: "Bedrock"
description: "选择原理"
stage: "基础"
reading_order: 5
canonical: https://bedrock.institute/zh/Base.Choice.html
html: Base.Choice.html
agda_source: https://github.com/BedrockInstitute/Bedrock/blob/main/src/Base/Choice.lagda.md
prerequisites: [Base.Prelude, Base.Classical]
routes: [common-foundations]
translations: [https://bedrock.institute/en/Base.Choice.md, https://bedrock.institute/ja/Base.Choice.md]
agent_guide: https://bedrock.institute/llms.txt
license: "CC-BY-NC-SA-4.0"
---


```agda
{-# OPTIONS --cubical --safe --guardedness #-}
module Base.Choice where
```

# 选择原理

```agda
open import Base.Prelude
open import Base.Classical using ( LEM )
```

知道一族类型中的每个类型都有元素，与拥有一个同时为它们选取元素的函数，是不同的两件事。命题截断把区别表达得很准确：`∥ B x ∥₁` 断言某个指标处有元素，`∥ ((x : X) → B x) ∥₁` 则断言整个选择函数存在。本章先陈述以 h-集合为指标、取值也为 h-集合的选择原理，再证明高一宇宙层级的选择原理蕴含当前层级的选择原理，最后证明选择原理蕴含排中律。

## 原理

对于族 `B : X → Type ℓ`，值得区分三种数据。如果每个 `B x` 的元素已经作为 `x` 的函数给出，那么这个函数本身就是选择函数。额外的原理针对的是较弱的、经过截断的输入。

| 陈述 | 给出的内容 |
| --- | --- |
| `(x : X) → B x` | 可以求值的选择函数 |
| `(x : X) → ∥ B x ∥₁` | 逐个指标处的存在 |
| `∥ ((x : X) → B x) ∥₁` | 一个同时处理全部指标的函数的存在 |
: 三种选择数据：可求值的函数、逐点的仅仅存在，以及整个函数的仅仅存在

**定义** (`SetChoice`) 层级 `ℓ` 上的集合值族的选择断言：对每个 h-集合 `X : Type ℓ` 及每个<span class="prose-annotation-target">取值 `B x` 都是 h-集合的族 `B : X → Type ℓ`</span><aside class="prose-annotation-note">这是 HoTT 教材采用的集合值族版本。允许任意取值的版本更强：它还蕴含每个类型都仅仅存在一个来自 h-集合的满射。本书的两处取用都不需要这项额外强度。</aside>，上表的第二行蕴含第三行。

```agda
SetChoice : ∀ ℓ → Type (ℓ-suc ℓ)
SetChoice ℓ = (X : Type ℓ) → isSet X → (B : X → Type ℓ)
            → ((x : X) → isSet (B x))
            → ((x : X) → ∥ B x ∥₁) → ∥ ((x : X) → B x) ∥₁
```

截断移到了依值函数类型之外，但并没有消失。因此，假设 `sc : SetChoice ℓ` 给出的是选择函数的仅仅存在。若要用 `rec₁` 利用这一存在，目标就必须是命题。由于量化了 `Type ℓ`，整条原理位于 `Type (ℓ-suc ℓ)`。

**引理** (`lowerSetChoice`) 高一个宇宙层级的选择蕴含原层级的选择。

```agda
lowerSetChoice : ∀ {ℓ} → SetChoice (ℓ-suc ℓ) → SetChoice ℓ
```

**证明** 给定 `sc : SetChoice (ℓ-suc ℓ)`。为证明 `SetChoice ℓ`，即须证明：对任意给定的 h-集合指标 `X` 和 h-集合值族 `B`，由前提 `inh : (x : X) → ∥ B x ∥₁` 得到 `∥ ((x : X) → B x) ∥₁`。`inh` 取自 *inhabited*，只提供逐点的仅仅存在，而未选定具体元素。由于 `sc` 处理的是高一层级的族，我们用 `Lift` 将这道选择问题移到它能够处理的层级。下图展示从原层上行、应用选择原理、再返回原层的过程。

<figure class="book-diagram choice-lift-figure" id="fig-lower-set-choice" aria-describedby="fig-lower-set-choice-caption">
<div class="diagram-framed">
<div class="choice-lift-flow">
<div class="choice-lift-legend">

$$\widehat B\,\hat x := \operatorname{Lift}(B(\operatorname{lower}\,\hat x))$$

</div>
<div class="diagram-space choice-lift-source">

$$(x:X)\to\|B\,x\|_1$$

</div>
<div class="choice-lift-step choice-lift-up"><span class="choice-lift-wide-arrow" aria-hidden="true">$\uparrow$</span><span class="choice-lift-narrow-arrow" aria-hidden="true">$\downarrow$</span> $\operatorname{map}_1\,\operatorname{lift}$</div>
<div class="diagram-space choice-lift-input">

$$(\hat x:\operatorname{Lift}X)\to\|\widehat B\,\hat x\|_1$$

</div>
<div class="choice-lift-step choice-lift-choice"><span class="choice-lift-wide-arrow" aria-hidden="true">$\rightarrow$</span><span class="choice-lift-narrow-arrow" aria-hidden="true">$\downarrow$</span> $\operatorname{sc}$</div>
<div class="diagram-space choice-lift-output">

$$\|(\hat x:\operatorname{Lift}X)\to\widehat B\,\hat x\|_1$$

</div>
<div class="choice-lift-step choice-lift-down"><span aria-hidden="true">$\downarrow$</span> $\operatorname{map}_1$</div>
<div class="diagram-space choice-lift-target">

$$\|(x:X)\to B\,x\|_1$$

</div>
</div>
</div>
<figcaption id="fig-lower-set-choice-caption">

高层级的选择如何导出原层级的选择：提升输入，应用选择原理，再将结果送回原层级

</figcaption>
</figure>

要在高一层应用 `sc`，还须证明 lift 后的指标与族的每个取值都是 h-集合。下表着重展示这些 h-集合性证明如何由原层级已有的性质得到，同时列出其余实参的对应。

| 层级 `ℓ` | 层级 `ℓ-suc ℓ` |
| --- | --- |
| `X` | `Lift X` |
| `setX` | `isOfHLevelLift 2 setX` |
| `B x` | `Lift (B (lower x̂))`，其中 `x̂ : Lift X` |
| `setB x` | `isOfHLevelLift 2 (setB (lower x̂))` |
| `inh x` | `map₁ lift (inh (lower x̂))` |
: 高层级的实参由原层级已有的数据构造

下面的 Agda 代码把图示与表格接在一起：表格右列给出中间选择步骤所需的输入，代码的嵌套结构则对应图中的上行、应用选择、返回原层。整个表达式的类型正是图底部的目标。

```agda
lowerSetChoice sc X setX B setB inh = map₁ (λ f x → lower (f (lift x)))
         (sc (Lift X) (isOfHLevelLift 2 setX)
             (λ x̂ → Lift (B (lower x̂)))
             (λ x̂ → isOfHLevelLift 2 (setB (lower x̂)))
             (λ x̂ → map₁ lift (inh (lower x̂))))
```

## Diaconescu 定理

选取代表元为什么能判定任意命题？上一章在取得判定之后，用布尔值编码命题。这里反过来：先由命题构造商，无须判定它，再由选择提供布尔值，最后比较这些值而得到判定。

私有子模块 `Diaconescu` 先固定任意 `P : hProp ℓ`，构造相应的商及辅助结果。最后的定理利用这些结果，把选择转化为对 `P` 的判定。

<details open class="submodule-fold">
<summary class="submodule-fold-heading">

```agda
private module Diaconescu {ℓ} (P : hProp ℓ) where
```

</summary>
<div class="submodule-fold-content">

先引入下文要用的集合商与二元关系工具。给定类型 `A` 与关系 `R`，商 `A / R` 中有点 `[ a ]`；`R a b` 的证明给出路径 `[ a ] ≡ [ b ]`，`squash/` 则保证结果是 h-集合。`BinaryRelation` 提供随后验证关系定律所用的表述。这里引入的同构定理 `isEquivRel→effectiveIso` 说：若 `R` 是取值于命题的等价关系，则商中 `[ a ] ≡ [ b ]` 的路径与 `R a b` 的证明同构。由此可以通过原关系理解商中两点的相等。

```agda
  open import Cubical.HITs.SetQuotients
    using ( _/_; [_]; squash/; []surjective; isEquivRel→effectiveIso )
  open import Cubical.Relation.Binary.Base using ( module BinaryRelation )
```

**构造** (`_~_`) 在 `Bool` 上定义关系，对角格始终有元素，非对角格则是 `⟨ P ⟩`。这样，两个不同的布尔值是否相关就由 `P` 控制。

```agda
  _~_ : Bool → Bool → Type ℓ
  true  ~ true  = ⊤*
  false ~ false = ⊤*
  _     ~ _     = ⟨ P ⟩
```

**构造** (`Glued`) 按这个关系取商。我们希望用 `P` 的证明来刻画两个特殊点 `[ true ]` 与 `[ false ]` 之间的路径。只要验证 `_~_` 是取值于命题的等价关系，就能应用同构定理。

```agda
  Glued : Type ℓ
  Glued = Bool / _~_
```

**引理** (`~-prop`) 对于刚构造的商，同构定理要求关系取值于命题并满足等价律。验证只需查看 `_~_` 的定义：对角格是命题 `⊤*`，非对角格是 `P` 所打包的命题。

```agda
  ~-prop : BinaryRelation.isPropValued _~_
  ~-prop true  true  = isProp⊤*
  ~-prop false false = isProp⊤*
  ~-prop true  false = ⟨ P ⟩isProp
  ~-prop false true  = ⟨ P ⟩isProp
```

**引理** (`~-refl`) 对角格有元素 `tt*`，这就证明了自反性。

```agda
  ~-refl : (a : Bool) → a ~ a
  ~-refl true  = tt*
  ~-refl false = tt*
```

**引理** (`~-sym`) 交换输入不改变格中的类型。对角格返回 `tt*`，非对角格复用所给的 `P` 的证明。

```agda
  ~-sym : (a b : Bool) → a ~ b → b ~ a
  ~-sym true  true  _ = tt*
  ~-sym false false _ = tt*
  ~-sym true  false p = p
  ~-sym false true  p = p
```

**引理** (`~-trans`) 传递性先看两端 `a` 与 `c`。两端相同时，`tt*` 证明 `a ~ c`。

```agda
  ~-trans : (a b c : Bool) → a ~ b → b ~ c → a ~ c
  ~-trans true  _     true  _ _ = tt*
  ~-trans false _     false _ _ = tt*
```

两端不同时，中间的布尔值必等于其中一端，因而两个前提中已有一个是 `P` 的证明，返回它即可。

```agda
  ~-trans true  false false p _ = p
  ~-trans false true  true  p _ = p
  ~-trans true  true  false _ p = p
  ~-trans false false true  _ p = p
```

**引理** (`~-equivRel`) 三条定律组成同构定理所需的等价关系记录。

```agda
  ~-equivRel : BinaryRelation.isEquivRel _~_
  ~-equivRel = BinaryRelation.equivRel ~-refl ~-sym ~-trans
```

**引理** (`quotientPath≃P`) 验证这些定律后，就能应用同构定理。它给出 `[ true ]` 与 `[ false ]` 之间的路径类型与 `true ~ false` 的同构，而后者按定义就是 `⟨ P ⟩`。再用 `isoToEquiv` 将这个同构转为下面的类型等价。

```agda
  quotientPath≃P : ([ true ] ≡ [ false ]) ≃ ⟨ P ⟩
  quotientPath≃P = isoToEquiv
    (isEquivRel→effectiveIso ~-prop ~-equivRel true false)
```

图中的 $e$ 简记 `quotientPath≃P`：正向映射把路径变为 `P` 的证明，逆向映射把证明变为路径。下面分别展示有 `P` 的证明或反驳时的情形，并不预先断定我们已经取得了其中一种。

<figure class="book-diagram type-comparison path-figure" id="fig-choice-gluing" aria-describedby="fig-choice-gluing-caption">
<div class="diagram-framed">

$$([\mathsf{true}] \equiv [\mathsf{false}]) \simeq \langle P\rangle$$

<div class="type-comparison-panels">
<div class="type-comparison-panel">

$$p : \langle P\rangle$$

<div class="path-stage diagram-compact-stage" style="aspect-ratio:300/190">
<svg viewBox="0 0 300 190" aria-hidden="true" focusable="false">
<rect class="diagram-space-shape" x="12" y="12" width="276" height="166"/>
<path class="diagram-path" d="M 70 115 Q 150 55 230 115"/>
<circle class="diagram-point" cx="70" cy="115" r="4"/><circle class="diagram-point" cx="230" cy="115" r="4"/>
</svg>
<span class="path-label" style="left:50%;top:20%">$\mathsf{Glued}$</span>
<span class="path-label" style="left:23.33%;top:77%">$[\mathsf{true}]$</span>
<span class="path-label" style="left:76.67%;top:77%">$[\mathsf{false}]$</span>
<span class="path-label" style="left:50%;top:35%">$e^{-1}(p)$</span>
</div>
</div>
<div class="type-comparison-panel">

$$n : \neg\langle P\rangle$$

<div class="path-stage diagram-compact-stage" style="aspect-ratio:300/190">
<svg viewBox="0 0 300 190" aria-hidden="true" focusable="false">
<rect class="diagram-space-shape" x="12" y="12" width="276" height="166"/>
<circle class="diagram-point" cx="70" cy="115" r="4"/><circle class="diagram-point" cx="230" cy="115" r="4"/>
</svg>
<span class="path-label" style="left:50%;top:20%">$\mathsf{Glued}$</span>
<span class="path-label" style="left:23.33%;top:77%">$[\mathsf{true}]$</span>
<span class="path-label" style="left:76.67%;top:77%">$[\mathsf{false}]$</span>
</div>
</div>
</div>
</div>
<figcaption id="fig-choice-gluing-caption">

左图通过 $e$ 的逆映射得到路径；右图中若存在连接路径，$e$ 就会把它变为与 `n` 矛盾的证明

</figcaption>
</figure>

**构造** (`Pick`) 接下来要使 `Glued` 中的相等变得可判定。点 `x : Glued` 的代表元由布尔值 `b` 与路径 `[ b ] ≡ x` 组成。它们的依值对类型 `Pick x` 恰是商映射 `[_] : Bool → Glued` 在 `x` 上的一束纤维。第二分量证明这个布尔值代表的是指定的商类。

```agda
  Pick : Glued → Type ℓ
  Pick x = Σ[ b ∶ Bool ] ([ b ] ≡ x)
```

**引理** (`pickIsSet`) 族 `Pick` 取值于 h-集合。这里将 `isSetClass` 用于 h-集合 `Bool`：固定布尔值后的第二分量是 h-集合 `Glued` 中的路径，因而是命题。

```agda
  pickIsSet : (x : Glued) → isSet (Pick x)
  pickIsSet x = isSetClass isSetBool (λ b → squash/ [ b ] x)
    where
      open import Cubical.Data.Bool.Properties using ( isSetBool )
```

**引理** (`pickable`) `[]surjective` 保证每个商点都有代表元，其存在性以命题截断表达。

```agda
  pickable : (x : Glued) → ∥ Pick x ∥₁
  pickable = []surjective
```

**引理** (`merePicker`) 以 `Glued` 为指标类型，`squash/` 为其 h-集合性证书，`Pick` 为所选的族，`pickIsSet` 为逐点的 h-集合性证书，应用 `sc`。这是针对 `P` 的论证中唯一一次使用选择；得到的是为每个商点选取代表元的函数的仅仅存在。

```agda
  merePicker : SetChoice ℓ → ∥ ((x : Glued) → Pick x) ∥₁
  merePicker sc = sc Glued squash/ Pick pickIsSet pickable
```

接下来暂设已取得实际函数 `g : (x : Glued) → Pick x`，而不只是知道它仅仅存在。里面的带参数子模块将 `g` 固定为共同参数；`_` 表示模块本身无须命名。离开子模块后，使用这些私有辅助定义仍须传入 `g`，所以这里并未凭空假设全局选择函数。稍后再消去截断，去掉这个暂设而得到判定。

<details open class="submodule-fold">
<summary class="submodule-fold-heading">

```agda
  private module _ (g : (x : Glued) → Pick x) where
```

</summary>
<div class="submodule-fold-content">

**构造** (`b₀` `b₁`)

- `b₀` 是 `g` 在 `[ true ]` 处选出的布尔值。
- `b₁` 是 `g` 在 `[ false ]` 处选出的布尔值。

```agda
    b₀ : Bool
    b₀ = g [ true ] .fst

    b₁ : Bool
    b₁ = g [ false ] .fst
```

**构造** (`agree→P` `P→agree`)

- `agree→P` 若有 `q : b₀ ≡ b₁`，`g` 中保存的证书就把这条相等接回商中。图中的 $s_0$、$s_1$ 分别简记 `g [ true ] .snd` 与 `g [ false ] .snd`。第一份证书从 `[ b₀ ]` 到 `[ true ]`，因此复合时要先用 `sym` 反向。
- `P→agree` 反过来，证明 `p : ⟨ P ⟩` 经逆映射给出路径 `invEq quotientPath≃P p`，即图中的 $e^{-1}(p)$。普通函数 `λ x → g x .fst` 把它送到 `b₀ ≡ b₁`。取第一分量后，值域是固定的 `Bool`，因此只需使用 `cong`。

```agda
    agree→P : b₀ ≡ b₁ → ⟨ P ⟩
    agree→P q = equivFun quotientPath≃P
      (sym (g [ true ] .snd) ∙ cong [_] q ∙ g [ false ] .snd)

    P→agree : ⟨ P ⟩ → b₀ ≡ b₁
    P→agree p = cong (λ x → g x .fst) (invEq quotientPath≃P p)
```

</div>
</details>

<figure class="book-diagram type-comparison path-figure" id="fig-choice-agreement" aria-describedby="fig-choice-agreement-caption">
<div class="diagram-framed">
<div class="type-comparison-panels">
<div class="type-comparison-panel">

$$q:b_0\equiv b_1$$

<div class="path-stage diagram-compact-stage" style="aspect-ratio:300/370">
<svg viewBox="0 0 300 370" aria-hidden="true" focusable="false">
<rect class="diagram-space-shape" x="12" y="10" width="276" height="350"/>
<path class="diagram-path" d="M 75 72 L 75 152"/>
<path class="diagram-path" d="M 75 152 L 75 232"/>
<path class="diagram-path" d="M 75 232 L 75 312"/>
<circle class="diagram-point" cx="75" cy="72" r="4"/>
<circle class="diagram-point" cx="75" cy="152" r="4"/>
<circle class="diagram-point" cx="75" cy="232" r="4"/>
<circle class="diagram-point" cx="75" cy="312" r="4"/>

</svg>
<span class="path-label" style="left:50%;top:9%">$\mathsf{Glued}$</span>
<span class="path-label" style="left:42%;top:19.46%">$[\mathsf{true}]$</span>
<span class="path-label" style="left:42%;top:41.08%">$[b_0]$</span>
<span class="path-label" style="left:42%;top:62.7%">$[b_1]$</span>
<span class="path-label" style="left:42%;top:84.32%">$[\mathsf{false}]$</span>
<span class="path-label" style="left:57%;top:30.27%">$\mathsf{sym}(s_0)$</span>
<span class="path-label" style="left:58%;top:51.89%">$\mathsf{cong}\,[{-}]\,q$</span>
<span class="path-label" style="left:57%;top:73.51%">$s_1$</span>
</div>
</div>
<div class="type-comparison-panel">

$$p:\langle P\rangle$$

<div class="path-stage diagram-compact-stage" style="aspect-ratio:300/370">
<svg viewBox="0 0 300 370" aria-hidden="true" focusable="false">
<rect class="diagram-space-shape" x="12" y="10" width="276" height="145"/>
<rect class="diagram-space-shape" x="12" y="215" width="276" height="145"/>
<path class="diagram-path" d="M 65 94 Q 150 48 235 94"/>
<path class="diagram-path" d="M 65 300 Q 150 254 235 300"/>
<circle class="diagram-point" cx="65" cy="94" r="4"/><circle class="diagram-point" cx="65" cy="300" r="4"/><path class="diagram-map-line" d="M 65 145 L 65 232"/><path class="diagram-map-tip" d="M 60 224 L 65 232 L 70 224"/>
<circle class="diagram-point" cx="235" cy="94" r="4"/><circle class="diagram-point" cx="235" cy="300" r="4"/><path class="diagram-map-line" d="M 235 145 L 235 232"/><path class="diagram-map-tip" d="M 230 224 L 235 232 L 240 224"/>

</svg>
<span class="path-label" style="left:50%;top:9%">$\mathsf{Glued}$</span>
<span class="path-label" style="left:50%;top:15%">$e^{-1}(p)$</span>
<span class="path-label" style="left:21.67%;top:33%">$[\mathsf{true}]$</span>
<span class="path-label" style="left:78.33%;top:33%">$[\mathsf{false}]$</span>
<span class="path-label" style="left:50%;top:50%">$x\mapsto g(x).\mathsf{fst}$</span>
<span class="path-label" style="left:50%;top:65%">$\mathsf{Bool}$</span>
<span class="path-label" style="left:21.67%;top:90%">$b_0$</span>
<span class="path-label" style="left:78.33%;top:90%">$b_1$</span>
</div>
</div>
</div>
</div>
<figcaption id="fig-choice-agreement-caption">

左图由 $e$ 把复合路径送到 `P` 的证明；右图沿 $e^{-1}(p)$ 读取所选布尔值，得到二者相等

</figcaption>
</figure>

**构造** (`decide`) 给定 `g : (x : Glued) → Pick x`，现在用 `_≟_` 判定选出的两个布尔值是否相等。刚证明的两个私有辅助映射把比较结果转换如下：

| 布尔值的比较 | 对 `P` 的判定 |
| --- | --- |
| `yes q` | `yes (agree→P g q)` |
| `no ne` | `no (λ p → ne (P→agree g p))` |
: 布尔值比较的两种结果分别给出对命题的肯定或否定判定

第二行中，`P` 的证明会迫使两个布尔值相等，而这正是 `ne` 所反驳的。因此得到传给 `mapDec` 的否定方向。

```agda
  decide : ((x : Glued) → Pick x) → Dec ⟨ P ⟩
  decide g = mapDec (agree→P g) (λ ne p → ne (P→agree g p)) (b₀ g ≟ b₁ g)
    where
      open import Cubical.Data.Bool using ( _≟_ )
```

</div>
</details>

[《基础词汇》中经由截断的分解](Base.Prelude.html#fig-truncation-rec)，在这里有了一个具体实例。图中的 $G$ 简记类型 `(x : Glued) → Pick x`。`decide` 以实际函数为输入。由于 `isPropDec ⟨ P ⟩isProp` 证明目标 `Dec ⟨ P ⟩` 是命题，`rec₁ (isPropDec ⟨ P ⟩isProp) decide` 也能接收函数的仅仅存在。

<figure class="book-diagram type-comparison" id="fig-choice-truncation" aria-describedby="fig-choice-truncation-caption">
<div class="diagram-framed type-comparison-panel">

<div class="factorization-stage">
<svg viewBox="0 0 500 230" aria-hidden="true" focusable="false">
<path class="diagram-map-line" d="M88 50 H315"/>
<path class="diagram-map-tip" d="M306 45 L315 50 L306 55"/>
<path class="diagram-map-line" d="M358 76 V160"/>
<path class="diagram-map-tip" d="M353 151 L358 160 L363 151"/>
<path class="diagram-map-line" d="M72 74 L315 177"/>
<path class="diagram-map-tip" d="M303 179 L315 177 L308 167"/>
</svg>
<span class="factorization-label factorization-source">$G$</span>
<span class="factorization-label factorization-truncated">$\|G\|_1$</span>
<span class="factorization-label factorization-target">$\mathsf{Dec}\,\langle P\rangle$</span>
<span class="factorization-label factorization-top-map">$|{-}|_1$</span>
<span class="factorization-label factorization-long-map">$\mathsf{decide}$</span>
<span class="factorization-label factorization-right-map">$\mathsf{rec}_1\,\cdots$</span>
</div>

</div>
<figcaption id="fig-choice-truncation-caption">

选择提供 $\|G\|_1$ 的元素，右侧函数由此返回 `P` 的判定

</figcaption>
</figure>

**定理 (Diaconescu)** (`SetChoice→LEM`) 集合值族的选择蕴含同一宇宙层级上的排中律。

**证明** 把 `rec₁ (isPropDec ⟨ P ⟩isProp) decide` 应用于 `merePicker sc`。由于 `P` 任意，得到的正是 `LEM ℓ`。

```agda
SetChoice→LEM : ∀ {ℓ} → SetChoice ℓ → LEM ℓ
SetChoice→LEM sc P = rec₁ (isPropDec ⟨ P ⟩isProp) decide (merePicker sc)
  where open Diaconescu P
```

证明完成后，再回看一个看似直接的做法：为什么不在 `[ true ]` 处选 `true`，在 `[ false ]` 处选 `false`？下图从逐点找到代表元，经 `SetChoice` 走到商上的同一个函数。先假设 `P` 成立，沿同一个商点的两种写法之间的路径看一看。

<figure class="book-diagram choice-contrast-figure" id="fig-choice-decision" aria-describedby="fig-choice-decision-caption">
<div class="diagram-framed choice-contrast-frame">
<div class="choice-contrast-premise">

<span>若 $P$ 成立，商中有路径</span>

<strong>$p:[\mathsf{true}]\equiv[\mathsf{false}]$</strong>
</div>
<div class="choice-contrast-columns">
<section class="diagram-panel choice-contrast-panel choice-contrast-pointwise">

<h4>逐点分别存在</h4>

<div class="choice-contrast-type">$(x : \mathsf{Glued})\to\|\mathsf{Pick}\,x\|_1$</div>

<p>即使暂时分别找到代表元：</p>

<div class="choice-contrast-picks">
<div class="choice-contrast-pick"><span>$[\mathsf{true}]$</span><span class="choice-contrast-correspondence" aria-hidden="true"></span><strong>$\mathsf{true}$</strong></div>
<div class="choice-contrast-pick"><span>$[\mathsf{false}]$</span><span class="choice-contrast-correspondence" aria-hidden="true"></span><strong>$\mathsf{false}$</strong></div>
</div>
<div class="choice-contrast-verdict choice-contrast-insufficient">

<span>当 $P$ 成立时，两种写法是同一个商点。分别找到不同代表元并不矛盾；若按写法指定输出，同一个输入却会同时得到 true 和 false，因而不是商上的函数。</span>

</div>
</section>
<div class="choice-contrast-choice-bridge diagram-implication">
<span>$\mathsf{SetChoice}$</span>
<span class="choice-contrast-choice-arrow" aria-hidden="true"></span>

<span class="choice-contrast-choice-note">仅仅存在一个统一的函数</span>

</div>
<section class="diagram-panel choice-contrast-panel choice-contrast-global">

<h4>商上的同一个函数</h4>

<div class="choice-contrast-type">$\|((x : \mathsf{Glued})\to\mathsf{Pick}\,x)\|_1$</div>

<p>在剩余的外层截断内部，看同一个函数 $g$：</p>

<div class="choice-contrast-map">
<div class="choice-contrast-map-name"><span>$f:\mathsf{Glued}\to\mathsf{Bool}$</span><span>$f(x)=(g\,x).\mathsf{fst}$</span></div>
<div class="path-stage choice-contrast-path-stage" style="aspect-ratio:360/240">
<svg viewBox="0 0 360 240" aria-hidden="true" focusable="false">
<path class="diagram-path" d="M55 60 Q180 5 305 60 M55 185 Q180 130 305 185"/>
<path class="diagram-map-line" d="M55 72 V165 M305 72 V165"/>
<path class="diagram-map-tip" d="M51 158 L55 165 L59 158 M301 158 L305 165 L309 158"/>
<circle class="diagram-point" cx="55" cy="60" r="4"/><circle class="diagram-point" cx="305" cy="60" r="4"/>
<circle class="diagram-point" cx="55" cy="185" r="4"/><circle class="diagram-point" cx="305" cy="185" r="4"/>
</svg>
<span class="path-label" style="left:15.2778%;top:15.4167%">$[\mathsf{true}]$</span>
<span class="path-label" style="left:84.7222%;top:15.4167%">$[\mathsf{false}]$</span>
<span class="path-label" style="left:50%;top:6.25%">$p$</span>
<span class="path-label" style="left:10.8333%;top:48.75%">$f$</span>
<span class="path-label" style="left:89.4444%;top:48.75%">$f$</span>
<span class="path-label" style="left:15.2778%;top:90%">$b_0$</span>
<span class="path-label" style="left:84.7222%;top:90%">$b_1$</span>
<span class="path-label" style="left:50%;top:56.25%">$\operatorname{cong}\,f\,p$</span>
</div>
</div>
<div class="choice-contrast-verdict choice-contrast-coherent">
<div class="choice-contrast-equivalence">$b_0\equiv b_1\quad\Longleftrightarrow\quad P$</div>

<span>代表元证书给出反向蕴含；比较 $b_0$ 与 $b_1$ 就能判定 $P$。</span>

</div>
</section>
</div>
</div>
<figcaption id="fig-choice-decision-caption">

同一个函数把商点间的路径送成布尔输出间的路径；判定是命题，因此可以消去外层截断

</figcaption>
</figure>

## 小结

本章针对 h-集合指标与 h-集合值族陈述了 `SetChoice ℓ`：从逐点的仅仅存在，得到整个选择函数的仅仅存在。`lowerSetChoice` 证明 `SetChoice (ℓ-suc ℓ)` 蕴含 `SetChoice ℓ`。为证明 `SetChoice→LEM`，我们把命题 `P` 编码为两个商点的相等；选择给出布尔代表元，比较它们便可判定 `P`。由于 `Dec ⟨ P ⟩` 是命题，`rec₁` 允许消去截断。因此，`SetChoice ℓ` 蕴含 `LEM ℓ`。
