如何检查产品内部的值(Σ)?

时间:2017-11-06 11:51:51

标签: agda

我试图通过使用Σ函数来绕过filterVec类型,类似于可用于列表的filter函数。请参阅下面的实施:

-- Some imports we will need later
open import Data.Bool
open import Data.Nat
open import Data.Product
open import Data.Vec

-- The filterVec function
filterVec : {n : ℕ} -> (ℕ -> Bool) -> Vec ℕ n -> Σ ℕ (λ length → Vec ℕ length)
filterVec _ [] = 0 , []
filterVec f (x ∷ xs) with filterVec f xs
... | length , filtered = if f x then (suc length , x ∷ filtered) else (length , filtered)

对我的功能感到满意,我决定测试它

dummyVec : Vec ℕ 5
dummyVec = 1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ []

dummyFn : Vec ℕ 5
dummyFn with filterVec (λ _ → true) dummyVec
dummyFn | length , xs = {!!} -- I would like to return xs here, but Agda throws a type error

出于某种原因,Agda无法判断length5,因此不允许我返回xs。但是,下面的代码确实有效:

open import Relation.Binary.PropositionalEquality
dummyProof : proj₁ (filterVec (λ _ → true) dummyVec) ≡ 5
dummyProof = refl

我对这种行为感到十分困惑。在dummyFn的情况下,Agda无法判断长度为5,但在dummyProof的情况下,Agda证明它没有任何问题。

我错过了什么?如何让dummyFn工作?

1 个答案:

答案 0 :(得分:4)

with将值绑定到名称。如果要进行计算,可以使用let

dummyFn′ : Vec ℕ 5
dummyFn′ = let length , xs = filterVec (λ _ → true) dummyVec
           in xs

让我们看看下面的例子:

dummy : Set
dummy with 5
dummy | x = {!!}

x是否应该在洞中神奇地减少到5?不,你给了5另一个名字 - x,这些表达既不是在判断上也不是在命题上相等。

现在在你的例子中:

dummyFn : Vec ℕ 5
dummyFn with filterVec (λ _ → true) dummyVec
dummyFn | length , xs = {!!}

您已将length名称指定为xs的长度。并且它不会减少到5。这是一个名字。如果你想要两者都给出一个名字并记住这个名字是什么,那就有inspect成语:

dummyFn′′ : Vec ℕ 5
dummyFn′′ with filterVec (λ _ → true) dummyVec | inspect (filterVec (λ _ → true)) dummyVec
dummyFn′′ | length , xs | [ refl ] = xs