我一直在反對一個問題的頭幾天,但我的Agda技能不是很強。特殊構造函數上的模式匹配
我想寫一個函數,只在一個索引的數據類型,只在一個特定的索引定義。這隻適用於數據構造函數的某些特殊化。我無法弄清楚如何定義這樣的功能。我試圖將我的問題減少到一個更小的例子。
該設置涉及到自然數列表,列表中有目擊成員的類型以及刪除列表成員的函數。
open import Data.Nat
open import Relation.Binary.Core
data List : Set where
nil : List
_::_ : (x : ℕ) -> (xs : List) -> List
-- membership within a list
data _∈_ (x : ℕ) : List -> Set where
here : forall {xs} -> x ∈ (x :: xs)
there : forall {xs y} -> (mem : x ∈ xs) -> x ∈ (y :: xs)
-- delete
_\\_ : forall {x} (xs : List) -> (mem : x ∈ xs) -> List
_\\_ nil()
_\\_ (_ :: xs) here = xs
_\\_ (_ :: nil) (there())
_\\_ (x :: xs) (there p) = x :: (xs \\ p)
只是一個快速檢查,取消一個單鏈表的頭元素是空列表:
check : forall {x} -> nil ≡ ((x :: nil) \\ here)
check = refl
現在我有一個是通過列表索引的一些包裝數據類型
-- Our test data type
data Foo : List -> Set where
test : Foo nil
test2 : forall {x} (xs : List) -> (mem : x ∈ xs) -> Foo (xs \\ mem)
構造函數test2
獲取列表和成員資格值,並根據從列表中刪除元素的結果爲數據類型編制索引。
現在我在哪裏卡住了位我想以下簽名的函數:
foo : Foo nil -> ℕ
foo = {!!}
即採取Foo
價值與它的索引專門用於nil
。這對test
案件很好
foo test = 0
第二種情況很棘手。我最初想象的是這樣的:
foo : Foo nil -> ℕ
foo test = 0
foo (test2 .(_ :: nil) .here) = 1
但阿格達抱怨xs \\ mem != nil of type List when checking that the pattern test2 .(_ :: nil) .here has type Foo nil
。所以我嘗試使用with
-clause:
foo : Foo nil -> ℕ
foo test = 0
foo (test2 xs m) with xs \\ m
... | nil = 1
... |()
這會產生相同的錯誤。我已經嘗試了各種排列,但唉,我不能完全弄清楚如何使用n \\ m = nil
回到模式中的信息。我已經嘗試了各種其他類型的謂詞,但不知道如何告訴Agda它需要知道什麼。非常感謝一些幫助!謝謝。
附加:我在阿格達寫了一個證明,給予任何xs : List
和m : x \in xs
那(xs \\ m = nil
)意味着xs = x :: nil
和m = here
,這似乎是它可以是給類型檢查是有用的,但我米不知道如何做到這一點。我已經向大家介紹的是尊重其問題複雜化的依賴於PI類型逐點平等:
data PiEq {A : Set} {B : A -> Set} : (a : A) -> (b : A) -> (c : B a) -> (d : B b) -> Set where
pirefl : forall {x : A} {y : B x} -> PiEq {A} {B} x x y y
check' : forall {x xs m} {eq : xs \\ m ≡ nil} -> (PiEq {List} {\xs -> x ∈ xs} xs (x :: nil) m here)
check' {xs = nil} {()}
-- The only case that works
check' {xs = ._ :: nil} {here} = pirefl
-- Everything else is refuted
check' {xs = ._ :: (_ :: xs)} {here} {()}
check' {xs = ._ :: nil} {there()}
check' {xs = ._} {there here} {()}
check' {xs = ._} {there (there m)} {()}
什麼關於[this](https://gist.github.com/vituscze/6807d6529aed9e9f60e6)? – Vitus 2014-11-21 00:49:20
是的。你需要'with'子句將'test2'的類型確定爲'Foo nil',但是輸入必須是'Foo nil',所以你不能在第一個條件中使用'with'子句地點。通過爲'Foo'的尾部賦一個變量值,你可以進入'with',然後等式確保只有'nil'情況在'with'內部是相關的。 – zmthy 2014-11-21 04:11:11
@Vitus是的!這就對了!你想發佈它作爲答案,所以我可以接受它嗎?我之前嘗試過這樣的事情,但設法失敗 - 我認爲我也與'refl'相匹配,這會使事情中斷,即添加「foo refl rest = 0」引發「我不確定是否應該有構造函數test2的情況「。這對我來說似乎很奇怪!我沒有在證明上進行匹配的情況下嘗試它!非常感謝 – dorchard 2014-11-21 11:57:17