Agda: возвращает последний элемент списка

#list #agda

#Список #agda

Вопрос:

Когда я регистрируюсь, agda-stdlib/src/Data/List/Base.agda я вижу, что last функции нет, но я вижу в agda-stdlib/src/Data/Vec/Base.agda функции для last .

Когда я пытаюсь его использовать, я получаю некоторые ошибки типа, которые я не уверен, что понимаю.

Вот как я пытаюсь это назвать: last (fromList todos)

где

 todos : List Todo
  

и

 record Todo : Set where
  field
    text      : String
    completed : Bool
    id        : ℕ
  

Ошибка, которую я получаю,

 Data.List.foldr (λ _ → suc) 0 todos != suc _n_31 of type ℕ
when checking that the expression fromList todos has type
Data.Vec.Vec Todo (1   _n_31)
  

Я предполагаю, что это связано с тем, что last имеет эту подпись:

 last : ∀ {n} → Vec A (1   n) → A
  

Но я в замешательстве, потому что, когда я делаю C-c C-l на:

 last (fromList ?)
  

Я получаю эту цель

 ?0 : List Todo
  

который, как я думал todos , был удовлетворен.

Что я должен изменить здесь, чтобы он передавал эту ошибку? Или есть другой способ получить последний элемент a List ?

Спасибо!

Редактировать

Я попробовал другой маршрут и решил заменить Vec на List . Однако я получаю другую ошибку, которую я не совсем понимаю, когда пытаюсь сделать

   Todo.completed (last (todos ∷ʳ record { text = text ; completed = false ; id = 1 }))
≡⟨⟩
  Todo.completed (record { text = text ; completed = false ; id = 1 })
  
 false !=
Todo.completed
(last
 (todos ∷ʳ record { text = text ; completed = false ; id = 1 })
 | Data.Vec.initLast
   (todos ∷ʳ record { text = text ; completed = false ; id = 1 }))
of type Bool
when checking that the inferred type of an application
  false ≡ _y_45
matches the expected type
  Todo.completed
  (last
   (todos ∷ʳ record { text = text ; completed = false ; id = 1 }))
  ≡ false
  

Я не уверен, что здесь говорится в сообщении об ошибке.

Редактировать

Я попытался упростить проблему до

 AddNat : ∀ {n : ℕ} → (Vec ℕ n) → (Vec ℕ (1   n))
AddNat numbers = numbers ∷ʳ 1

AddNatLastAddedElementIsNat :
  ∀ {n : ℕ} (numbers : Vec ℕ (1   n)) →
    last (AddNat numbers) ≡ 1
AddNatLastAddedElementIsNat numbers =
  begin
    last (AddNat numbers)
  ≡⟨⟩
    last (numbers ∷ʳ 1)
  ≡⟨⟩
    1
  ∎
  

но я все равно получаю аналогичную ошибку:

 1 != (last (numbers ∷ʳ 1) | Data.Vec.initLast (numbers ∷ʳ 1)) of
type ℕ
when checking that the expression 1 ∎ has type
last (numbers ∷ʳ 1) ≡ 1
  

Почему last (numbers ∷ʳ 1) отображается как тип (last (numbers ∷ʳ 1) | Data.Vec.initLast (numbers ∷ʳ 1)) ? | Указывает ли это на тип суммы, и мне нужно будет сопоставить шаблон в обоих случаях? Спасибо!

Ответ №1:

Цель в fromList ?0 имеет тип List Todo , но поскольку fromList ?0 имеет тип Vec _ (length ?0) , вы получите сообщение об ошибке, если средство проверки типов придет к выводу, что не может быть n такого, которое length ?0 (по определению) равно 1 n . В вашем случае это происходит, как только вы это говорите ?0 := todos ?0 := x ∷ todos , вместо этого сработало бы что-то вроде.

Обычно функция like last должна знать, что список или векторы непустые, альтернативой является определение функции, которая возвращает Maybe A вместо A though .