{-# OPTIONS --safe #-}
open import Prelude.Init
open import Prelude.Decidable

-- Vectors of all (bounded) natural numbers satisfying a predicate.
-- TODO: consider alternative using `Vec.Bounded.Vec≤`?
module Prelude.PVec {n} (P : Pred (Fin n) )  _ : P ⁇¹  where

open import Prelude.PFin public
  using (pweaken)
  renaming (pweaken-injective to ↑-injective)

pFins : List (Fin n)
pFins = filter ¿ P ¿¹ (L.allFin n)

PVec : Type   Type 
PVec A = Vec A (length pFins)

PIndex = ∃· P
↑_ = pweaken {P = P}

private variable A : Type 

pLookup : PVec A  PIndex  A
pLookup vs i = V.lookup vs ( i)

module _ {A : Type } i  _ : P i  where
  pLookup-replicate = V.lookup-replicate {A = A} ( (i  it))
  pLookup∘updateAt = V.lookup∘updateAt {A = A} ( (i  it))
  module _ j  _ : P j  where
    pLookup∘updateAt′ = V.lookup∘updateAt′ {A = A} ( (i  it)) ( (j  it))
  module _ {B : Type ℓ′} where
    pLookup-map = V.lookup-map {A = A} {B = B} ( (i  it))

infixl 6 _[_]%=_ _[_]%=′_ _[_]≔_

_[_]%=′_ : PVec A  Fin n  (A  A)  PVec A
xs [ i ]%=′ f =
  case ¿ P i ¿ of λ where
    (yes p)  xs V.[  (i  p) ]%= f
    (no ¬p)  xs

update-¬ :  {xs : PVec A} {i : Fin n} {f : A  A} 
  ¬ P i 
  (xs [ i ]%=′ f)  xs
update-¬ ¬p rewrite dec-no ¿ _ ¿ ¬p = refl

_[_]%=_ : PVec A  PIndex  (A  A)  PVec A
xs [ i ]%= f = xs V.[  i ]%= f

_[_]≔_ : PVec A  PIndex  A  PVec A
xs [ i ]≔ y = xs V.[  i ]≔ y