[Agda] Problem with reversing vector

Lyndon Maydwell maydwell at gmail.com
Fri Jun 15 14:27:53 CEST 2012


Thanks so much Dominique.

That's very helpful.

On Fri, Jun 15, 2012 at 6:24 PM, Dominique Devriese
<dominique.devriese at cs.kuleuven.be> wrote:
> Lyndon,
>
> Yes, one solution is to prove this fact about natural numbers. You can
> construct such a proof using the standard library:
>
> 2012/6/15 Lyndon Maydwell <maydwell at gmail.com>:
>> vrev (y ► ys) = vconcat (vrev ys) (y ► ε)
>
>  open import Data.Nat.Properties
>  open import Relation.Binary.PropositionalEquality
>  open import Algebra.Structures
>  open import Function
>
>  open IsCommutativeSemiring isCommutativeSemiring using (+-comm)
>
>  {- ... -}
>
>  vrev {A} {suc n} (y ► ys) = subst (Vec _) (+-comm _ 1) $ vconcat
> (vrev ys) (y ► ε)
>
> However, such casts are a bit unnice, and they typically get in your
> way when proving properties of vrev. There are sometimes better
> ways to organise your code that allow you to avoid casts. For
> example, if you look in the standard library in Data.Vec, you can find
> a cleaner way to make everything work (translated to your naming):
>
>  foldl : ∀ {b} {A : Set} (B : ℕ → Set b) {m} →
>          (∀ {n} → B n → A → B (suc n)) →
>          B zero →
>          Vec A m → B m
>  foldl b _⊕_ n ε       = n
>  foldl b _⊕_ n (x ► xs) = foldl (λ n → b (suc n)) _⊕_ (n ⊕ x) xs
>
>  reverse : {A : Set} → {n : ℕ} → Vec A n → Vec A n
>  reverse {A} = foldl (Vec A) (flip _►_) ε
>
> You might exploit the same strategy directly, by defining a version of
> Data.Nat._+_ that has a different recursion structure:
>
>  reverse : {A : Set} → {n : ℕ} → Vec A n → Vec A n
>  reverse {A} = go 0 (flip _►_) ε
>    where _+′_ : ℕ → ℕ → ℕ
>          x +′ zero = x
>          x +′ suc y = suc x +′ y
>
>          go : ∀ m {n} {A : Set} →
>               (∀ {n} → Vec A (n +′ m) → A → Vec A (n +′ suc m)) →
>               Vec A (0 +′ m) →
>               Vec A n → Vec A (n +′ m)
>          go m _⊕_ n ε       = n
>          go m _⊕_ n (x ► xs) = go (suc m) _⊕_ (n ⊕ x) xs
>
> A crucial point here is that while folding, the type of _⊕_ changes to
> keep track of the current length of the accumulator. I mean that after
> m iterations of foldl, _⊕_'s type will amount to something like
>  (∀ {n} → Vec A (m +′ n) → A → Vec A (m +′ suc n))
> where the type of _►_ would be hard to work with:
>  (∀ {n} → Vec A n → A → Vec A (suc n))
>
> Note also that the recursion structure of _+′_ that we had to define
> internally is the same as the recursion structure of the indices of
> the vectors in the recursion of go (i.e. we shift one element from the
> iteratee to the accumulator each time, so indices (m, suc b) are
> turned into indices (suc m, n)).
>
> Anyway, the point is that you can sometimes avoid casts like the subst
> call above by organizing your code in the best way. This best way may
> be hard to find though..
>
> Dominique


More information about the Agda mailing list