{-# OPTIONS --cubical --safe #-}

module Data.Tuple.Base where

open import Prelude hiding (; tt)
open import Data.Unit.UniversePolymorphic
open import Data.Fin

Tuple :  n  (Lift a (Fin n)  Type b)  Type b
Tuple zero    f = 
Tuple {a = a} {b = b} (suc n) f = f (lift f0) × Tuple {a = a} {b = b} n (f  lift  fs  lower)

private
  variable
    n : 
    u : Level
    U : Lift a (Fin n)  Type u

ind : Tuple n U  (i : Lift a (Fin n))  U i
ind {n = suc n} (x , xs) (lift f0)     = x
ind {n = suc n} (x , xs) (lift (fs i)) = ind xs (lift i)

tab : ((i : Lift a (Fin n))  U i)  Tuple n U
tab {n = zero}  f = tt
tab {n = suc n} f = f (lift f0) , tab (f  lift  fs  lower)

Π→Tuple→Π :  {a n u} {U : Lift a (Fin n)  Type u} (xs : (i : Lift a (Fin n))  U i) i  ind (tab xs) i  xs i
Π→Tuple→Π {n = suc n} f (lift f0) = refl
Π→Tuple→Π {n = suc n} f (lift (fs i)) = Π→Tuple→Π (f  lift  fs  lower) (lift i)

Tuple→Π→Tuple :  {n} {U : Lift a (Fin n)  Type u} (xs : Tuple n U)  tab (ind xs)  xs
Tuple→Π→Tuple {n = zero} tt = refl
Tuple→Π→Tuple {n = suc n} (x , xs) i .fst = x
Tuple→Π→Tuple {n = suc n} (x , xs) i .snd = Tuple→Π→Tuple xs i

Tuple⇔ΠFin :  {a n u} {U : Lift a (Fin n)  Type u}  Tuple n U  ((i : Lift a (Fin n))  U i)
Tuple⇔ΠFin .fun = ind
Tuple⇔ΠFin .inv = tab
Tuple⇔ΠFin .leftInv = Tuple→Π→Tuple
Tuple⇔ΠFin .rightInv x = funExt (Π→Tuple→Π x)