我可以使用值的常规形式来避免Agda中不完全的模式匹配吗?

时间:2019-05-27 23:51:53

标签: agda

在下面的Agda程序中,尽管one仅适合myList的情况,但在cons的定义中缺少大小写的情况下我得到了警告。

open import Data.Nat

data List (A : Set) : Set where
  nil : List A
  cons : A → List A → List A

myList : List ℕ
myList = cons 1 (cons 2 (cons 3 nil))

one : ℕ
one with myList 
... | (cons x xs) = x
Incomplete pattern matching for .test.with-16. Missing
cases:
  one | nil

我知道这听起来有些令人费解,但是有一种方法可以用one来定义myList,而不会遇到“不完整的模式匹配”错误?

此示例简化了我的原始问题,该问题来自家庭作业,并使用稍微复杂一些的类型。在这种情况下,"myList"是一个聪明的函数根据较小的输入计算出的较大值。如果我使用Emacs的Agda模式(C-c C-n)计算"myList"的范式,则可以从中获取"one"的值并将其粘贴到程序中。但是,此值在打印时占用数十行,因此,我在徘徊是否有一种方法可以根据"one"直接定义"myList",而不会遇到不完整的模式匹配错误。

2 个答案:

答案 0 :(得分:3)

如果您使用with e,则e从目标和上下文中抽象(认为是lambda抽象),并且要求您像在变量中而不是e那样继续进行操作本身。因此,以下模式匹配根本不考虑myList的值(这是完全反推论的,但只是用于使用一个额外的参数创建辅助定义的语法糖)。

但是,您可以编写以下内容:

open import Agda.Builtin.List
open import Agda.Builtin.Nat renaming (Nat to ℕ)
open import Agda.Builtin.Equality

myList : List ℕ
myList = 1 ∷ 2 ∷ 3 ∷ []

head : {n : ℕ} {ns : List ℕ} (xs : List ℕ) → n ∷ ns ≡ xs → ℕ
head (x ∷ xs) refl = x

one : ℕ
one = head myList refl

您也可以查看标准库中的inspect模式,以获取针对此问题的更通用解决方案。

答案 1 :(得分:1)

您可以在类型级别反映一个值,然后在其上进行模式匹配。看起来像这样:

open import Data.Nat

data List (A : Set) : Set where
  nil : List A
  cons : A → List A → List A

myList : List ℕ
myList = cons 1 (cons 2 (cons 3 nil))

data Sing {α} {A : Set α} : A -> Set where
  sing : ∀ x -> Sing x

one : ℕ
one with sing myList
... | sing (cons x (cons _ (cons _ nil))) = x