У меня есть эта программа Agda:
data ℕ⁺ : ℕ → Set where
one : ℕ⁺ (suc zero)
suc⁺ : {n : ℕ} → ℕ⁺ (suc n)
lemma : ∀ (m n : ℕ) → m ≡ suc n → ℕ⁺ m
lemma m zero p = one
lemma m (suc n) p = suc⁺ {suc n}
Проблема в предпоследней строке: она жалуется, что one
не является ℕ⁺ m
, однако у меня есть p
, чтобы доказать, что они на самом деле есть.
Как я могу это сделать? Я знаю, как это сделать, если то, что я хотел доказать, на самом деле было равенством (ну, просто передайте p
в этом случае), но я не знаю, как использовать p
для преобразования общего ℕ⁺ m
в ℕ⁺ (suc zero)
.
Тип равенства _≡_
не имеет особого значения в Агде. Для Agda one
выглядит как значение типа ℕ⁺ (suc zero)
, и ему нужен ℕ⁺ m
. transport
должно помочь.
transport : forall {A : Set} {B : A → Set} {x y : A} → x ≡ y → B x → B y
transport refl bx = bx
comm : forall {A : Set} {x y : A} → x ≡ y → y ≡ x
comm {x = x} p = transport {B = _≡ x} p refl
lemma : ∀ (m n : ℕ) → m ≡ suc n → ℕ⁺ m
lemma _ _ p = transport {B = \k → ℕ⁺ k} (comm p) suc⁺
(Здесь я убрал one
, так как он не нужен.)
(В стандартной библиотеке transport
называется subst
, а comm
называется sym
. Оба определены в Relation.Binary.PropositionalEquality
.)
Если вы сопоставите шаблон на p
, он уточнит m
в .(suc n)
:
lemma : ∀ (m n : ℕ) → m ≡ suc n → ℕ⁺ m
lemma .(suc n) zero refl = one
lemma .(suc n) (suc n) refl = suc⁺
(отказ от ответственности: это не с точки зрения HoTT/CTT; вероятно, это не сработает без аксиома К.)
Спасибо! Я догадался об этой подписи, но не знал, что ее определение настолько простое.