{-# OPTIONS --safe #-}
module Cubical.Data.Sequence.Base where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.Nat
open import Cubical.Data.Fin

private
  variable
     ℓ' ℓ'' : Level

record Sequence ( : Level) : Type (ℓ-suc ) where
  constructor sequence
  field
    obj :   Type 
    map : {n : }  obj n  obj (1 + n)

record SequenceMap (C : Sequence ) (D : Sequence ℓ') : Type (ℓ-max  ℓ') where
  constructor sequencemap
  field
    map : (n : )  Sequence.obj C n  Sequence.obj D n
    comm : (n : ) (x : Sequence.obj C n)
       Sequence.map D (map n x)  map (suc n) (Sequence.map C x)

converges :  {}  Sequence   (n : )  Type 
converges seq n = (k : )  isEquiv (Sequence.map seq {n = k + n})

finiteSequence : ( : Level) (m : )  Type (ℓ-suc )
finiteSequence  m = Σ[ S  Sequence  ] converges S m

shiftSequence :  {}  Sequence   (n : )  Sequence 
Sequence.obj (shiftSequence seq n) m = Sequence.obj seq (m + n)
Sequence.map (shiftSequence seq n)  {n = k} x = Sequence.map seq x

-- Isomorphism of sequences
SequenceIso : (A : Sequence ) (B : Sequence ℓ')  Type (ℓ-max  ℓ')
SequenceIso A B =
  Σ[ is  ((n : )  Iso (Sequence.obj A n) (Sequence.obj B n)) ]
     ((n : ) (a : Sequence.obj A n)
        Sequence.map B (Iso.fun (is n) a)  Iso.fun (is (suc n))
                         (Sequence.map A a))

-- Equivalences of sequences
SequenceEquiv : (A : Sequence ) (B : Sequence ℓ')  Type (ℓ-max  ℓ')
SequenceEquiv A B =
  Σ[ e  (SequenceMap A B) ]
     ((n : )  isEquiv (SequenceMap.map e n))

-- Iso to equiv
SequenceIso→SequenceEquiv : {A : Sequence } {B : Sequence ℓ'}
   SequenceIso A B  SequenceEquiv A B
SequenceMap.map (fst (SequenceIso→SequenceEquiv (is , e))) x = Iso.fun (is x)
SequenceMap.comm (fst (SequenceIso→SequenceEquiv (is , e))) = e
snd (SequenceIso→SequenceEquiv (is , e)) n = isoToIsEquiv (is n)