open import Arith::Fin
open import Data::List hiding (++, ++-assoc, !!)
open import Paths

open data Vec (A : Type) (n : Nat) : Type
| A, 0 ⇒ vnil
| A, suc minfixr :> A (Vec A m)
  tighter =

variable A B : Type
variable n m o : Nat

def vmap (f : AB) (xs : Vec A n) : Vec B n
| f, vnilvnil
| f, x :> xsf x :> vmap f xs

overlap def infix ++ (xs : Vec A n) (ys : Vec A m) : Vec A (n + m)
| vnil, ysys
| xs, vnilxs
| x :> xs, ysx :> (xs ++ ys)
tighter =

overlap def ++-assoc (xs : Vec A n) (ys : Vec A m) (zs : Vec A o)
  : Path (\iVec A (+-assoc i)) ((xs ++ ys) ++ zs) (xs ++ (ys ++ zs))
| vnil, ys, zsidp
| xs, vnil, zsidp
| xs, ys, vnilidp
// TODO: Debug the following
// | x :> xs, ys, zs => pmapd (\i => x :>) (++-assoc xs ys zs)
| x :> xs, ys, zs\ix :> (++-assoc xs ys zs i)

def infix !! (l : Vec A n) (i : Fin n) : A
| a :> l, fzeroa
| a :> l, fsuc il !! i

def fold (f : Fn B AB) (init : B) (xs : Vec A n) : B
| f, init, vnilinit
| f, acc, x :> xsfold f (f acc x) xs

def last (Vec A (suc n)) : A
| x :> vnilx
// | _ :> xs => last xs
// ^ The purpose of #243 is to make this work
| _ :> (x :> xs) ⇒ last (x :> xs)

def head (Vec A (suc n)) : A
| x :> _ ⇒ x

def tail (Vec A (suc n)) : Vec A n
| _ :> xsxs

def toList (Vec A n) : List A
| a :> xsa :< toList xs
| vnilnil

def fromList (l : List A) : Vec A (length l)
| a :< la :> fromList l
| nilvnil