{-# OPTIONS --cubical --guardedness #-}
module Padova2025-zh-TW.Cubical.FirstSteps where
第一步#
open import Cubical.Foundations.Prelude
open import Padova2025-zh-TW.ProgrammingBasics.Naturals.Base
open import Padova2025-zh-TW.ProgrammingBasics.Naturals.Arithmetic
open import Padova2025-zh-TW.ProvingBasics.Negation
open import Padova2025-zh-TW.ProvingBasics.Termination.Gas using (𝟙; tt)
待補:適當的簡介。把各種型別的大雜燴拆出來。
無序對#
data UnorderedPair (A : Set) : Set where
pair : (x y : A) → UnorderedPair A
swap : (x y : A) → pair x y ≡ pair y x
關於相等的一般事項#
refl' : {X : Set} {a : X} → a ≡ a
refl' {a = a} = λ i → a
symm' : {X : Set} {a b : X} → a ≡ b → b ≡ a
symm' p = λ i → p (~ i)
習題 1
cong'cong' : {X Y : Set} {a b : X} → (f : X → Y) → a ≡ b → f a ≡ f b
cong' f p = {!!}
你的解答
習題 2
funextfunext : {A B : Set} {f g : A → B} → ((x : A) → f x ≡ g x) → f ≡ g
funext = {!!}
你的解答
驗證遞移性比較困難。我們就直接使用 cubical 標準函式庫中的函數:
trans' : {X : Set} {a b c : X} → a ≡ b → b ≡ c → a ≡ c
trans' p q = p ∙ q
儘管 cubical Agda 以激進的方式重新想像了同一性,最終原生的相等型別與我們一直在使用的歸納定義的型別是一致的:
open import Padova2025-zh-TW.ProvingBasics.Equality.Base renaming (_≡_ to _≡ᵢ_)
習題 3
≡ᵢ→≡≡ᵢ→≡ : {X : Set} {a b : X} → a ≡ᵢ b → a ≡ b
≡ᵢ→≡ = {!!}
你的解答
≡→≡ᵢ : {X : Set} {a b : X} → a ≡ b → a ≡ᵢ b
≡→≡ᵢ = J (λ b q → _ ≡ᵢ b) _≡ᵢ_.refl
習題:無序對的和#
open import Padova2025-zh-TW.ProvingBasics.Equality.NaturalNumbers
習題 4
sum-pairsum-pair : UnorderedPair ℕ → ℕ
sum-pair = {!!}
你的解答
整數#
infixl 5 _⊝_
data ℤ : Set where
_⊝_ : (a b : ℕ) → ℤ
cancel : (a b : ℕ) → a ⊝ b ≡ succ a ⊝ succ b
定義後繼與前驅函數。
習題 5
succℤsuccℤ : ℤ → ℤ
succℤ (a ⊝ b) = succ a ⊝ b
succℤ (cancel a b i) = {!!}
你的解答
習題 6
predℤpredℤ : ℤ → ℤ
predℤ (a ⊝ b) = a ⊝ succ b
predℤ (cancel a b i) = {!!}
你的解答
習題:一不是零,再訪#
證明一不是零。
習題 7
lemma-nontriviallemma-nontrivial : one ≡ zero → ⊥
lemma-nontrivial = {!!}
你的解答
使用我們先前採用的 _≡_ 的歸納定義時,這需要一個空模式。現在 _≡_ 不再是歸納定義的,而是內建的概念,
我們無法對相等見證做 case split。
取而代之,請這樣進行:
- 定義一個函數
disambig : ℕ → Set,把 zero 映射到 ⊥,把其他一切映射到某個有居民的型別。 - 假設存在一條路徑
zero ≡ succ zero,結合標準函式庫中的transport與disambig:transport : {A B : Set} → A ≡ B → A → B
習題:無序對抽象的穩健性#
證明無序對的抽象不會洩漏,意思是不可能存在一個函數,能取出無序對的第一個分量。
習題 8
lemma-not-leakylemma-not-leaky : (f : UnorderedPair ℕ → ℕ) → ((a b : ℕ) → f (pair a b) ≡ a) → ⊥
lemma-not-leaky = {!!}
你的解答
習題:反轉兩次#
下面這個習題的解答令人愉悅。不需要(也不可能)做 case split:
習題 9
symm-symmsymm-symm : {X : Set} {a b : X} → (p : a ≡ b) → symm' (symm' p) ≡ p
symm-symm = {!!}
參考解答用到: refl'
你的解答
單純命題(Mere propositions)#
在同倫型別論中,一個型別稱為命題,若且唯若它的所有居民都相等。因此,關於一個命題,所有需要知道的就是它是否有居民。
isProp' : Set → Set
isProp' X = (a b : X) → a ≡ b
證明型別 ⊥ 與 𝟙 在這個意義下是命題。
習題 10
⊥-isProp⊥-isProp : isProp' ⊥
⊥-isProp = {!!}
你的解答
習題 11
𝟙-isProp𝟙-isProp : isProp' 𝟙
𝟙-isProp = {!!}
你的解答
證明否定是命題。
習題 12
lemma-negations-are-propslemma-negations-are-props : (X : Set) → isProp' (X → ⊥)
lemma-negations-are-props = {!!}
你的解答
自然數型別的零維性#
在同倫型別論中,一個型別稱為 hset(或簡稱集合),若且唯若它的同一性型別都是單純命題,也就是說, 任意兩個元素之間至多有一條路徑。
isHSet : Set → Set
isHSet X = (a b : X) → isProp' (a ≡ b)
要驗證 ℕ 是 hset,我們需要它的同一性型別的明確描述。對於下面 Code 的定義,會證明型別 a ≡ b 與 Code a b 是等價的。
Code : ℕ → ℕ → Set
Code zero zero = 𝟙
Code zero (succ y) = ⊥
Code (succ x) zero = ⊥
Code (succ x) (succ y) = Code x y
習題 13
fromCodefromCode : (a b : ℕ) → Code a b → a ≡ b
fromCode = {!!}
你的解答
習題 14
Code-reflCode-refl : (a : ℕ) → Code a a
Code-refl = {!!}
你的解答
習題 15
Code-isPropCode-isProp : (a b : ℕ) → isProp' (Code a b)
Code-isProp = {!!}
你的解答
習題 16
toCodetoCode : (a b : ℕ) → a ≡ b → Code a b
toCode a b = J {!!} {!!}
參考解答用到: Code-refl
你的解答
如果 _≡_ 是先前那種歸納定義的相等謂詞,我們會對 p 做 case split,化約到 toCode a a refl 的情況;
這個情況可以用 Code-refl a 解決。
這種 case split 對 _≡_ 並不可用,不過我們可以用標準函式庫的 J 函數來模擬它的效果。
from-to₀ : (a : ℕ) → fromCode a a (toCode a a refl') ≡ refl'
from-to₀ zero = refl'
from-to₀ (succ a) i = cong succ (from-to₀ a i)
from-to : (a b : ℕ) → (p : a ≡ b) → fromCode a b (toCode a b p) ≡ p
from-to a b p = J (λ y q → fromCode a y (toCode a y q) ≡ q) (from-to₀ a) p
習題 17
ℕ-isHSetℕ-isHSet : isHSet ℕ
ℕ-isHSet = {!!}
你的解答