Skip to content

[Add] takeNat for Vec in Data.Vec.Base #2778

@e-mniang

Description

@e-mniang

The current take in Data.Vec.Base is defined as:

take : ∀ m {n} → Vec A (m + n) → Vec A m
take m xs = proj₁ (splitAt m xs)

This is a useful total function, but it requires that the input vector has exactly m + n elements. While this is type-safe, it makes many natural theorems difficult or verbose to express—especially when working with partial takes on vectors of unknown or unrestricted size.

For example, the following becomes difficult, requiring rewrites and equalities just to satisfy the type of take:

take-++-more : ∀ {A : Set} {m n k : ℕ} → (xs : Vec A m) → (ys : Vec A n) → (p : ℕ) → (m≤p : m ≤ p) → (m+n≡p+k∸n : m + n ≡ p + (n ∸ k)) →  (n≡k+n-k : n ≡ k + (n ∸ k)) → 
 toList (Data.Vec.Base.take p (cast m+n≡p+k∸n (xs Data.Vec.Base.++ ys))) ≡ toList (xs Data.Vec.Base.++  (Data.Vec.Base.take k (cast n≡k+n-k ys)))

So, maybe we could add a less restrictive version of take, named takeNat, defined as:

takeNat : ∀ {A : Set} {m : ℕ} → (k : ℕ) → Vec A m → Vec A (k ⊓ m)
takeNat zero     xs        = []
takeNat (suc k)  []        = []
takeNat (suc k)  (x ∷ xs)  = x ∷ takeNat k xs

This definition behaves like List.take, and avoids the need for index coercion or auxiliary equalities.
With takeNat, the same lemma becomes:

takeNat-++-more : ∀ {A : Set} {m n : ℕ} → (xs : Vec A m) → (ys : Vec A n) → (p : ℕ) → m ≤ p
                  → toList (takeNat p (xs Data.Vec.Base.++ ys)) ≡ toList (xs Data.Vec.Base.++ takeNat (p ∸ m) ys)

Feedback on this suggestion, definition, naming, and placement is welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions