{-# OPTIONS --safe #-}

module Cubical.HITs.Modulo.Base where

open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Prelude

open import Cubical.Data.Empty using ()
open import Cubical.Data.Nat using (; zero; suc; _+_)
open import Cubical.Data.Unit renaming (Unit to )

open import Cubical.Relation.Nullary

NonZero :   Type₀
NonZero 0 = 
NonZero _ = 

private
  variable
     : Level
    k : 

-- The Modulo type is similar to the Fin type, but instead of being
-- inhabited by canonical values, the inhabitants are all naturals,
-- and paths are added between numbers that have the same residue.
--
-- This representation makes it easier to do certain arithmetic
-- without changing the modulus. For instance, we can just add any
-- natural to a Modulo k to get another, whereas with Fin k, we must
-- calculate the canonical representative.
--
-- The reason the path constructor is guarded is to avoid adding
-- non-trivial path structure to the k=0 case. If it were not guarded,
-- each `Modulo 0` would become like the circle, and guarding the
-- constructor is somewhat easier to work with than truncation.
--
-- Note also that unlike `Fin 0`, `Modulo 0` is equivalent to the naturals.
data Modulo (k : ) : Type₀ where
  embed : (n : )  Modulo k
  pre-step : NonZero k  (n : )  embed n  embed (k + n)

-- When we are working with k = suc k₀, the `step` alias is much
-- we can use this alias.
pattern step n i = pre-step _ n i

-- Helper to avoid having to case on `k` in certain places.
ztep : ∀{k} n  Path (Modulo k) (embed n) (embed (k + n))
ztep {0}     n = refl
ztep {suc k} n = step n

-- The standard eliminator for `Modulo`.
elim
  : (P :  k  Modulo k  Type )
   (e :  k n  P k (embed n))
   (st :  k n  PathP  i  P (suc k) (step n i)) (e (suc k) n) (e (suc k) (suc k + n)))
   (m : Modulo k)  P k m
elim P e st (embed n) = e _ n
elim {k = suc k} P e st (step n i) = st k n i