Reputation: 982
I needed to use lists for something I'm doing and needed look-up,
open import Data.List.Properties
open import Data.List
open import Data.Fin
infix 10 _‼_
_‼_ : ∀ {X : Set} → (xs : List X) → Fin (length xs) → X
[] ‼ ()
(x ∷ xs) ‼ fzero = x
(x ∷ xs) ‼ fsuc i = xs ‼ i
I had to define it myself since I could not find it in the libraries. I wish the libraries where easier to navigate and search. Any suggestions on better navigating or searching the libraries is much appreciated.
I wanted to show that look-ups on one argument of a concatenation is just lookup on the whole concatenation using a raised or injected index, namely
open import Relation.Binary.PropositionalEquality
‼-upper : ∀ {X} (pre main : List X) (i : Fin (length main))
→ let #pre+i = subst Fin (sym (length-++ pre)) (raise (length pre) i)in
(pre ++ main) ‼ #pre+i ≡ main ‼ i
‼-upper = ?
and dually
open import Data.Nat
open import Relation.Binary using
open DecTotalOrder decTotalOrder renaming (refl to ≤ℕ-refl ; trans to ≤ℕ-trans ; reflexive to ≤ℕ-reflexive)
open import Data.Nat.Properties
‼-lower : ∀ {X} (main pos : List X) (i : Fin (length main))
→ let i∶Fin#m++p = inject≤ i (≤ℕ-trans (m≤m+n _ (length pos) (≤ℕ-reflexive (sym (length-++ main)))) in
(main ++ pos) ‼ i∶Fin#m++p ≡ main ‼ i
‼-lower = {!!}
I originally proved these two for a variant of vectors, Fin n → X
, and used pasting of such sequences in place of concatenation. Now I just want to do the same thing but for the usual List
datatype. Any advice is appreciated.
Upvotes: 3
Views: 48
Reputation: 12715
Usually, when you have subst
at the type level (which is a rather bad situation) you can eliminate it with rewrite
at the value level. So let's try it:
‼-upper : ∀ {X} (pre main : List X) (i : Fin (length main))
→ let #pre+i = subst Fin (sym (length-++ pre)) (raise (length pre) i)in
(pre ++ main) ‼ #pre+i ≡ main ‼ i
‼-upper [] main i = refl
‼-upper (x ∷ pre) main i rewrite length-++ pre {main} = ?
Agda refuses:
w != foldr (λ _ → suc) 0 (pre ++ main) of type ℕ
when checking that the type
OK, something clashes with something. To remove this clashing we can instead rewrite by a "bigger" equation:
lem : ∀ {n m} (i : Fin n) (p : m ≡ n)
-> subst Fin (sym (cong suc p)) (fsuc i) ≡ fsuc (subst Fin (sym p) i)
lem i refl = refl
‼-upper : ∀ {X} (pre main : List X) (i : Fin (length main))
→ let #pre+i = subst Fin (sym (length-++ pre)) (raise (length pre) i)in
(pre ++ main) ‼ #pre+i ≡ main ‼ i
‼-upper [] main i = refl
‼-upper (x ∷ pre) main i rewrite lem (raise (length pre) i) (length-++ pre {main})
= ‼-upper pre main i
I guess ‼-lower
is similar (also, it should be simpler if you replace inject≤
with inject+
, see lookup-++-inject+
in Data.Vec.Properties
). An alternative way is to define specialized versions of raise
and inject
:
raise-length : ∀ {α} {A : Set α}
-> (xs ys : List A) -> Fin (length ys) -> Fin (length (xs ++ ys))
raise-length [] ys i = i
raise-length (x ∷ xs) ys i = fsuc (raise-length xs ys i)
inject-length : ∀ {α} {A : Set α} {ys}
-> (xs : List A) -> Fin (length xs) -> Fin (length (xs ++ ys))
inject-length [] ()
inject-length (x ∷ xs) fzero = fzero
inject-length (x ∷ xs) (fsuc i) = fsuc (inject-length xs i)
‼-upper : ∀ {X} (pre main : List X) (i : Fin (length main))
-> (pre ++ main) ‼ raise-length pre main i ≡ main ‼ i
‼-upper [] main i = refl
‼-upper (x ∷ pre) main i = ‼-upper pre main i
‼-lower : ∀ {X} (main pos : List X) (i : Fin (length main))
-> (main ++ pos) ‼ inject-length main i ≡ main ‼ i
‼-lower [] pos ()
‼-lower (x ∷ main) pos fzero = refl
‼-lower (x ∷ main) pos (fsuc i) = ‼-lower main pos i
But I would simply use some form of vectors — why complicate your life?
Upvotes: 1