[英]agda return the even number index of the list
代碼是:
filter-pos : {A : Set} → 𝕃 A → (ℕ → 𝔹) → 𝕃 A
filter-pos = {!!}
filter-pos-test : filter-pos ('a' :: 'b' :: 'c' :: 'd' :: 'e' :: 'f' :: []) is-even ≡ 'a' :: 'c' :: 'e' :: []
filter-pos-test = refl
我的想法是使用nth
輸出nth
索引,使用map
函數使它們成為一個列表,如果它是偶數n
,它將返回。 但是,這不能正常工作。
有人可以讓我知道如何解決這個問題嗎? 我認為編寫幫助功能來解決問題會有所幫助。
我將使用標准庫。
一種愚蠢的解決方案是使用元素索引壓縮列表,使用常規filter
,然后刪除索引。 例如
'a' :: 'b' :: 'c' :: 'd' :: 'e' :: 'f' :: []
變
('a', 0) :: ('b', 1) :: ('c', 2) :: ('d', 3) :: ('e', 4) :: ('f', 5) :: []
filter (is-even ∘ snd)
返回
('a', 0) :: ('c', 2) :: ('e', 4) :: []
並在中map fst
結果
'a' :: 'c' :: 'e' :: []
一個更自然的解決方案是遍歷列表並在每個遞歸調用上增加一個計數器:
filter-pos : {A : Set} → List A → (ℕ → Bool) → List A
filter-pos {A} xs p = go 0 xs where
go : ℕ -> List A -> List A
go i [] = []
go i (x ∷ xs) = if p i then x ∷ r else r where
r = go (suc i) xs
在這里, i
是元素的索引。 但是現在,每當需要證明有關filter-pos
,您都需要證明有關go
的引理,因為它go
完成實際的工作,而filter-pos
只是它的包裝。 慣用的解決方案如下所示:
filter-pos : {A : Set} → List A → (ℕ → Bool) → List A
filter-pos [] p = []
filter-pos (x ∷ xs) p = if p 0 then x ∷ r else r where
r = filter-pos xs (p ∘ suc)
在這里,我們沒有調整計數器,而是調整了謂詞,並用suc
。 因此,在第一個元素上,我們檢查p 0
是否為真,在第二個元素上,我們檢查(p ∘ suc) 0
(立即變為p 1
)是否為真,在第三個元素上,我們檢查(p ∘ suc ∘ suc) 0
(立即減少到p 2
)為真,依此類推。 即,這與使用計數器的解決方案相同,但是僅使用一個功能。
最后一個版本也可以調整與工作Fin
代替ℕ
filter-pos-fin : {A : Set} → (xs : List A) → (Fin (length xs) → Bool) → List A
filter-pos-fin [] p = []
filter-pos-fin (x ∷ xs) p = if p zero then x ∷ r else r where
r = filter-pos-fin xs (p ∘ suc)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.