{-# OPTIONS --cumulativity #-}
module ROmega.IndexCalculus.Records where

open import Agda.Primitive

open import Relation.Binary.PropositionalEquality
  using (_≡_; refl; sym; trans)

-- open import Data.Nat using (ℕ; zero; suc)
open import Data.List
open import Data.Sum
  renaming (_⊎_ to _or_; inj₁ to left; inj₂ to right)
  hiding (map)
open import Data.Product
  using (_×_; ; ∃-syntax; Σ-syntax; _,_)
  renaming (proj₁ to fst; proj₂ to snd)
open import Data.Fin  renaming (zero to fzero; suc to fsuc)
  hiding (fold)  

open import ROmega.IndexCalculus.Rows
open import ROmega.IndexCalculus.Properties

--------------------------------------------------------------------------------
-- Records say: "If you give me an index in range, I can give you a type".

Π :  {}  Row (Set )  Set 
Π (n , P) =  (i : Fin n)  P i

--------------------------------------------------------------------------------
-- Projection.

prj :  {} (z y : Row {lsuc } (Set )) (w : z  y) (p : Π y)  Π z
prj {} z y w p i with w i
... | (n , P) rewrite P = p n

--------------------------------------------------------------------------------
-- Concatenation.

infixl 5 _⊹_
infix  5 _⊹_Using_

_⊹_ :  {} {x y z : Row {lsuc } (Set )} {x·y~z : x · y ~ z} (Πx : Π x) (Πy : Π y)  Π z
_⊹_ {} {x} {y} {z} {x·y~z} Πx Πy i with fst x·y~z i
... | left (j , x[j]=z[i]) rewrite (sym x[j]=z[i]) = Πx j
... | right (j , y[j]=z[i]) rewrite (sym y[j]=z[i]) = Πy j

_⊹_Using_ :  {} {x y z : Row {lsuc } (Set )} (Πx : Π x) (Πy : Π y) (x·y~z : x · y ~ z)  Π z
Πx  Πy Using pf = _⊹_ {x·y~z = pf} Πx Πy

--------------------------------------------------------------------------------
-- Folding.

fold :  { ℓ'} {υ : Set ℓ'}
          (ρ : Row {lsuc } (Set ))
          (f :  (τ : Set ) (y : Row {lsuc } (Set )) 
            (sing {lsuc } τ) · y ~ ρ  τ   υ) 
         (_++_ : υ  υ  υ) 
         (e : υ) 
         (r  : Π ρ) 
         υ
fold ρ@(n , P) f _++_ e r =
  foldr _++_ e (map  i  f (P i) (ρ delete i) (recombine ρ i) (r i)) (ixs n))