检查推断的类型时发生Agda错误

时间:2019-06-08 16:33:49

标签: agda

我试图证明两个奇数之和是偶数。

最后一行出了什么问题?

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的错误消息?变量名后面的下标有意义吗?

1 个答案:

答案 0 :(得分:1)

这是在告诉您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