在下面的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"
,而不会遇到不完整的模式匹配错误。
答案 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