检查推断类型时出现 Agda 错误
Agda error when checking the inferred type
我试图证明两个奇数之和是偶数。
最后一行有什么问题?
data odd : ℕ → Set
data even : ℕ → Set
data even where
ezero :
-------
even zero
esuc : ∀ {n : ℕ}
→ odd n
------
→ even (suc n)
data odd where
osuc : ∀ { n : ℕ }
→ even n
------
→ odd (suc n)
e+e≡e : ∀ {m n : ℕ}
→ even m
→ even n
----
→ even (m + n)
o+e≡o : ∀ {m n : ℕ}
→ odd m
→ even n
------
→ odd (m + n)
e+e≡e ezero en = en
e+e≡e (esuc om) en = esuc (o+e≡o om en)
o+e≡o (osuc em) en = osuc (e+e≡e em en)
o+o≡e : ∀ {m n : ℕ}
→ odd m
→ odd n
------
→ even (m + n)
o+o≡e (osuc em) on = esuc (o+e≡o on em)
我收到这个错误:
➊ - 660 Experiment.agda Agda ∏ unix | 50: 0 Bottom
/Users/max/dev/plfa.github.io/src/plfa/Experiment.agda:52,28-39
n != n₁ of type ℕ
when checking that the inferred type of an application
odd (n + _n_31)
matches the expected type
odd (n₁ + n)
但我觉得这些类型还不错。例如,如果我将右侧替换为?并检查目标,Agda 显示:
Goal: even (suc (n + n₁))
————————————————————————————————————————————————————————————
on : odd n₁
em : even n
n₁ : ℕ (not in scope)
n : ℕ (not in scope
所以我要传递证据 on
n
是奇数,em
m
是偶数。并将这些传递给 o+e≡e
,后者需要这些类型的参数。那我哪里错了?
一般来说,我如何阅读 Agda 的错误消息?变量名后的下标是否有意义?
它告诉你 em
不等于 on
:你想要 odd (m + n)
的证明,但你得到 odd (n + m)
- Agda 看不到加法是可交换的。你应该交换参数。
o+o≡e on (osuc em) = esuc (o+e≡o on em)
这会产生不同的错误。该错误告诉您 Agda 无法计算出 suc (m + n)
等于 m + suc n
,这意味着您需要引入一个确定等式的引理。然后回想一下 transport
(一个将依赖类型 B x
的值沿着等式 x ≡ y
传输到不同依赖类型 B y
的值的函数),这会给你一种从 esuc (o+e≡o on em)
构造的值中获取所需类型值的方法。
零导入的工作解决方案:
data _==_ {A : Set} (x : A) : A -> Set where
refl : x == x
-- congruence
cong : forall {A B : Set} {x y : A} -> (f : A -> B) -> (x == y) -> (f x) == (f y)
cong f refl = refl -- note these refls are of different types: of x == y on the left, and of (f x) == (f y) on the right
-- transport: given two values are "equal", transport one dependent value along the equality path into a different dependent value
transport : forall {A : Set} {B : A -> Set} {x y : A} -> x == y -> B x -> B y
transport refl bx = bx -- proof relies on the circumstance that the only way to construct x == y is refl, so (B x) is (B y)
-- then induction at the heart of Agda can work out that this must be valid for any x == y
-- commutativity of _==_
comm : forall {A : Set} {x y : A} -> x == y -> y == x
comm refl = refl
data Nat : Set where
zero : Nat
suc : Nat -> Nat
_+_ : ∀ (m n : Nat) -> Nat
zero + n = n
(suc m) + n = suc (m + n)
-- Proving the necessary commutativity of suc.
-- Agda can see things like "(suc m) + n == suc (m + n)" by definition
-- but other equalities need proving, and then you can transport
-- the values from one type to another
n+1≡1+n : forall (m n : Nat) -> (m + (suc n)) == (suc (m + n))
n+1≡1+n zero n = refl
n+1≡1+n (suc m) n = cong suc (n+1≡1+n m n)
data odd : Nat → Set
data even : Nat → Set
data even where
ezero :
-------
even zero
esuc : ∀ {n : Nat}
→ odd n
------
→ even (suc n)
data odd where
osuc : ∀ { n : Nat }
→ even n
------
→ odd (suc n)
e+e≡e : ∀ {m n : Nat}
→ even m
→ even n
----
→ even (m + n)
o+e≡o : ∀ {m n : Nat}
→ odd m
→ even n
------
→ odd (m + n)
e+e≡e ezero en = en
e+e≡e (esuc om) en = esuc (o+e≡o om en)
o+e≡o (osuc em) en = osuc (e+e≡e em en)
-- Prove commutativity of even based on a known proof for commutativity of suc.
e-comm : forall {m n : Nat} -> even (suc (m + n)) -> even (m + (suc n))
e-comm {m} {n} esmn = transport {B = even} (comm (n+1≡1+n m n)) esmn -- transport needs hinting what B is
-- otherwise Agda cannot infer what B is based on the definition as found in this snippet
-- the error may seem a bit obscure, but you can see it is wrangling with
-- the dependent type of B:
-- Failed to solve the following constraints:
-- _74 := λ {m} {n} esmn → transport (comm (n+1≡1+n m n)) (_72 esmn)
-- [blocked on problem 166]
-- [165] (even (suc (m + n))) =< (_B_73 (suc (m + n))) : Set
-- [166] _B_73 (m + suc n) =< even (m + suc n) : Set
-- _71 := (λ {m} {n} esmn → esmn) [blocked on problem 165]
--
-- See, it is stuck trying to work out a type _B_73 such that even
-- would be a subtype of it, and a different even would be a supertype of it.
o+o≡e : ∀ {m n : Nat}
→ odd m
→ odd n
------
→ even (m + n)
o+o≡e {m} om (osuc en) = e-comm {m} (esuc (o+e≡o om en)) -- Agda had a problem working out m, so extracting it from implicits
-- Failed to solve the following constraints:
-- _81 := λ {.n} {.m} om en → e-comm (_80 om en)
-- [blocked on problem 188]
-- [188, 189] _m_74 om en + suc (_n_75 om en) = .m + suc .n : Nat
-- _79 := λ {.n} {.m} om en → esuc (o+e≡o om en)
-- [blocked on problem 185]
-- [185, 186, 187] .m + .n = _m_74 om en + _n_75 om en : Nat
--
-- See, if e-comm is not given {m} and {n}, then it is stuck working out
-- _m_74
transport
连接依赖类型是关键概念之一。例如,_==_
的同余和交换性可以简化为 transport
:
-- congruence
cong : forall {A B : Set} {x y : A} -> (f : A -> B) -> (x == y) -> (f x) == (f y)
cong {x = x} f xy = transport {B = (\y -> (f x) == (f y))} -- just making explicit that B is a type (f x) == (f _)
xy refl -- this refl is of type (f x) == (f x), which gets transported along x == y to (f x) == (f y)
-- commutativity of _==_
comm : forall {A : Set} {x y : A} -> x == y -> y == x
comm {x = x} xy = transport {B = (_== x)} xy refl -- this refl is of type x == x, which gets transported along x == y to y == x
我试图证明两个奇数之和是偶数。
最后一行有什么问题?
data odd : ℕ → Set
data even : ℕ → Set
data even where
ezero :
-------
even zero
esuc : ∀ {n : ℕ}
→ odd n
------
→ even (suc n)
data odd where
osuc : ∀ { n : ℕ }
→ even n
------
→ odd (suc n)
e+e≡e : ∀ {m n : ℕ}
→ even m
→ even n
----
→ even (m + n)
o+e≡o : ∀ {m n : ℕ}
→ odd m
→ even n
------
→ odd (m + n)
e+e≡e ezero en = en
e+e≡e (esuc om) en = esuc (o+e≡o om en)
o+e≡o (osuc em) en = osuc (e+e≡e em en)
o+o≡e : ∀ {m n : ℕ}
→ odd m
→ odd n
------
→ even (m + n)
o+o≡e (osuc em) on = esuc (o+e≡o on em)
我收到这个错误:
➊ - 660 Experiment.agda Agda ∏ unix | 50: 0 Bottom
/Users/max/dev/plfa.github.io/src/plfa/Experiment.agda:52,28-39
n != n₁ of type ℕ
when checking that the inferred type of an application
odd (n + _n_31)
matches the expected type
odd (n₁ + n)
但我觉得这些类型还不错。例如,如果我将右侧替换为?并检查目标,Agda 显示:
Goal: even (suc (n + n₁))
————————————————————————————————————————————————————————————
on : odd n₁
em : even n
n₁ : ℕ (not in scope)
n : ℕ (not in scope
所以我要传递证据 on
n
是奇数,em
m
是偶数。并将这些传递给 o+e≡e
,后者需要这些类型的参数。那我哪里错了?
一般来说,我如何阅读 Agda 的错误消息?变量名后的下标是否有意义?
它告诉你 em
不等于 on
:你想要 odd (m + n)
的证明,但你得到 odd (n + m)
- Agda 看不到加法是可交换的。你应该交换参数。
o+o≡e on (osuc em) = esuc (o+e≡o on em)
这会产生不同的错误。该错误告诉您 Agda 无法计算出 suc (m + n)
等于 m + suc n
,这意味着您需要引入一个确定等式的引理。然后回想一下 transport
(一个将依赖类型 B x
的值沿着等式 x ≡ y
传输到不同依赖类型 B y
的值的函数),这会给你一种从 esuc (o+e≡o on em)
构造的值中获取所需类型值的方法。
零导入的工作解决方案:
data _==_ {A : Set} (x : A) : A -> Set where
refl : x == x
-- congruence
cong : forall {A B : Set} {x y : A} -> (f : A -> B) -> (x == y) -> (f x) == (f y)
cong f refl = refl -- note these refls are of different types: of x == y on the left, and of (f x) == (f y) on the right
-- transport: given two values are "equal", transport one dependent value along the equality path into a different dependent value
transport : forall {A : Set} {B : A -> Set} {x y : A} -> x == y -> B x -> B y
transport refl bx = bx -- proof relies on the circumstance that the only way to construct x == y is refl, so (B x) is (B y)
-- then induction at the heart of Agda can work out that this must be valid for any x == y
-- commutativity of _==_
comm : forall {A : Set} {x y : A} -> x == y -> y == x
comm refl = refl
data Nat : Set where
zero : Nat
suc : Nat -> Nat
_+_ : ∀ (m n : Nat) -> Nat
zero + n = n
(suc m) + n = suc (m + n)
-- Proving the necessary commutativity of suc.
-- Agda can see things like "(suc m) + n == suc (m + n)" by definition
-- but other equalities need proving, and then you can transport
-- the values from one type to another
n+1≡1+n : forall (m n : Nat) -> (m + (suc n)) == (suc (m + n))
n+1≡1+n zero n = refl
n+1≡1+n (suc m) n = cong suc (n+1≡1+n m n)
data odd : Nat → Set
data even : Nat → Set
data even where
ezero :
-------
even zero
esuc : ∀ {n : Nat}
→ odd n
------
→ even (suc n)
data odd where
osuc : ∀ { n : Nat }
→ even n
------
→ odd (suc n)
e+e≡e : ∀ {m n : Nat}
→ even m
→ even n
----
→ even (m + n)
o+e≡o : ∀ {m n : Nat}
→ odd m
→ even n
------
→ odd (m + n)
e+e≡e ezero en = en
e+e≡e (esuc om) en = esuc (o+e≡o om en)
o+e≡o (osuc em) en = osuc (e+e≡e em en)
-- Prove commutativity of even based on a known proof for commutativity of suc.
e-comm : forall {m n : Nat} -> even (suc (m + n)) -> even (m + (suc n))
e-comm {m} {n} esmn = transport {B = even} (comm (n+1≡1+n m n)) esmn -- transport needs hinting what B is
-- otherwise Agda cannot infer what B is based on the definition as found in this snippet
-- the error may seem a bit obscure, but you can see it is wrangling with
-- the dependent type of B:
-- Failed to solve the following constraints:
-- _74 := λ {m} {n} esmn → transport (comm (n+1≡1+n m n)) (_72 esmn)
-- [blocked on problem 166]
-- [165] (even (suc (m + n))) =< (_B_73 (suc (m + n))) : Set
-- [166] _B_73 (m + suc n) =< even (m + suc n) : Set
-- _71 := (λ {m} {n} esmn → esmn) [blocked on problem 165]
--
-- See, it is stuck trying to work out a type _B_73 such that even
-- would be a subtype of it, and a different even would be a supertype of it.
o+o≡e : ∀ {m n : Nat}
→ odd m
→ odd n
------
→ even (m + n)
o+o≡e {m} om (osuc en) = e-comm {m} (esuc (o+e≡o om en)) -- Agda had a problem working out m, so extracting it from implicits
-- Failed to solve the following constraints:
-- _81 := λ {.n} {.m} om en → e-comm (_80 om en)
-- [blocked on problem 188]
-- [188, 189] _m_74 om en + suc (_n_75 om en) = .m + suc .n : Nat
-- _79 := λ {.n} {.m} om en → esuc (o+e≡o om en)
-- [blocked on problem 185]
-- [185, 186, 187] .m + .n = _m_74 om en + _n_75 om en : Nat
--
-- See, if e-comm is not given {m} and {n}, then it is stuck working out
-- _m_74
transport
连接依赖类型是关键概念之一。例如,_==_
的同余和交换性可以简化为 transport
:
-- congruence
cong : forall {A B : Set} {x y : A} -> (f : A -> B) -> (x == y) -> (f x) == (f y)
cong {x = x} f xy = transport {B = (\y -> (f x) == (f y))} -- just making explicit that B is a type (f x) == (f _)
xy refl -- this refl is of type (f x) == (f x), which gets transported along x == y to (f x) == (f y)
-- commutativity of _==_
comm : forall {A : Set} {x y : A} -> x == y -> y == x
comm {x = x} xy = transport {B = (_== x)} xy refl -- this refl is of type x == x, which gets transported along x == y to y == x