agda返回列表的偶数索引

时间:2017-02-23 01:29:20

标签: agda

代码是:

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,它将会返回。但是,这不能正常工作。

有人可以告诉我应该如何解决这个问题吗?我认为编写帮助函数来解决问题会很有帮助。

1 个答案:

答案 0 :(得分:2)

我将使用标准库。

一个愚蠢的解决方案是使用索引元素压缩列表,使用通常的filter然后删除索引。 E.g。

'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)是否为真,在第三个元素上我们检查是否{ {1}}(立即缩减为(p ∘ suc ∘ suc) 0)为真,依此类推。即这与计数器的解决方案相同,但只使用一个函数。

也可以调整最后一个版本以使用p 2代替Fin