{-# OPTIONS --allow-unsolved-metas --no-termination-check #-}

module TT where

module Prelude where

-- Props ------------------------------------------------------------------

  data True : Set where
    tt : True

  data False : Set where

  postulate
    falseE : (A : Set) -> False -> A

  infix 3 _/\_

  data _/\_ (P Q : Set) : Set where
    andI : P -> Q -> P /\ Q

  -- Zero and One -----------------------------------------------------------

  data Zero : Set where

  data One : Set where
    unit : One

  -- Natural numbers --------------------------------------------------------

  data Nat : Set where
    zero : Nat
    suc  : Nat -> Nat

  _+_ : Nat -> Nat -> Nat
  zero  + m = m
  suc n + m = suc (n + m)

  module NatEq where

    infix 5 _==_

    _==_ : Nat -> Nat -> Set
    zero  == zero = True
    suc n == suc m = n == m
    _     == _     = False

    rewriteEq : (C : Nat -> Set){m n : Nat} -> m == n -> C n -> C m
    rewriteEq C {zero}  {zero}  _  x = x
    rewriteEq C {suc _} {suc _} eq x = rewriteEq (\z -> C (suc z)) eq x
    rewriteEq C {zero}  {suc _} () _
    rewriteEq C {suc _} {zero}  () _

module Chain {A : Set}(_==_ : A -> A -> Set)
             (_trans_ : {x y z : A} -> x == y -> y == z -> x == z)
    where

  infixl 4 _=-=_
  infixl 4 _===_
  infixr 8 _since_

  _=-=_ : (x : A){y : A} -> x == y -> x == y
  x =-= xy = xy

  _===_ : {x y z : A} -> x == y -> y == z -> x == z
  xy === yz = xy trans yz

  _since_ : {x : A}(y : A) -> x == y -> x == y
  y since xy = xy

module Fin where

  open Prelude

  -- Finite sets ------------------------------------------------------------

  data Suc (A : Set) : Set where
    fzero' : Suc A
    fsuc'  : A -> Suc A

  mutual
    data Fin (n : Nat) : Set where
      finI : Fin' n -> Fin n

    Fin' : Nat -> Set
    Fin'  zero   = Zero
    Fin' (suc n) = Suc (Fin n)

  fzero : {n : Nat} -> Fin (suc n)
  fzero = finI fzero'

  fsuc : {n : Nat} -> Fin n -> Fin (suc n)
  fsuc i = finI (fsuc' i)

  finE : {n : Nat} -> Fin n -> Fin' n
  finE (finI i) = i

  module FinEq where

    infix 5 _==_

    _==_ : {n : Nat} -> Fin n -> Fin n -> Set
    _==_ {suc _} (finI  fzero'  ) (finI  fzero'  ) = True
    _==_ {suc _} (finI (fsuc' i)) (finI (fsuc' j)) = i == j
    _==_          _                _               = False

    rewriteEq : {n : Nat}(C : Fin n -> Set){i j : Fin n} -> i == j -> C j -> C i
    rewriteEq {suc _} C {finI  fzero'  } {finI  fzero'  } eq x = x
    rewriteEq {suc _} C {finI (fsuc' i)} {finI (fsuc' j)} eq x = rewriteEq (\z -> C (fsuc z)) eq x
    rewriteEq {suc _} C {finI (fsuc' _)} {finI fzero'   } () _
    rewriteEq {suc _} C {finI fzero'   } {finI (fsuc' _)} () _
    rewriteEq {zero}  C {finI ()}        {_}              _  _

module Vec where

  open Prelude
  open Fin

  infixr 15 _::_

  -- Vectors ----------------------------------------------------------------

  data Nil : Set where
    nil' : Nil

  data Cons (A As : Set) : Set where
    cons' : A -> As -> Cons A As

  mutual
    data Vec (A : Set)(n : Nat) : Set where
      vecI : Vec' A n -> Vec A n

    Vec' : Set -> Nat -> Set
    Vec' A  zero   = Nil
    Vec' A (suc n) = Cons A (Vec A n)

  nil : {A : Set} -> Vec A zero
  nil = vecI nil'

  _::_ : {A : Set}{n : Nat} -> A -> Vec A n -> Vec A (suc n)
  x :: xs = vecI (cons' x xs)

  vecE : {A : Set}{n : Nat} -> Vec A n -> Vec' A n
  vecE (vecI xs) = xs

  vec : {A : Set}(n : Nat) -> A -> Vec A n
  vec  zero   _ = nil
  vec (suc n) x = x :: vec n x

  map : {n : Nat}{A B : Set} -> (A -> B) -> Vec A n -> Vec B n
  map {zero}  f (vecI nil')         = nil
  map {suc n} f (vecI (cons' x xs)) = f x :: map f xs

  _!_ : {n : Nat}{A : Set} -> Vec A n -> Fin n -> A
  _!_ {zero } _                   (finI ())
  _!_ {suc n} (vecI (cons' x _ )) (finI fzero')    = x
  _!_ {suc n} (vecI (cons' _ xs)) (finI (fsuc' i)) = xs ! i

  tabulate : {n : Nat}{A : Set} -> (Fin n -> A) -> Vec A n
  tabulate {zero}  f = nil
  tabulate {suc n} f = f fzero :: tabulate (\x -> f (fsuc x))

module Untyped where

  open Prelude
  open Fin
  open Vec

  Name = Nat

  data Expr (n : Nat) : Set where
    eVar : Fin n -> Expr n
    eApp : Expr n -> Expr n -> Expr n
    eLam : Expr (suc n) -> Expr n
    eSet : Expr n
    eEl  : Expr n
    ePi  : Expr n
    eCon : Name -> Expr n

  module ExprEq where

    infix 5 _==_

    _==_ : {n : Nat} -> Expr n -> Expr n -> Set
    eVar i              == eVar j                = FinEq._==_ i j
    eApp e1 e2          == eApp e3 e4            = e1 == e3 /\ e2 == e4
    eLam e1             == eLam e2               = e1 == e2
    eSet                == eSet                  = True
    eEl                 == eEl                   = True
    ePi                 == ePi                   = True
    eCon f              == eCon g                = NatEq._==_ f g
    _                   == _                     = False

    rewriteEq : {n : Nat}(C : Expr n -> Set){r s : Expr n} -> r == s -> C s -> C r
    rewriteEq C {eVar i    } {eVar j    } eq x = FinEq.rewriteEq (\z -> C (eVar z)) eq x
    rewriteEq C {eLam e1   } {eLam e2   } eq x = rewriteEq (\z -> C (eLam z)) eq x
    rewriteEq C {eSet      } {eSet      } eq x = x
    rewriteEq C {eEl       } {eEl       } eq x = x
    rewriteEq C {ePi       } {ePi       } eq x = x
    rewriteEq C {eCon f    } {eCon g    } eq x = NatEq.rewriteEq (\z -> C (eCon z)) eq x
    rewriteEq C {eApp e1 e2} {eApp e3 e4} (andI eq13 eq24) x =
      rewriteEq (\z -> C (eApp z e2)) eq13 (
        rewriteEq (\z -> C (eApp e3 z)) eq24 x
      )
    rewriteEq C {eVar _} {eLam _  } () _
    rewriteEq C {eVar _} {eSet    } () _
    rewriteEq C {eVar _} {eEl     } () _
    rewriteEq C {eVar _} {eCon _  } () _
    rewriteEq C {eVar _} {ePi     } () _
    rewriteEq C {eVar _} {eApp _ _} () _

    rewriteEq C {eLam _} {eVar _  } () _
    rewriteEq C {eLam _} {eSet    } () _
    rewriteEq C {eLam _} {eEl     } () _
    rewriteEq C {eLam _} {eCon _  } () _
    rewriteEq C {eLam _} {ePi     } () _
    rewriteEq C {eLam _} {eApp _ _} () _

    rewriteEq C {eSet  } {eLam _  } () _
    rewriteEq C {eSet  } {eVar _  } () _
    rewriteEq C {eSet  } {eEl     } () _
    rewriteEq C {eSet  } {eCon _  } () _
    rewriteEq C {eSet  } {ePi     } () _
    rewriteEq C {eSet  } {eApp _ _} () _

    rewriteEq C {eEl   } {eLam _  } () _
    rewriteEq C {eEl   } {eSet    } () _
    rewriteEq C {eEl   } {eVar _  } () _
    rewriteEq C {eEl   } {eCon _  } () _
    rewriteEq C {eEl   } {ePi     } () _
    rewriteEq C {eEl   } {eApp _ _} () _

    rewriteEq C {eCon _} {eLam _  } () _
    rewriteEq C {eCon _} {eSet    } () _
    rewriteEq C {eCon _} {eEl     } () _
    rewriteEq C {eCon _} {eVar _  } () _
    rewriteEq C {eCon _} {ePi     } () _
    rewriteEq C {eCon _} {eApp _ _} () _

    rewriteEq C {ePi   } {eLam _  } () _
    rewriteEq C {ePi   } {eSet    } () _
    rewriteEq C {ePi   } {eEl     } () _
    rewriteEq C {ePi   } {eCon _  } () _
    rewriteEq C {ePi   } {eVar _  } () _
    rewriteEq C {ePi   } {eApp _ _} () _

    rewriteEq C {eApp _ _} {eLam _  } () _
    rewriteEq C {eApp _ _} {eSet    } () _
    rewriteEq C {eApp _ _} {eEl     } () _
    rewriteEq C {eApp _ _} {eCon _  } () _
    rewriteEq C {eApp _ _} {ePi     } () _
    rewriteEq C {eApp _ _} {eVar _  } () _

module Typed where

  open Prelude
  open Fin
  open Vec

  infixl 15 _&_
  infix  13 _!!_
  infix  5  _==_

  -- Contexts ---------------------------------------------------------------
  data CSuc (n : Nat) : Set

  Context' : Nat -> Set
  Context' zero    = Nil
  Context' (suc n) = CSuc n

  data Context (n : Nat) : Set
  data Type {n : Nat}(Γ : Context n) : Set

  data CSuc n where
    ext : (Γ : Context n) -> Type Γ -> Context' (suc n)

  data Context n where
    ctxI : Context' n -> Context n

  -- Types ------------------------------------------------------------------
  _&_ : {n : Nat}(Γ : Context n) -> Type Γ -> Context (suc n)
  data Term {n : Nat}(Γ : Context n)(A : Type Γ) : Set

  data Type {n} Γ where
    SET : Type Γ
    Pi  : (A : Type Γ) -> Type (Γ & A) -> Type Γ
    El  : Term Γ SET -> Type Γ

  Γ & A = ctxI (ext Γ A)

  -- Variables --------------------------------------------------------------
  data VarSuc {n : Nat}(Γ : Context n)(B : Type Γ)(A : Type (Γ & B)) : Set

  Var' : {n : Nat}(Γ : Context n) -> Type Γ -> Set
  Var' {zero}   Γ              A = Zero
  Var' {suc n} (ctxI (ext Γ B)) A = VarSuc Γ B A

  _==_ : {n : Nat}{Γ : Context n} -> Type Γ -> Type Γ -> Set
  data Ren {n m : Nat}(Γ : Context n)(Δ : Context m) : Set

  rename : {n m : Nat}{Γ : Context n}{Δ : Context m} -> Ren Γ Δ -> Type Γ -> Type Δ
  upR : {n : Nat}{Γ : Context n}{A : Type Γ} -> Ren Γ (Γ & A)
  data Var {n : Nat}(Γ : Context n)(A : Type Γ) : Set

  data VarSuc {n} Γ B A where
    vzero_ : A == rename upR B -> Var' (Γ & B) A
    vsuc_  : (C : Type Γ) -> A == rename upR C -> Var Γ C -> Var' (Γ & B) A

  data Var {n} Γ A where
    varI : Var' Γ A -> Var Γ A

  -- Terms ------------------------------------------------------------------
  data Sub {n m : Nat}(Γ : Context n)(Δ : Context m) : Set
  subst : {n m : Nat}{Γ : Context n}{Δ : Context m} -> Sub Γ Δ -> Type Γ -> Type Δ
  down : {n : Nat}{Γ : Context n}{A : Type Γ} -> Term Γ A -> Sub (Γ & A) Γ

  data Term {n} Γ A where
    var : (x : Var Γ A) -> Term Γ A
    app : {B : Type Γ}{C : Type (Γ & B)} -> Term Γ (Pi B C) -> (t : Term Γ B) ->
          A == subst (down t) C -> Term Γ A
    lam : {B : Type Γ}{C : Type (Γ & B)} -> Term (Γ & B) C -> A == Pi B C -> Term Γ A

  -- Context manipulation ---------------------------------------------------

  ∅ : Context zero
  ∅ = ctxI nil'

  _!!_ : {n : Nat}(Γ : Context n) -> Fin n -> Type Γ
  _!!_ {zero}  _                (finI ())
  _!!_ {suc _} (ctxI (ext Γ A)) (finI fzero')           = rename upR A
  _!!_ {suc _} (ctxI (ext Γ A)) (finI (fsuc' i)) = rename upR (Γ !! i)

  -- Renamings --------------------------------------------------------------
  data ConsRen {n m : Nat}(Γ : Context n)(A : Type Γ)(Δ : Context m) : Set

  Ren' : {n m : Nat} -> Context n -> Context m -> Set
  Ren' {zero}  {m} (ctxI nil')      Δ = Nil
  Ren' {suc n} {m} (ctxI (ext Γ A)) Δ = ConsRen Γ A Δ

  data ConsRen {n m} Γ A Δ where
    extRen' : (ρ : Ren Γ Δ) -> Var Δ (rename ρ A) -> Ren' (Γ & A) Δ

  data Ren {n m} Γ Δ where
    renI : Ren' Γ Δ -> Ren Γ Δ

  -- Performing renamings ---------------------------------------------------
  rename' : {n m : Nat}{Γ : Context n}{Δ : Context m} -> Ren Γ Δ -> Type Γ -> Type Δ

  rename ρ SET = SET
  rename ρ A  = rename' ρ A

  liftR : {n m : Nat}{Γ : Context n}{A : Type Γ}{Δ : Context m} ->
          (ρ : Ren Γ Δ) -> Ren (Γ & A) (Δ & rename ρ A)
  renameTerm : {n m : Nat}{Γ : Context n}{Δ : Context m}{A : Type Γ}
               (ρ : Ren Γ Δ) -> Term Γ A -> Term Δ (rename ρ A)

  rename' ρ SET      = SET
  rename' ρ (Pi A B) = Pi (rename ρ A) (rename (liftR ρ) B)
  rename' ρ (El t)   = El (renameTerm ρ t)

  lookupR : {n m : Nat}{Γ : Context n}{A : Type Γ}{Δ : Context m}
            (ρ : Ren Γ Δ)(x : Var Γ A) -> Var Δ (rename ρ A)
  cong : {n m : Nat}{Γ : Context n}{Δ : Context m}(f : Type Γ -> Type Δ)
         {A B : Type Γ} -> A == B -> f A == f B
  _trans_ : {n : Nat}{Γ : Context n}{A B C : Type Γ} -> A == B -> B == C -> A == C
  renameSubstCommute :
    {n m : Nat}{Γ : Context n}{Δ : Context m}{A : Type Γ}{B : Type (Γ & A)}
    {ρ : Ren Γ Δ}{t : Term Γ A} ->
    rename ρ (subst (down t) B) == subst (down (renameTerm ρ t)) (rename (liftR ρ) B)

  renameTerm ρ (var x)      = var (lookupR ρ x)
  renameTerm {_}{_}{_}{_}{A} ρ (app{_}{C} s t eq) =
      app (renameTerm ρ s) (renameTerm ρ t)
          (cong (rename ρ) eq  trans  renameSubstCommute)
  renameTerm ρ (lam t eq)   = lam (renameTerm (liftR ρ) t) (cong (rename ρ) eq)

  lookupR {zero} _ (varI ())
  lookupR {suc n} {_} {ctxI (ext Γ B)} {A} {Δ}
          (renI (extRen' ρ z)) (varI (vzero_ eq)) = {!!}
  lookupR {suc n} {_} {ctxI (ext Γ B)} {A} {Δ}
          (renI (extRen' ρ z)) (varI (vsuc_ C eq x)) = {!!}

  -- Building renamings -----------------------------------------------------

  extRen : {n m : Nat}{Γ : Context n}{A : Type Γ}{Δ : Context m}
           (ρ : Ren Γ Δ) -> Var Δ (rename ρ A) -> Ren (Γ & A) Δ
  extRen ρ x = renI (extRen' ρ x)

  _coR_ : {n m p : Nat}{Γ : Context n}{Δ : Context m}{Θ : Context p} -> Ren Δ Θ -> Ren Γ Δ -> Ren Γ Θ

  liftR {_}{_}{_}{A} ρ = extRen (upR coR ρ) (varI {!!})

  idR : {n : Nat} {Γ : Context n} -> Ren Γ Γ
  idR = {!!}

  _coR_ = {!!}

  upR = {!!}

  -- Substitutions ----------------------------------------------------------
  data ConsSub {n m : Nat}(Γ : Context n)(A : Type Γ)(Δ : Context m) : Set

  Sub' : {n m : Nat} -> Context n -> Context m -> Set
  Sub' {zero}  {m} (ctxI nil')      Δ = Nil
  Sub' {suc n} {m} (ctxI (ext Γ A)) Δ = ConsSub Γ A Δ

  data ConsSub {n m} Γ A Δ  where
    extSub' : (σ : Sub Γ Δ) -> Term Δ (subst σ A) -> Sub' (Γ & A) Δ

  data Sub {n m} Γ Δ where
    subI : Sub' Γ Δ -> Sub Γ Δ

  -- Performing substitution ------------------------------------------------
  subst' : {n m : Nat}{Γ : Context n}{Δ : Context m} -> Sub Γ Δ -> Type Γ -> Type Δ

  subst σ SET              = SET
  subst σ A        = subst' σ A

  liftS : {n m : Nat}{Γ : Context n}{A : Type Γ}{Δ : Context m} ->
          (σ : Sub Γ Δ) -> Sub (Γ & A) (Δ & subst σ A)

  substTerm : {n m : Nat}{Γ : Context n}{Δ : Context m}{A : Type Γ} ->
              (σ : Sub Γ Δ) -> Term Γ A -> Term Δ (subst σ A)

  subst' σ (Pi A B) = Pi (subst σ A) (subst (liftS σ) B)
  subst' σ (El t)   = El (substTerm σ t)
  subst' σ SET      = SET

  substTerm σ (var x)             = {!!}
  substTerm σ (app s t eq) = {!!}
  substTerm σ (lam t eq)   = {!!}

  -- Building substitutions -------------------------------------------------

  liftS {_}{_}{_}{A} σ = {!!} -- extSub (upS ∘ σ) (var fzero (substCompose upS σ A))
    -- Works with hidden args to substCompose when inlined in subst
    -- but not here. Weird.

  topS : {n : Nat}{Γ : Context n} -> Sub ∅ Γ
  topS = subI nil'

  extSub : {n m : Nat}{Γ : Context n}{A : Type Γ}{Δ : Context m}
           (σ : Sub Γ Δ) -> Term Δ (subst σ A) -> Sub (Γ & A) Δ
  extSub σ t = subI (extSub' σ t)

  idS : {n : Nat}{Γ : Context n} -> Sub Γ Γ
  idS {zero}  {ctxI nil'}      = topS
  idS {suc _} {ctxI (ext Γ A)} = {!!} -- extSub upS (var fzero refl)

  convert : {n : Nat}{Γ : Context n}{A B : Type Γ} -> A == B -> Term Γ B -> Term Γ A

  _∘_ : {n m p : Nat}{Γ : Context n}{Δ : Context m}{Θ : Context p} -> Sub Δ Θ -> Sub Γ Δ -> Sub Γ Θ

  substCompose : {n m p : Nat}{Γ : Context n}{Δ : Context m}{Θ : Context p}
                 (σ : Sub Δ Θ)(δ : Sub Γ Δ)(A : Type Γ) ->
                 subst (σ ∘ δ) A == subst σ (subst δ A)

  _∘_ {zero} {_}{_} {ctxI nil'}      _  _                 = topS
  _∘_ {suc _}{_}{_} {ctxI (ext Γ A)} σ (subI (extSub' δ t)) =
    extSub (σ ∘ δ) (convert (substCompose σ δ A) (substTerm σ t))

  upS : {n : Nat}{Γ : Context n}{A : Type Γ} -> Sub Γ (Γ & A)
  upS = {!!}

  substId : {n : Nat}{Γ : Context n}{A : Type Γ} -> subst idS A == A

  down t = extSub idS (convert substId t)

  -- Convertibility ---------------------------------------------------------

  A == B = {!!}

  refl : {n : Nat}{Γ : Context n}{A : Type Γ} -> A == A
  refl = {!!}

  cong f eq = {!!}

  ab trans bc = {!!}

  convert eq t = {!!}

  -- Properties -------------------------------------------------------------

  renameId : {n : Nat}{Γ : Context n}{A : Type Γ} -> rename idR A == A
  renameId = {!!}

  renameCompose : {n m p : Nat}{Γ : Context n}{Δ : Context m}{Θ : Context p}
                  (σ : Ren Δ Θ)(δ : Ren Γ Δ)(A : Type Γ) ->
                  rename (σ coR δ) A == rename σ (rename δ A)
  renameCompose σ δ A = {!!}

  substId = {!!}

  substCompose σ δ A = {!!}

  renameSubstCommute = {!!}


module McK-B where

open import CS410-Prelude
open import CS410-Nat
open import CS410-Vec

data Bit : Set where O I : Bit

exp2 : Nat -> Nat
exp2 zero    = 1
exp2 (suc n) = exp2 n +N exp2 n

WordNZ : Nat -> Set
data Word (n : Nat) : Set where
  O : Word n
  [_]  : WordNZ n -> Word n
WordNZ zero    = One
WordNZ (suc n) = (WordNZ n * Word n) + WordNZ n

_!_ : {n : Nat} -> Word n -> Word n -> Word (suc n)
O  ! O   = O
O  ! [ x ]  = [ inr x ]
[ x ] ! y      = [ inl (x , y) ]

_!+_ : {n : Nat} -> Word n -> WordNZ n -> WordNZ (suc n)
O  !+ y  = inr y
[ x ] !+ y  = inl (x , [ y ])

iNZ : (n : Nat) -> WordNZ n
iNZ zero = <>
iNZ (suc n) = inr (iNZ n)
i : {n : Nat} -> Word n
i {n} = [ iNZ n ] where

data WViewable : {n : Nat} -> Word n -> Set where
  O0 : WViewable {zero} O
  I0  : WViewable {zero} i
  _!!_  : {n : Nat}(x y : Word n) -> WViewable (x ! y)

wView : {n : Nat}(x : Word n) -> WViewable x
wView {zero} O    = O0
wView {zero} [ <> ]  = I0
wView {suc n} O   = O !! O
wView {suc n} [ inl (x , y) ] = [ x ] !! y
wView {suc n} [ inr      y  ] = O !! [ y ]

expand : {n : Nat} -> Word n -> Vec Bit (exp2 n)
expand x with wView x
expand .O      | O0   = O :: []
expand .([ <> ])  | I0    = I :: []
expand .(x ! y)   | x !! y  = expand x +V expand y

inc : {n : Nat}(x : Word n) -> One + WordNZ n
inc x with wView x
inc .O     | O0   = inr (iNZ zero)
inc .([ <> ]) | I0    = inl <>
inc .(x ! y)  | x !! y  with inc y
inc .(x ! y)  | x !! y  | inr y' = inr (x !+ y')
inc .(x ! y)  | x !! y  | inl <> with inc x
inc .(x ! y)  | x !! y  | inl <> | inr x'  = inr (inl (x' , O))
inc .(x ! y)  | x !! y  | inl <> | inl <>  = inl <>

incm : {n : Nat}(x : Word n) -> Word n
incm x with inc x
incm x | inl <> = O
incm x | inr x' = [ x' ]

fiveW2 : Word 2
fiveW2 = incm (incm (incm (incm (incm O))))

adc : {n : Nat} -> Word n -> Word n -> Bit -> Bit * Word n
adc x y c with wView x | wView y
adc .O .O O | O0 | O0 = O , O
adc .O .O I | O0 | O0 = O , i
adc .O .i O | O0 | I0 = O , i
adc .O .i I | O0 | I0 = I , O
adc .i .O O | I0 | O0 = O , i
adc .i .O I | I0 | O0 = I , O
adc .i .i O | I0 | I0 = I , O
adc .i .i I | I0 | I0 = I , i
adc .(xh ! xl) .(yh ! yl) c | xh !! xl | yh !! yl with adc xl yl c
... | cl , zl with adc xh yh cl
... | ch , zh = ch , zh ! zl


{- Type class for monads. -}
module CategoryTheory.Monad where

open import CategoryTheory.Categories
open import CategoryTheory.Functor
open import CategoryTheory.NatTrans

-- A monad on a category
record Monad {n} (ℂ : Category n) : Set (lsuc n) where
    open Category ℂ
    field
        -- Underlying endofunctor
        T : Endofunctor ℂ
    open Functor T

    field
        -- || Definitions
        -- Unit / return
        η : I ⟹ T
        -- Multiplication / join
        μ : (T ²) ⟹ T

    module η = _⟹_ η
    module μ = _⟹_ μ
    field
        -- || Laws
        -- Unit on both sides is cancelled by multiplication (unit)
        η-unit1 : ∀ {A : obj} -> (μ.at A) ∘ (η.at (omap A)) ≈ id
        η-unit2 : ∀ {A : obj} -> (μ.at A) ∘ (fmap (η.at A)) ≈ id

        -- Multiplication can be performed on both sides (associativity)
        μ-assoc : ∀ {A : obj} -> (μ.at A) ∘ (μ.at (omap A))
                               ≈ (μ.at A) ∘ (fmap (μ.at A))


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

open import Algebra

module Algebra.Construct.OrderedMonoid {ℓ} (monoid : Monoid ℓ) where

open import Prelude
open import Relation.Binary
open import Path.Reasoning

open Monoid monoid

infix 4 _≤_ _≥_ _<_ _>_
_≤_ : 𝑆 → 𝑆 → Type ℓ
x ≤ y = ∃ z × (y ≡ x ∙ z)

_<_ : 𝑆 → 𝑆 → Type ℓ
x < y = ∃ z × (z ≢ ε) × (y ≡ x ∙ z)

_>_ = flip _<_
_≥_ = flip _≤_

≤-refl : Reflexive _≤_
≤-refl = ε , sym (∙ε _)

≤-trans : Transitive _≤_
≤-trans {x} {y} {z} (k₁ , y≡x∙k₁) (k₂ , z≡y∙k₂) = k₁ ∙ k₂ ,_ $
  z ≡⟨ z≡y∙k₂ ⟩
  y ∙ k₂ ≡⟨ cong (_∙ k₂) y≡x∙k₁ ⟩
  (x ∙ k₁) ∙ k₂ ≡⟨ assoc x k₁ k₂ ⟩
  x ∙ (k₁ ∙ k₂) ∎

ε≤x : ∀ x → ε ≤ x
ε≤x x = x , sym (ε∙ x)

∙-cong : ∀ x {y z} → y ≤ z → x ∙ y ≤ x ∙ z
∙-cong x (k , z≡y∙k) = k , cong (x ∙_) z≡y∙k ; sym (assoc x _ k)

-- Trichotomous : Type _
-- Trichotomous = (x y : 𝑆) → Tri _<_ _≡_ _>_ x y


{-# OPTIONS --cubical --no-import-sorts  #-}

open import Cubical.Foundations.Everything renaming (_⁻¹ to _⁻¹ᵖ; assoc to ∙-assoc)
open import Function.Base using (_∋_; _$_)

open import MorePropAlgebra.Bundles
import Cubical.Algebra.Ring as Std

module MorePropAlgebra.Properties.Ring {ℓ} (assumptions : Ring {ℓ}) where
open Ring assumptions renaming (Carrier to R)

import MorePropAlgebra.Properties.AbGroup
module AbGroup'Properties = MorePropAlgebra.Properties.AbGroup   (record { Ring assumptions renaming (+-AbGroup to is-AbGroup) })
module AbGroup'           =                            AbGroup   (record { Ring assumptions renaming (+-AbGroup to is-AbGroup) })
(      AbGroup')          =                            AbGroup ∋ (record { Ring assumptions renaming (+-AbGroup to is-AbGroup) })

import MorePropAlgebra.Properties.Monoid
module Monoid'Properties = MorePropAlgebra.Properties.Monoid   (record { Ring assumptions renaming (·-Monoid to is-Monoid) })
module Monoid'           =                            Monoid   (record { Ring assumptions renaming (·-Monoid to is-Monoid) })
(      Monoid')          =                            Monoid ∋ (record { Ring assumptions renaming (·-Monoid to is-Monoid) })

stdIsRing : Std.IsRing 0r 1r _+_ _·_ (-_)
stdIsRing  .Std.IsRing.+-isAbGroup = AbGroup'Properties.stdIsAbGroup
stdIsRing  .Std.IsRing.·-isMonoid  = Monoid'Properties.stdIsMonoid
stdIsRing  .Std.IsRing.dist        = is-dist

stdRing : Std.Ring {ℓ}
stdRing = record { Ring assumptions ; isRing = stdIsRing }

module RingTheory' = Std.Theory stdRing

{-

-- NOTE: a few facts about rings that might be collected from elsewhere
a+b-b≡a : ∀ a b → a ≡ (a + b) - b
a+b-b≡a a b = let P = sym (fst (+-inv b))
                  Q = sym (fst (+-identity a))
                  R = transport (λ i → a ≡ a + P i) Q
                  S = transport (λ i → a ≡ (+-assoc a b (- b)) i ) R
              in S

-- NOTE: this is called `simplL` and `simplL` in `Cubical.Structures.Group.Properties.GroupLemmas`
+-preserves-≡ : ∀{a b} → ∀ c → a ≡ b → a + c ≡ b + c
+-preserves-≡ c a≡b i = a≡b i + c

+-preserves-≡-l : ∀{a b} → ∀ c → a ≡ b → c + a ≡ c + b
+-preserves-≡-l c a≡b i = c + a≡b i

a+b≡0→a≡-b : ∀{a b} → a + b ≡ 0r → a ≡ - b
a+b≡0→a≡-b {a} {b} a+b≡0 = transport
  (λ i →
    let RHS = snd (+-identity (- b))
        LHS₁ : a + (b + - b) ≡ a + 0r
        LHS₁ = +-preserves-≡-l a (fst (+-inv b))
        LHS₂ : (a + b) - b ≡ a
        LHS₂ = transport (λ j →  (+-assoc a b (- b)) j ≡ fst (+-identity a) j) LHS₁
        in  LHS₂ i ≡ RHS i
  ) (+-preserves-≡ (- b) a+b≡0)

-- NOTE: there is already
-- -commutesWithRight-· : (x y : R) →  x · (- y) ≡ - (x · y)

a·-b≡-a·b : ∀ a b → a · (- b) ≡ - (a · b)
a·-b≡-a·b a b =
  let P : a · 0r ≡ 0r
      P = 0-rightNullifies a
      Q : a · (- b + b) ≡ 0r
      Q = transport (λ i →  a · snd (+-inv b) (~ i) ≡ 0r) P
      R : a · (- b) + a · b ≡ 0r
      R = transport (λ i → ·-rdist-+ a (- b) b i ≡ 0r) Q
  in a+b≡0→a≡-b R

a·b-a·c≡a·[b-c] : ∀ a b c → a · b - (a · c) ≡ a · (b - c)
a·b-a·c≡a·[b-c] a b c =
  let P : a · b + a · (- c) ≡ a · (b + - c)
      P = sym (·-rdist-+ a b (- c))
      Q : a · b - a · c ≡ a · (b + - c)
      Q = transport (λ i →  a · b + a·-b≡-a·b a c i ≡ a · (b + - c) ) P
  in  Q

-}


------------------------------------------------------------------------
-- The Agda standard library
--
-- Endomorphisms on a Setoid
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

open import Relation.Binary

module Function.Endomorphism.Setoid {c e} (S : Setoid c e) where

open import Agda.Builtin.Equality

open import Algebra
open import Algebra.Structures
open import Algebra.Morphism; open Definitions
open import Function.Equality
open import Data.Nat.Base using (ℕ; _+_); open ℕ
open import Data.Nat.Properties
open import Data.Product

import Relation.Binary.Indexed.Heterogeneous.Construct.Trivial as Trivial

private
  module E = Setoid (setoid S (Trivial.indexedSetoid S))
  open E hiding (refl)

------------------------------------------------------------------------
-- Basic type and functions

Endo : Set _
Endo = S ⟶ S

_^_ : Endo → ℕ → Endo
f ^ zero  = id
f ^ suc n = f ∘ (f ^ n)

^-cong₂ : ∀ f → (f ^_) Preserves _≡_ ⟶ _≈_
^-cong₂ f {n} refl = cong (f ^ n)

^-homo : ∀ f → Homomorphic₂ ℕ Endo _≈_ (f ^_) _+_ _∘_
^-homo f zero    n x≈y = cong (f ^ n) x≈y
^-homo f (suc m) n x≈y = cong f (^-homo f m n x≈y)

------------------------------------------------------------------------
-- Structures

∘-isMagma : IsMagma _≈_ _∘_
∘-isMagma = record
  { isEquivalence = isEquivalence
  ; ∙-cong        = λ g f x → g (f x)
  }

∘-magma : Magma _ _
∘-magma = record { isMagma = ∘-isMagma }

∘-isSemigroup : IsSemigroup _≈_ _∘_
∘-isSemigroup = record
  { isMagma = ∘-isMagma
  ; assoc   = λ h g f x≈y → cong h (cong g (cong f x≈y))
  }

∘-semigroup : Semigroup _ _
∘-semigroup = record { isSemigroup = ∘-isSemigroup }

∘-id-isMonoid : IsMonoid _≈_ _∘_ id
∘-id-isMonoid = record
  { isSemigroup = ∘-isSemigroup
  ; identity    = cong , cong
  }

∘-id-monoid : Monoid _ _
∘-id-monoid = record { isMonoid = ∘-id-isMonoid }

------------------------------------------------------------------------
-- Homomorphism

^-isSemigroupMorphism : ∀ f → IsSemigroupMorphism +-semigroup ∘-semigroup (f ^_)
^-isSemigroupMorphism f = record
  { ⟦⟧-cong = ^-cong₂ f
  ; ∙-homo  = ^-homo f
  }

^-isMonoidMorphism : ∀ f → IsMonoidMorphism +-0-monoid ∘-id-monoid (f ^_)
^-isMonoidMorphism f = record
  { sm-homo = ^-isSemigroupMorphism f
  ; ε-homo  = λ x≈y → x≈y
  }


module Cats.Category.Constructions.Unique where

open import Data.Unit using (⊤)
open import Level

open import Cats.Category.Base
open import Cats.Util.Conv

module Build {lo la l≈} (Cat : Category lo la l≈) where

  open Category Cat

  IsUniqueSuchThat : ∀ {lp A B} → (A ⇒ B → Set lp) → A ⇒ B → Set (la ⊔ l≈ ⊔ lp)
  IsUniqueSuchThat P f = ∀ {g} → P g → f ≈ g

  IsUnique : ∀ {A B} → A ⇒ B → Set (la ⊔ l≈)
  IsUnique {A} {B} = IsUniqueSuchThat {A = A} {B} (λ _ → ⊤)

  IsUniqueSuchThat→≈ : ∀ {lp A B} {P : A ⇒ B → Set lp} {f}
    → IsUniqueSuchThat P f
    → ∀ {g h}
    → P g
    → P h
    → g ≈ h
  IsUniqueSuchThat→≈ unique Pg Ph = ≈.trans (≈.sym (unique Pg)) (unique Ph)

  record ∃!′ {lp A B} (P : A ⇒ B → Set lp) : Set (la ⊔ l≈ ⊔ lp) where
    constructor ∃!-intro
    field
      arr : A ⇒ B
      prop : P arr
      unique : IsUniqueSuchThat P arr

  instance
    HasArrow-∃! : ∀ {lp A B} {P : A ⇒ B → Set lp}
      → HasArrow (∃!′ P) lo la l≈
    HasArrow-∃! = record { Cat = Cat ; _⃗ = ∃!′.arr }

  syntax ∃!′ (λ f → P) = ∃![ f ] P

  ∃!″ : ∀ {lp A B} (P : A ⇒ B → Set lp) → Set (la ⊔ l≈ ⊔ lp)
  ∃!″ = ∃!′

  syntax ∃!″ {A = A} {B} (λ f → P) = ∃![ f ∈ A ⇒ B ] P

  ∃! : (A B : Obj) → Set (la ⊔ l≈)
  ∃! A B = ∃![ f ∈ A ⇒ B ] ⊤

  ∃!→≈ : ∀ {lp A B} {P : A ⇒ B → Set lp}
    → ∃!′ P
    → ∀ {g h}
    → P g
    → P h
    → g ≈ h
  ∃!→≈ (∃!-intro _ _ unique) = IsUniqueSuchThat→≈ unique


module Prolegomenon where

open import Agda.Primitive
open import Relation.Binary
open import Algebra
open import Category.Applicative.Predicate

open import Algebra
open import Algebra.Structures
open import Category.Monad.Indexed
open import Algebra.FunctionProperties.Core
open import Function

PowerRightIdentity : ∀ {a ℓ} {A : Set a} → Rel A ℓ → ∀ {b} {B : Set b} → B → (B → A → A) → Set _
PowerRightIdentity _≈_ e _◃_ = ∀ x → (e ◃ x) ≈ x

PowerAssociative : ∀ {a b ℓ} {A : Set a} {B : Set b} → (A → A → Set ℓ) → (B → A → A) → (B → B → B) → Set _
PowerAssociative _≈_ _◃_ _∙_ = ∀ x a b → ((b ∙ a) ◃ x) ≈ (b ◃ (a ◃ x))

_over_ : ∀ {f} {F : Set f} {g} → (F → F → Set g) → ∀ {i} {I : Set i} {a} {A : Set a} → (A → I → F) → A → A → Set (i ⊔ g)
_*_ over f = λ x y → ∀ i → f x i * f y i

record IsMonoidTransformer {s ℓˢ} {S : Set s} (≈ˢ : Rel S ℓˢ) {m ℓᵐ} {M : Set m} (≈ᵐ : Rel M ℓᵐ) (∙ : Op₂ M) (ε : M) (◃ : M → S → S) : Set (s ⊔ ℓˢ ⊔ m ⊔ ℓᵐ) where
  field
    ◃-identity : PowerRightIdentity ≈ˢ ε ◃
    ≈ˢ-over-◃-⟶-≈ᵐ : ≈ˢ over ◃ ⇒ ≈ᵐ
    ≈ᵐ-to-≈ˢ-over-◃ : ≈ᵐ ⇒ ≈ˢ over ◃
    ◃-extracts-∙ : PowerAssociative ≈ˢ ◃ ∙

record MonoidTransformer ℓˢ ℓ⁼ˢ ℓᵐ ℓ⁼ᵐ
  : Set (lsuc (ℓˢ ⊔ ℓ⁼ˢ ⊔ ℓᵐ ⊔ ℓ⁼ᵐ)) where
  field
    base : Setoid ℓˢ ℓ⁼ˢ
    exponent : Monoid ℓᵐ ℓ⁼ᵐ

  module B = Setoid base
  module E = Monoid exponent
{-
  open Setoid base public renaming
    (Carrier to Carrierˢ
    ;_≈_ to _≈ˢ_
    ;reflexive to reflexiveˢ
    ;refl to reflˢ
    ;trans to transˢ
    ;sym to symˢ
    )

  open Monoid exponent public renaming
    (Carrier to Carrierᵐ
    ;_≈_ to _≈ᵐ_
    ;reflexive to reflexiveᵐ
    ;_∙_ to _∙_
    ;ε to ε
    ;refl to reflᵐ
    ;trans to transᵐ
    ;sym to symᵐ)
-}
  infixl 6 _◃_
  field
    _◃_ : E.Carrier → B.Carrier → B.Carrier
    isMonoidTransformer : IsMonoidTransformer B._≈_ E._≈_ E._∙_ E.ε _◃_

  open IsMonoidTransformer isMonoidTransformer public


{-# OPTIONS --without-K --safe #-}

open import Categories.Category

module Categories.Object.Product.Indexed.Properties {o ℓ e} (C : Category o ℓ e) where

open import Level

open import Categories.Category.Discrete
open import Categories.Category.Complete
open import Categories.Category.Construction.Cones
open import Categories.Category.Lift
open import Categories.Object.Product.Indexed C
open import Categories.Diagram.Limit
open import Categories.Functor

import Relation.Binary.PropositionalEquality as ≡

private
  variable
    o′ ℓ′ e′ : Level
  open Category C

module _ {i} (Com : Complete (i ⊔ o′) (i ⊔ ℓ′) (i ⊔ e′) C) where

  module _ {I : Set i} (P : I → Obj) where
    private
      Z = liftC o′ ℓ′ e′ (Discrete I)
      F = lift-func C P ∘F unliftF o′ ℓ′ e′ (Discrete I)
      module L = Limit (Com F)

      K : ∀ {Y} → (∀ i → Y ⇒ P i) → Cone F
      K f = record
        { apex = record
          { ψ       = λ i → f (lower i)
          ; commute = λ { (lift ≡.refl) → identityˡ }
          }
        }

    Complete⇒IndexedProductOf : IndexedProductOf P
    Complete⇒IndexedProductOf = record
      { X       = L.apex
      ; π       = λ i → L.proj (lift i)
      ; ⟨_⟩     = λ f → L.rep (K f)
      ; commute = λ f _ → Cone⇒.commute (L.rep-cone (K f))
      ; unique  = λ f g eq → L.terminal.!-unique {A = K g} record
        { arr     = f
        ; commute = eq _
        }
      }


------------------------------------------------------------------------
-- Properties of homogeneous binary relations
------------------------------------------------------------------------

-- This file contains some core definitions which are reexported by
-- Relation.Binary or Relation.Binary.PropositionalEquality.

module Relation.Binary.Core where

open import Data.Product
open import Data.Sum
open import Data.Function
open import Relation.Nullary.Core

------------------------------------------------------------------------
-- Homogeneous binary relations

Rel : Set → Set₁
Rel a = a → a → Set

------------------------------------------------------------------------
-- Simple properties of binary relations

infixr 4 _⇒_ _=[_]⇒_

-- Implication/containment. Could also be written ⊆.

_⇒_ : ∀ {a} → Rel a → Rel a → Set
P ⇒ Q = ∀ {i j} → P i j → Q i j

-- Generalised implication. If P ≡ Q it can be read as "f preserves
-- P".

_=[_]⇒_ : ∀ {a b} → Rel a → (a → b) → Rel b → Set
P =[ f ]⇒ Q = P ⇒ (Q on₁ f)

-- A synonym, along with a binary variant.

_Preserves_⟶_ : ∀ {a₁ a₂} → (a₁ → a₂) → Rel a₁ → Rel a₂ → Set
f Preserves P ⟶ Q = P =[ f ]⇒ Q

_Preserves₂_⟶_⟶_ : ∀ {a₁ a₂ a₃} →
                   (a₁ → a₂ → a₃) → Rel a₁ → Rel a₂ → Rel a₃ → Set
_+_ Preserves₂ P ⟶ Q ⟶ R =
  ∀ {x y u v} → P x y → Q u v → R (x + u) (y + v)

-- Reflexivity of _∼_ can be expressed as _≈_ ⇒ _∼_, for some
-- underlying equality _≈_. However, the following variant is often
-- easier to use.

Reflexive : {a : Set} → (_∼_ : Rel a) → Set
Reflexive _∼_ = ∀ {x} → x ∼ x

-- Irreflexivity is defined using an underlying equality.

Irreflexive : {a : Set} → (_≈_ _<_ : Rel a) → Set
Irreflexive _≈_ _<_ = ∀ {x y} → x ≈ y → ¬ (x < y)

-- Generalised symmetry.

Sym : ∀ {a} → Rel a → Rel a → Set
Sym P Q = P ⇒ flip₁ Q

Symmetric : {a : Set} → Rel a → Set
Symmetric _∼_ = Sym _∼_ _∼_

-- Generalised transitivity.

Trans : ∀ {a} → Rel a → Rel a → Rel a → Set
Trans P Q R = ∀ {i j k} → P i j → Q j k → R i k

Transitive : {a : Set} → Rel a → Set
Transitive _∼_ = Trans _∼_ _∼_ _∼_

Antisymmetric : {a : Set} → (_≈_ _≤_ : Rel a) → Set
Antisymmetric _≈_ _≤_ = ∀ {x y} → x ≤ y → y ≤ x → x ≈ y

Asymmetric : {a : Set} → (_<_ : Rel a) → Set
Asymmetric _<_ = ∀ {x y} → x < y → ¬ (y < x)

_Respects_ : {a : Set} → (a → Set) → Rel a → Set
P Respects _∼_ = ∀ {x y} → x ∼ y → P x → P y

_Respects₂_ : {a : Set} → Rel a → Rel a → Set
P Respects₂ _∼_ =
  (∀ {x} → P x       Respects _∼_) ×
  (∀ {y} → flip₁ P y Respects _∼_)

Substitutive : {a : Set} → Rel a → Set₁
Substitutive _∼_ = ∀ P → P Respects _∼_

Congruential : ({a : Set} → Rel a) → Set₁
Congruential ∼ = ∀ {a b} → (f : a → b) → f Preserves ∼ ⟶ ∼

Congruential₂ : ({a : Set} → Rel a) → Set₁
Congruential₂ ∼ =
  ∀ {a b c} → (f : a → b → c) → f Preserves₂ ∼ ⟶ ∼ ⟶ ∼

Decidable : {a : Set} → Rel a → Set
Decidable _∼_ = ∀ x y → Dec (x ∼ y)

Total : {a : Set} → Rel a → Set
Total _∼_ = ∀ x y → (x ∼ y) ⊎ (y ∼ x)

data Tri (A B C : Set) : Set where
  tri< : ( a :   A) (¬b : ¬ B) (¬c : ¬ C) → Tri A B C
  tri≈ : (¬a : ¬ A) ( b :   B) (¬c : ¬ C) → Tri A B C
  tri> : (¬a : ¬ A) (¬b : ¬ B) ( c :   C) → Tri A B C

Trichotomous : {a : Set} → Rel a → Rel a → Set
Trichotomous _≈_ _<_ = ∀ x y → Tri (x < y) (x ≈ y) (x > y)
  where _>_ = flip₁ _<_

record NonEmpty {I : Set} (T : Rel I) : Set where
  field
    i     : I
    j     : I
    proof : T i j

nonEmpty : ∀ {I} {T : Rel I} {i j} → T i j → NonEmpty T
nonEmpty p = record { i = _; j = _; proof = p }

------------------------------------------------------------------------
-- Propositional equality

-- This dummy module is used to avoid shadowing of the field named
-- refl defined in IsEquivalence below. The module is opened publicly
-- at the end of this file.

private
 module Dummy where

  infix 4 _≡_ _≢_

  data _≡_ {a : Set} (x : a) : a → Set where
    refl : x ≡ x

  {-# BUILTIN EQUALITY _≡_ #-}
  {-# BUILTIN REFL refl #-}

  -- Nonequality.

  _≢_ : {a : Set} → a → a → Set
  x ≢ y = ¬ x ≡ y

------------------------------------------------------------------------
-- Equivalence relations

-- The preorders of this library are defined in terms of an underlying
-- equivalence relation, and hence equivalence relations are not
-- defined in terms of preorders.

record IsEquivalence {a : Set} (_≈_ : Rel a) : Set where
  field
    refl  : Reflexive _≈_
    sym   : Symmetric _≈_
    trans : Transitive _≈_

  reflexive : Dummy._≡_ ⇒ _≈_
  reflexive Dummy.refl = refl

open Dummy public


open import Agda.Builtin.List

map : ∀ {a b} {A : Set a} {B : Set b} → (A → B) → List A → List B
map f []       = []
map f (x ∷ xs) = f x ∷ map f xs

foldr : ∀ {a b} {A : Set a} {B : Set b} → (A → B → B) → B → List A → B
foldr c n []       = n
foldr c n (x ∷ xs) = c x (foldr c n xs)

data Rose (A : Set) : Set where
  leaf : (a : A) → Rose A
  node : (rs : List (Rose A)) → Rose A

record IsSeq (A S : Set) : Set where
  field
    nil : S
    sg  : (a : A) → S
    _∙_ : (s t : S) → S

  concat : (ss : List S) → S
  concat = foldr _∙_ nil

open IsSeq {{...}}

{-# TERMINATING #-}
flatten : ∀{A S} {{_ : IsSeq A S}} → Rose A → S
flatten (leaf a) = sg a
flatten (node rs) = concat (map flatten rs)


{-# OPTIONS --safe --warning=error --without-K #-}

open import LogicalFormulae
open import Groups.Lemmas
open import Groups.Definition
open import Groups.Subgroups.Definition
open import Setoids.Setoids
open import Sets.EquivalenceRelations
open import Rings.Definition

open import Agda.Primitive using (Level; lzero; lsuc; _⊔_)

module Rings.Ideals.Definition {a b : _} {A : Set a} {S : Setoid {a} {b} A} {_+_ _*_ : A → A → A} (R : Ring S _+_ _*_) where

open Ring R
open Setoid S
open Equivalence eq
open Group additiveGroup

open import Rings.Lemmas R
open import Rings.Divisible.Definition R

record Ideal {c : _} (pred : A → Set c) : Set (a ⊔ b ⊔ c) where
  field
    isSubgroup : Subgroup additiveGroup pred
    accumulatesTimes : {x : A} → {y : A} → pred x → pred (x * y)
  closedUnderPlus = Subgroup.closedUnderPlus isSubgroup
  closedUnderInverse = Subgroup.closedUnderInverse isSubgroup
  containsIdentity = Subgroup.containsIdentity isSubgroup
  isSubset = Subgroup.isSubset isSubgroup
  predicate = pred

generatedIdealPred : A → A → Set (a ⊔ b)
generatedIdealPred a b = a ∣ b

generatedIdeal : (a : A) → Ideal (generatedIdealPred a)
Subgroup.isSubset (Ideal.isSubgroup (generatedIdeal a)) {x} {y} x=y (c , prC) = c , transitive prC x=y
Subgroup.closedUnderPlus (Ideal.isSubgroup (generatedIdeal a)) {g} {h} (c , prC) (d , prD) = (c + d) , transitive *DistributesOver+ (+WellDefined prC prD)
Subgroup.containsIdentity (Ideal.isSubgroup (generatedIdeal a)) = 0G , timesZero
Subgroup.closedUnderInverse (Ideal.isSubgroup (generatedIdeal a)) {g} (c , prC) = inverse c , transitive ringMinusExtracts (inverseWellDefined additiveGroup prC)
Ideal.accumulatesTimes (generatedIdeal a) {x} {y} (c , prC) = (c * y) , transitive *Associative (*WellDefined prC reflexive)


module Warshall
  (X   : Set)
  ((≤) : X -> X -> Prop)
  -- and axioms...
  where

id : {A:Set} -> A -> A
id x = x

(∘) : {A B C:Set} -> (B -> C) -> (A -> B) -> A -> C
f ∘ g = \x -> f (g x)

-- Natural numbers --------------------------------------------------------

data Nat : Set where
  zero : Nat
  suc  : Nat -> Nat

(+) : Nat -> Nat -> Nat
zero  + m = m
suc n + m = suc (n + m)

-- Finite sets ------------------------------------------------------------

data Zero : Set where

data Suc (A:Set) : Set where
  fzero_ : Suc A
  fsuc_  : A -> Suc A

mutual

  data Fin (n:Nat) : Set where
    finI : Fin_ n -> Fin n

  Fin_ : Nat -> Set
  Fin_  zero   = Zero
  Fin_ (suc n) = Suc (Fin n)

fzero : {n:Nat} -> Fin (suc n)
fzero = finI fzero_

fsuc : {n:Nat} -> Fin n -> Fin (suc n)
fsuc i = finI (fsuc_ i)

finE : {n:Nat} -> Fin n -> Fin_ n
finE (finI i) = i

infixr 15 ::

-- Vectors ----------------------------------------------------------------

data Nil : Set where
  nil_ : Nil

data Cons (Xs:Set) : Set where
  cons_ : X -> Xs -> Cons Xs

mutual

  data Vec (n:Nat) : Set where
    vecI : Vec_ n -> Vec n

  Vec_ : Nat -> Set
  Vec_  zero   = Nil
  Vec_ (suc n) = Cons (Vec n)

nil : Vec zero
nil = vecI nil_

(::) : {n:Nat} -> X -> Vec n -> Vec (suc n)
x :: xs = vecI (cons_ x xs)

vecE : {n:Nat} -> Vec n -> Vec_ n
vecE (vecI xs) = xs

vec : (n:Nat) -> X -> Vec n
vec  zero   _ = nil
vec (suc n) x = x :: vec n x

map : {n:Nat} -> (X -> X) -> Vec n -> Vec n
map {zero}  f (vecI nil_)	  = nil
map {suc n} f (vecI (cons_ x xs)) = f x :: map f xs

(!) : {n:Nat} -> Vec n -> Fin n -> X
(!) {suc n} (vecI (cons_ x _ )) (finI fzero_)    = x
(!) {suc n} (vecI (cons_ _ xs)) (finI (fsuc_ i)) = xs ! i

upd : {n:Nat} -> Fin n -> X -> Vec n -> Vec n
upd {suc n} (finI fzero_)    x (vecI (cons_ _ xs)) = x :: xs
upd {suc n} (finI (fsuc_ i)) x (vecI (cons_ y xs)) = y :: upd i x xs

tabulate : {n:Nat} -> (Fin n -> X) -> Vec n
tabulate {zero}  f = nil
tabulate {suc n} f = f fzero :: tabulate (\x -> f (fsuc x))

postulate
  (===) : {n:Nat} -> Vec n -> Vec n -> Prop

module Proof
    (F : {n:Nat} -> Vec n -> Vec n)
    -- and axioms...
    where

  stepF : {n:Nat} -> Fin n -> Vec n -> Vec n
  stepF i xs = upd i (F xs ! i) xs

  unsafeF' : {n:Nat} -> Nat -> Vec (suc n) -> Vec (suc n)
  unsafeF' zero    = id
  unsafeF' (suc m) = unsafeF' m ∘ stepF fzero

  unsafeF : {n:Nat} -> Vec n -> Vec n
  unsafeF {zero}  = id
  unsafeF {suc n} = unsafeF' (suc n)

  thm : {n:Nat} -> (xs:Vec n) -> F xs === unsafeF xs
  thm = ?


{-# OPTIONS --safe --warning=error --without-K #-}

open import Sets.EquivalenceRelations
open import Setoids.Setoids
open import Agda.Primitive using (Level; lzero; lsuc; _⊔_)

module Groups.Definition where

record Group {lvl1 lvl2} {A : Set lvl1} (S : Setoid {lvl1} {lvl2} A) (_·_ : A → A → A) : Set (lsuc lvl1 ⊔ lvl2) where
  open Setoid S
  field
    +WellDefined : {m n x y : A} → (m ∼ x) → (n ∼ y) → (m · n) ∼ (x · y)
    0G : A
    inverse : A → A
    +Associative : {a b c : A} → (a · (b · c)) ∼ (a · b) · c
    identRight : {a : A} → (a · 0G) ∼ a
    identLeft : {a : A} → (0G · a) ∼ a
    invLeft : {a : A} → (inverse a) · a ∼ 0G
    invRight : {a : A} → a · (inverse a) ∼ 0G
  +Associative' : {a b c : A} → ((a · b) · c) ∼ (a · (b · c))
  +Associative' = Equivalence.symmetric (Setoid.eq S) +Associative
  +WellDefinedLeft : {m x n : A} → (m ∼ n) → (m · x) ∼ (n · x)
  +WellDefinedLeft m=n = +WellDefined m=n (Equivalence.reflexive (Setoid.eq S))
  +WellDefinedRight : {m x y : A} → (x ∼ y) → (m · x) ∼ (m · y)
  +WellDefinedRight x=y = +WellDefined (Equivalence.reflexive (Setoid.eq S)) x=y


------------------------------------------------------------------------
-- Digits and digit expansions
------------------------------------------------------------------------

module Data.Digit where

open import Data.Nat
open import Data.Nat.Properties
open SemiringSolver
open import Data.Fin as Fin using (Fin; zero; suc; toℕ)
open import Relation.Nullary.Decidable
open import Data.Char using (Char)
open import Data.List
open import Data.Vec as Vec using (Vec; _∷_; [])
open import Induction.Nat
open import Data.Nat.DivMod
open ≤-Reasoning
open import Relation.Binary.PropositionalEquality
open import Data.Function

------------------------------------------------------------------------
-- A boring lemma

private

  lem : ∀ x k r → 2 + x ≤′ r + (1 + x) * (2 + k)
  lem x k r = ≤⇒≤′ $ begin
    2 + x
      ≤⟨ m≤m+n _ _ ⟩
    2 + x + (x + (1 + x) * k + r)
      ≡⟨ solve 3 (λ x r k → con 2 :+ x :+ (x :+ (con 1 :+ x) :* k :+ r)
                              :=
                            r :+ (con 1 :+ x) :* (con 2 :+ k))
                 refl x r k ⟩
    r + (1 + x) * (2 + k)
      ∎

------------------------------------------------------------------------
-- Digits

-- Digit b is the type of digits in base b.

Digit : ℕ → Set
Digit b = Fin b

-- Some specific digit kinds.

Decimal = Digit 10
Bit     = Digit 2

-- Some named digits.

0b : Bit
0b = zero

1b : Bit
1b = suc zero

------------------------------------------------------------------------
-- Showing digits

-- The characters used to show the first 16 digits.

digitChars : Vec Char 16
digitChars =
  '0' ∷ '1' ∷ '2' ∷ '3' ∷ '4' ∷ '5' ∷ '6' ∷ '7' ∷ '8' ∷ '9' ∷
  'a' ∷ 'b' ∷ 'c' ∷ 'd' ∷ 'e' ∷ 'f' ∷ []

-- showDigit shows digits in base ≤ 16.

showDigit : ∀ {base} {base≤16 : True (base ≤? 16)} →
            Digit base → Char
showDigit {base≤16 = base≤16} d =
  Vec.lookup (Fin.inject≤ d (witnessToTruth base≤16)) digitChars

------------------------------------------------------------------------
-- Digit expansions

-- fromDigits takes a digit expansion of a natural number, starting
-- with the _least_ significant digit, and returns the corresponding
-- natural number.

fromDigits : ∀ {base} → List (Fin base) → ℕ
fromDigits        []       = 0
fromDigits {base} (d ∷ ds) = toℕ d + fromDigits ds * base

-- toDigits b n yields the digits of n, in base b, starting with the
-- _least_ significant digit.
--
-- Note that the list of digits is always non-empty.
--
-- This function should be linear in n, if optimised properly (see
-- Data.Nat.DivMod).

data Digits (base : ℕ) : ℕ → Set where
  digits : (ds : List (Fin base)) → Digits base (fromDigits ds)

toDigits : (base : ℕ) {base≥2 : True (2 ≤? base)} (n : ℕ) →
           Digits base n
toDigits zero       {base≥2 = ()} _
toDigits (suc zero) {base≥2 = ()} _
toDigits (suc (suc k)) n = <-rec Pred helper n
  where
  base = suc (suc k)
  Pred = Digits base

  cons : ∀ {n} (r : Fin base) → Pred n → Pred (toℕ r + n * base)
  cons r (digits ds) = digits (r ∷ ds)

  helper : ∀ n → <-Rec Pred n → Pred n
  helper n rec with n divMod base
  helper .(toℕ r + 0     * base) rec | result zero    r = digits (r ∷ [])
  helper .(toℕ r + suc x * base) rec | result (suc x) r =
    cons r (rec (suc x) (lem (pred (suc x)) k (toℕ r)))

theDigits : (base : ℕ) {base≥2 : True (2 ≤? base)} (n : ℕ) →
            List (Fin base)
theDigits base {base≥2} n       with toDigits base {base≥2} n
theDigits base .(fromDigits ds) | digits ds = ds


module Golden.FstSnd where

open import Agda.Builtin.Nat

data Tuple a b : Set where
  Tup : a -> b -> Tuple a b

fst : {a b : Set} -> Tuple a b -> a
fst (Tup x x₁) = x
snd : {a b : Set} -> Tuple a b -> b
snd (Tup x b) = b

tup1 : Tuple Nat Nat
tup1 = Tup 0 1

a = fst tup1
b = snd tup1


{-# OPTIONS --without-K --safe #-}
module Experiment.Transitive where

open import Level
open import Relation.Binary
open import Relation.Binary.Construct.Closure.Transitive
open import Relation.Binary.PropositionalEquality as ≡ using (_≡_)

insert-permutation : ∀ x xs → insert x xs ↭ x ∷ xs
insert-pres-Sorted : ∀ x {xs} → Sorted xs → Sorted (insert x xs)
sort-Sorted        : ∀ xs → Sorted (sort xs)
sort-permutation   : ∀ xs → sort xs ↭ xs

private
  variable
    a b r : Level
    A B : Set a
    R S : Rel A r

fold : Transitive R → A [ R ]⁺ B → R A B
fold R-trans [ x∼y ]         = x∼y
fold R-trans (x ∼⁺⟨ x₁ ⟩ x₂) = R-trans (fold R-trans x₁) (fold R-trans x₂)

reverse : Symmetric R → A [ R ]⁺ B → B [ R ]⁺ A
reverse R-sym [ x∼y ]         = [ R-sym x∼y ]
reverse R-sym (x ∼⁺⟨ x₁ ⟩ x₂) = _ ∼⁺⟨ reverse R-sym x₂ ⟩ reverse R-sym x₁

fold-reverse : (R-trans : Transitive R) (R-sym : Symmetric R) (xs : A [ R ]⁺ B) →
              (∀ {a b c} (x : R b c) (y : R a b) →
                R-trans (R-sym x) (R-sym y) ≡ R-sym (R-trans y x)) →
              fold R-trans (reverse R-sym xs) ≡ R-sym (fold R-trans xs)
fold-reverse R-trans R-sym [ x∼y ]           homo = ≡.refl
fold-reverse R-trans R-sym (x ∼⁺⟨ xs₁ ⟩ xs₂) homo = begin
  R-trans (fold R-trans (reverse R-sym xs₂)) (fold R-trans (reverse R-sym xs₁))
    ≡⟨ ≡.cong₂ R-trans (fold-reverse R-trans R-sym xs₂ homo) (fold-reverse R-trans R-sym xs₁ homo) ⟩
  R-trans (R-sym (fold R-trans xs₂)) (R-sym (fold R-trans xs₁))
    ≡⟨ homo (fold R-trans xs₂) (fold R-trans xs₁) ⟩
  R-sym (R-trans (fold R-trans xs₁) (fold R-trans xs₂))
    ∎
  where
  open ≡.≡-Reasoning

-- map :
-- Star⇔ReflexiveTransitive : Star R x y ↔ Reflexive (Transitive R x y)

-- map-reverse : (RS : R ⊆ S) (R-sym : Symmetric R) (S-sym : Symmetric S) xs → map RS (reverse R-sym xs) ≡ reverse S-sym (map RS xs)
-- map-reverse R-sym xs = ?

-- ∘ᵢ-tc (reverse f⁺) ∘ᵢ ∘ᵢ-tc f⁺ ≃ ≅.refl


{-

Definition of finitely indexed types

A type is finitely indexed if, for some `n`, there merely exists a
surjective function from `Fin n` to it. Note that a type doesn't need
to be a set in order for it to be finitely indexed. For example, the
circle is finitely indexed.

This definition is weaker than `isFinSet`.

-}

{-# OPTIONS --safe #-}

module Cubical.Data.FinInd where

open import Cubical.Data.Nat
open import Cubical.Data.SumFin
open import Cubical.Data.Sigma
open import Cubical.Data.FinSet
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Functions.Surjection
open import Cubical.HITs.PropositionalTruncation as PT
open import Cubical.HITs.S1

private
  variable
    ℓ : Level
    A : Type ℓ

isFinInd : Type ℓ → Type ℓ
isFinInd A = ∃[ n ∈ ℕ ] Fin n ↠ A

isFinSet→isFinInd : isFinSet A → isFinInd A
isFinSet→isFinInd h = PT.elim
  (λ _ → squash)
  (λ equiv →
    ∣ _ , invEq equiv , section→isSurjection (retEq equiv) ∣) (h .snd)

isFinInd-S¹ : isFinInd S¹
isFinInd-S¹ = ∣ 1 , f , isSurjection-f ∣
  where
    f : Fin 1 → S¹
    f _ = base
    isSurjection-f : isSurjection f
    isSurjection-f b = PT.map (λ base≡b → fzero , base≡b) (isConnectedS¹ b)


-- Andreas, 2017-04-26
-- Allow more flexible size assignment.

module _ where

open import Agda.Builtin.Size

module ZeroZero where

  data Nat : Size → Set where
    zero : ∀{i}         → Nat i   -- does not have to be ↑ i
    suc  : ∀{i} → Nat i → Nat (↑ i)

  mon : ∀{i}{j : Size< i} → Nat j → Nat i
  mon x = x

  minus : ∀{i} → Nat i → Nat ∞ → Nat i
  minus x       zero    = x
  minus zero    (suc y) = zero
  minus (suc x) (suc y) = minus x y

  div : ∀{i} → Nat i → Nat ∞ → Nat i
  div zero y = zero
  div (suc x) y = suc (div (minus x y) y)

module DSuc where

  -- Here, the upper least bound for the size is the number itself.

  data Nat : Size → Set where
    zero : ∀{i}         → Nat i
    suc  : ∀{i} → Nat i → Nat (↑ i)
    dsuc : ∀{i} → Nat i → Nat (↑ ↑ i)

  -- Testing subtyping.

  mon : ∀{i}{j : Size< i} → Nat j → Nat i
  mon x = x

  minus : ∀{i} → Nat i → Nat ∞ → Nat i
  minus x        zero     = x
  minus zero     y        = zero
  minus (suc x)  (suc y)  = minus x y
  minus (suc x)  (dsuc y) = minus x (suc y)
  minus (dsuc x) (suc y)  = minus (suc x) y
  minus (dsuc x) (dsuc y) = minus x y

  div : ∀{i} → Nat i → Nat ∞ → Nat i
  div zero     y = zero
  div (suc x)  y = suc (div (minus x y) y)
  div (dsuc x) y = suc (div (minus (suc x) y) y)


open import Data.Nat using (ℕ; zero; suc; _+_; _*_)
open import Data.Product using (∃; _,_)
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym)

+-identity : ∀ (m : ℕ) → m + zero ≡ m
+-identity zero = refl
+-identity (suc m) rewrite +-identity m = refl

+-suc : ∀ (m n : ℕ) → n + suc m ≡ suc (n + m)
+-suc m zero = refl
+-suc m (suc n) rewrite +-suc m n = refl

+-comm : ∀ (m n : ℕ) → m + n ≡ n + m
+-comm zero n rewrite +-identity n = refl
+-comm (suc m) n rewrite +-suc m n | +-comm m n = refl

mutual
  data even : ℕ → Set where
    zero : even zero
    suc : ∀ {n : ℕ} → odd n → even (suc n)
  data odd : ℕ → Set where
    suc : ∀ {n : ℕ} → even n → odd (suc n)

+-lemma : ∀ (m : ℕ) → suc (suc (m + (m + 0))) ≡ suc m + suc (m + 0)
+-lemma m rewrite +-identity m | +-suc m m = refl

mutual
  is-even : ∀ (n : ℕ) → even n → ∃(λ (m : ℕ) → n ≡ 2 * m)
  is-even zero zero =  zero , refl
  is-even (suc n) (suc oddn) with is-odd n oddn
  ... | m , n≡1+2*m rewrite n≡1+2*m | +-lemma m = suc m , refl

  is-odd : ∀ (n : ℕ) → odd n → ∃(λ (m : ℕ) → n ≡ 1 + 2 * m)
  is-odd (suc n) (suc evenn) with is-even n evenn
  ... | m , n≡2*m rewrite n≡2*m = m , refl

+-lemma′ : ∀ (m : ℕ) → suc (suc (m + (m + 0))) ≡ suc m + suc (m + 0)
+-lemma′ m rewrite +-suc (m + 0) m = refl

is-even′ : ∀ (n : ℕ) → even n → ∃(λ (m : ℕ) → n ≡ 2 * m)
is-even′ zero zero =  zero , refl
is-even′ (suc n) (suc oddn) with is-odd n oddn
... | m , n≡1+2*m rewrite n≡1+2*m | +-identity m | +-suc m m = suc m , {!!}


module YonedaLemma where

open import Library
open import Categories
open import Categories.Sets
open import Functors
open import Naturals
open import FunctorCat

HomF[-,_] : ∀{l m}{C : Cat {l}{m}}(X : Cat.Obj C) -> Fun (C Op) (Sets {m})
HomF[-,_] {C = C} B = functor
  (\ X -> Hom X B)
  (\ f g -> comp g f)
  (ext \ _ -> idr)
  (ext \ _ -> sym ass)
  where open Cat C

HomN[-,_] : ∀{l m}{C : Cat {l}{m}}{X Y : Cat.Obj C}(f : Cat.Hom C X Y) ->
            NatT (HomF[-,_] {C = C} X) HomF[-, Y ]
HomN[-,_] {C = C} f = natural
  (comp f)
  (ext \ _ -> ass)
  where open Cat C

y : ∀{l m}(C : Cat {l}{m}) -> Fun C (FunctorCat (C Op) (Sets {m}))
y C = functor
  HomF[-,_]
  HomN[-,_]
  (NatTEq (iext \ _ -> ext \ _ -> idl))
  (NatTEq (iext \ _ -> ext \ _ -> ass))
  where open Cat C

yleminv : ∀{l m}(C : Cat {l}{m})(F : Fun (C Op) (Sets {m}))(X : Cat.Obj C) ->
          NatT (Fun.OMap (y C) X) F -> Fun.OMap F X
yleminv C F X α = NatT.cmp α {X} (Cat.iden C)

ylem : ∀{l m}(C : Cat {l}{m})(F : Fun (C Op) (Sets {m}))(X : Cat.Obj C) ->
       Fun.OMap F X -> NatT (Fun.OMap (y C) X) F
ylem C F X FX = natural
  (\ {X'} f -> HMap f FX)
  (\{X'}{Y}{f} -> ext \ g -> sym (fcong FX (fcomp {f = f}{g = g})) )
  where open Cat C; open Fun F


module Relator.Equals.Proofs where

open import Relator.Equals
open import Structure.Relator.Equivalence
open import Structure.Relator.Properties
open import Structure.Setoid renaming (_≡_ to _≡ₛ_)

instance
  [≡]-reflexivity : ∀{ℓ}{A : Type{ℓ}} → Reflexivity(_≡_ {P = A})
  Reflexivity.proof([≡]-reflexivity) = constant-path

instance
  [≡]-symmetry : ∀{ℓ}{A : Type{ℓ}} → Symmetry(_≡_ {P = A})
  Symmetry.proof([≡]-symmetry) = reversed-path


module Matrix where

open import Data.Nat
open import Data.Vec

Matrix : (A : Set) → ℕ → ℕ → Set
Matrix A m n = Vec (Vec A m) n

transpose : ∀ {A m n} → Matrix A m n → Matrix A n m
transpose [] = replicate []
transpose (xs ∷ xss) = zipWith _∷_ xs (transpose xss)

a = (1 ∷ 2 ∷ 3 ∷ []) ∷ (4 ∷ 5 ∷ 6 ∷ []) ∷ []
b = transpose a


{-# OPTIONS --without-K --safe #-}
open import Categories.Category

-- Definition of Terminal object and some properties

module Categories.Object.Terminal {o ℓ e} (C : Category o ℓ e) where

open import Level

open import Relation.Binary using (IsEquivalence; Setoid)
open import Relation.Binary.PropositionalEquality as ≡ using (_≡_)

open import Categories.Morphism C
open import Categories.Morphism.IsoEquiv C using (_≃_; ⌞_⌟)
open import Categories.Morphism.Reasoning C

open Category C
open HomReasoning

record Terminal : Set (o ⊔ ℓ ⊔ e) where
  field
    ⊤ : Obj
    ! : {A : Obj} → (A ⇒ ⊤)
    !-unique : ∀ {A} → (f : A ⇒ ⊤) → ! ≈ f

  !-unique₂ : ∀ {A} {f g : A ⇒ ⊤} → f ≈ g
  !-unique₂ {A} {f} {g} = begin
    f ≈˘⟨ !-unique f ⟩
    ! ≈⟨ !-unique g ⟩
    g ∎
    where open HomReasoning

  ⊤-id : (f : ⊤ ⇒ ⊤) → f ≈ id
  ⊤-id _ = !-unique₂

open Terminal

from-⊤-is-Mono : ∀ {A : Obj} {t : Terminal} → (f : ⊤ t ⇒ A) → Mono f
from-⊤-is-Mono {_} {t} _ = λ _ _ _ → !-unique₂ t

up-to-iso : (t₁ t₂ : Terminal) → ⊤ t₁ ≅ ⊤ t₂
up-to-iso t₁ t₂ = record
  { from = ! t₂
  ; to   = ! t₁
  ; iso  = record { isoˡ = ⊤-id t₁ _; isoʳ = ⊤-id t₂ _ }
  }

transport-by-iso : (t : Terminal) → ∀ {X} → ⊤ t ≅ X → Terminal
transport-by-iso t {X} t≅X = record
  { ⊤        = X
  ; !        = from ∘ ! t
  ; !-unique = λ h → begin
    from ∘ ! t     ≈⟨ refl⟩∘⟨ !-unique t (to ∘ h)  ⟩
    from ∘ to ∘ h  ≈⟨ cancelˡ isoʳ ⟩
    h              ∎
  }
  where open _≅_ t≅X

up-to-iso-unique : ∀ t t′ → (i : ⊤ t ≅ ⊤ t′) → up-to-iso t t′ ≃ i
up-to-iso-unique t t′ i = ⌞ !-unique t′ _ ⌟

up-to-iso-invˡ : ∀ {t X} {i : ⊤ t ≅ X} → up-to-iso t (transport-by-iso t i) ≃ i
up-to-iso-invˡ {t} {i = i} = up-to-iso-unique t (transport-by-iso t i) i

up-to-iso-invʳ : ∀ {t t′} → ⊤ (transport-by-iso t (up-to-iso t t′)) ≡ ⊤ t′
up-to-iso-invʳ {t} {t′} = ≡.refl


module Issue558b where

data Nat : Set where
  Z : Nat
  S : Nat → Nat

data _≡_ {A : Set} (a : A) : A → Set where
  Refl : a ≡ a

plus : Nat → Nat → Nat
plus Z n = n
plus (S n) m = S (plus n m)

data Addable (τ : Set) : Set where
  addable : (τ → τ → τ) → Addable τ

plus' : {τ : Set} → Addable τ → τ → τ → τ
plus' (addable p) = p

record ⊤ : Set where

module AddableM {τ : Set} {a : ⊤} (a : Addable τ) where
  _+_ : τ → τ → τ
  _+_ = plus' a

-- record Addable (τ : Set) : Set where
--  constructor addable
--  field
--   _+_ : τ → τ → τ

open module AddableIFS {t : Set} {a : ⊤} {{r : Addable t}} = AddableM {t} r

data CommAddable (τ : Set) {a : ⊤} : Set where
 commAddable : (addable : Addable τ) → ((a b : τ) → (a + b) ≡ (b + a)) → CommAddable τ

private
  addableCA' : {τ : Set} (ca : CommAddable τ) → Addable τ
  addableCA' (commAddable a _) = a

  comm' : {τ : Set} (ca : CommAddable τ) →
          let a = addableCA' ca in (a b : τ) → (a + b) ≡ (b + a)
  comm' (commAddable _ c) = c

module CommAddableM {τ : Set} {a : ⊤} (ca : CommAddable τ) where
  addableCA : Addable τ
  addableCA = addableCA' ca

  comm : (a b : τ) → (a + b) ≡ (b + a)
  comm = comm' ca

natAdd : Addable Nat
natAdd = addable plus

postulate commPlus : (a b : Nat) → plus a b ≡ plus b a

commNatAdd : CommAddable Nat
commNatAdd = commAddable natAdd commPlus

open CommAddableM {{...}}

test : (Z + Z) ≡ Z
test = comm Z Z

a : {x y : Nat} → (S (S Z) + (x + y)) ≡ ((x + y) + S (S Z))
a {x}{y} = comm (S (S Z)) (x + y)


module L.Base.Nat.Core where

-- Introducing Nat type with constructors zero and succ
data Nat : Set where
  zero : Nat
  succ : Nat → Nat

-- Enabling the usage of numerals in code.
{-# BUILTIN NATURAL Nat #-}

ind : ∀{c} (C : Nat → Set c)
  → C zero → ((x : Nat) → C x → C (succ x))
  → (n : Nat) → C n
ind C cₒ cₛ  zero    = cₒ
ind C cₒ cₛ (succ n) = cₛ n (ind C cₒ cₛ n)


open import Structure.Setoid
open import Structure.Category
open import Type

module Structure.Category.Monoid
  {ℓₒ ℓₘ ℓₑ}
  {Obj : Type{ℓₒ}}
  {Morphism : Obj → Obj → Type{ℓₘ}}
  ⦃ morphism-equiv : ∀{x y} → Equiv{ℓₑ}(Morphism x y) ⦄
  (cat : Category(Morphism))
  where

open import Logic.Predicate
open import Structure.Categorical.Properties
open import Structure.Operator.Monoid
open import Structure.Operator.Properties

open Category(cat)

-- A monoid constructed from a category for a specific object.
monoid : ∀{x} → Monoid(_∘_ {x = x})
Monoid.binary-operator monoid = binaryOperator
Associativity.proof (Monoid.associativity monoid) = Morphism.associativity(_∘_)
∃.witness (Monoid.identity-existence monoid) = id
Identityₗ.proof (Identity.left  (∃.proof (Monoid.identity-existence monoid))) = Morphism.identityₗ(_∘_)(id)
Identityᵣ.proof (Identity.right (∃.proof (Monoid.identity-existence monoid))) = Morphism.identityᵣ(_∘_)(id)


{-# OPTIONS --without-K --safe #-}

open import Categories.Category
open import Categories.Functor

-- Street fibration, which is the version of fibration that respects the principle of equivalence.
-- https://ncatlab.org/nlab/show/Grothendieck+fibration#StreetFibration
module Categories.Functor.Fibration {o ℓ e o′ ℓ′ e′} {C : Category o ℓ e} {D : Category o′ ℓ′ e′} (F : Functor C D) where

open import Level

open import Categories.Morphism D using (_≅_)
open import Categories.Morphism.Cartesian using (Cartesian)

private
  module C = Category C
  module D = Category D
  open Functor F

record Fibration : Set (levelOfTerm F) where
  field
    universal₀ : ∀ {A B} (f : A D.⇒ F₀ B) → C.Obj
    universal₁ : ∀ {A B} (f : A D.⇒ F₀ B) → universal₀ f C.⇒ B
    iso        : ∀ {A B} (f : A D.⇒ F₀ B) → F₀ (universal₀ f) ≅ A

  module iso {A B} (f : A D.⇒ F₀ B) = _≅_ (iso f)

  field
    commute   : ∀ {A B} (f : A D.⇒ F₀ B) → f D.∘ iso.from f D.≈ F₁ (universal₁ f)
    cartesian : ∀ {A B} (f : A D.⇒ F₀ B) → Cartesian F (universal₁ f)

  module cartesian {A B} (f : A D.⇒ F₀ B) = Cartesian (cartesian f)


module NatCat where

open import Relation.Binary.PropositionalEquality

-- If you can show that a relation only ever has one inhabitant
-- you get the category laws for free
module
  EasyCategory
  (obj : Set)
  (_⟶_ : obj → obj → Set)
  (_∘_ : ∀ {x y z} → x ⟶ y → y ⟶ z → x ⟶ z)
  (id : ∀ x → x ⟶ x)
  (single-inhabitant : (x y : obj) (r s : x ⟶ y) → r ≡ s)
  where

  idʳ : ∀ x y (r : x ⟶ y) → r ∘ id y ≡ r
  idʳ x y r = single-inhabitant x y (r ∘ id y) r

  idˡ : ∀ x y (r : x ⟶ y) → id x ∘ r ≡ r
  idˡ x y r = single-inhabitant x y (id x ∘ r) r

  ∘-assoc : ∀ w x y z (r : w ⟶ x) (s : x ⟶ y) (t : y ⟶ z) → (r ∘ s) ∘ t ≡ r ∘ (s ∘ t)
  ∘-assoc w x y z r s t = single-inhabitant w z ((r ∘ s) ∘ t) (r ∘ (s ∘ t))

open import Data.Nat

same : (x y : ℕ) (r s : x ≤ y) → r ≡ s
same .0 y z≤n z≤n = refl
same .(suc m) .(suc n) (s≤s {m} {n} r) (s≤s s) = cong s≤s (same m n r s)

≤-trans : ∀ x y z → x ≤ y → y ≤ z → x ≤ z
≤-trans .0 y z z≤n s = z≤n
≤-trans .(suc m) .(suc n) .(suc n₁) (s≤s {m} {n} r) (s≤s {.n} {n₁} s) = s≤s (≤-trans m n n₁ r s)

≤-refl : ∀ x → x ≤ x
≤-refl zero = z≤n
≤-refl (suc x) = s≤s (≤-refl x)

module Nat-EasyCategory = EasyCategory ℕ _≤_ (λ {x}{y}{z} → ≤-trans x y z) ≤-refl same


module Dave.Embedding where
    open import Dave.Functions
    open import Dave.Equality
    open import Dave.Isomorphism

    infix 0 _≲_
    record _≲_ (A B : Set) : Set where
        field
            to : A → B
            from : B → A
            from∘to : ∀ (x : A) → from (to x) ≡ x

    open _≲_

    ≲-refl : ∀ {A : Set} → A ≲ A
    ≲-refl = record
        {
            to = λ a → a ;
            from = λ b → b ;
            from∘to = λ a → refl
        }

    ≲-trans : ∀ {A B C : Set} → A ≲ B → B ≲ C → A ≲ C
    ≲-trans A≲B B≲C = record
        {
            to = λ a → to B≲C (to A≲B a) ;
            from = λ c → from A≲B (from B≲C c) ;
            from∘to = λ a → begin
                (from A≲B ∘ from B≲C) ((to B≲C ∘ to A≲B) a) ≡⟨⟩
                from A≲B (from B≲C (to B≲C (to A≲B a))) ≡⟨ cong (from A≲B) (from∘to B≲C (to A≲B a)) ⟩
                from A≲B (to A≲B a) ≡⟨ from∘to A≲B a ⟩
                a ∎
        }

    ≲-antisym : ∀ {A B : Set}
        → (A≲B : A ≲ B)
        → (B≲A : B ≲ A)
        → (to A≲B ≡ from B≲A)
        → (from A≲B ≡ to B≲A)
        → A ≃ B
    ≲-antisym A≲B B≲A to≡from from≡to = record
        {
            to = λ a → to A≲B a ;
            from = λ b → from A≲B b ;
            from∘to = from∘to A≲B;
            to∘from = λ b → begin
                to A≲B (from A≲B b) ≡⟨ cong (λ x → (to A≲B (x b))) from≡to ⟩
                to A≲B (to B≲A b) ≡⟨ cong-app to≡from (to B≲A b) ⟩
                from B≲A (to B≲A b) ≡⟨ from∘to B≲A b ⟩
                b ∎
        }

    module ≲-Reasoning where

        infix  1 ≲-begin_
        infixr 2 _≲⟨_⟩_
        infix  3 _≲-∎

        ≲-begin_ : ∀ {A B : Set}
            → A ≲ B
            -----
            → A ≲ B
        ≲-begin A≲B = A≲B

        _≲⟨_⟩_ : ∀ (A : Set) {B C : Set}
            → A ≲ B
            → B ≲ C
            -----
            → A ≲ C
        A ≲⟨ A≲B ⟩ B≲C = ≲-trans A≲B B≲C

        _≲-∎ : ∀ (A : Set)
            -----
            → A ≲ A
        A ≲-∎ = ≲-refl

    open ≲-Reasoning

    ≃-implies-≲ : ∀ {A B : Set} → A ≃ B → A ≲ B
    ≃-implies-≲ A≃B = record
        {
            to = _≃_.to A≃B;
            from = _≃_.from A≃B;
            from∘to = _≃_.from∘to A≃B
        }


{-# OPTIONS --safe --warning=error --without-K #-}

open import LogicalFormulae
open import Numbers.Naturals.Semiring
open import Numbers.Integers.RingStructure.Ring
open import Rings.IntegralDomains.Definition

module Numbers.Integers.RingStructure.IntegralDomain where

intDom : (a b : ℤ) → a *Z b ≡ nonneg 0 → (a ≡ nonneg 0 → False) → (b ≡ nonneg 0)
intDom (nonneg zero) (nonneg b) x a!=0 = exFalso (a!=0 x)
intDom (nonneg (succ a)) (nonneg zero) a!=0 _ = refl
intDom (nonneg zero) (negSucc b) pr a!=0 = exFalso (a!=0 pr)
intDom (negSucc a) (nonneg zero) _ _ = refl

ℤIntDom : IntegralDomain ℤRing
IntegralDomain.intDom ℤIntDom {a} {b} = intDom a b
IntegralDomain.nontrivial ℤIntDom ()


module CH where

data ℕ : Set where
  zero : ℕ
  succ : ℕ → ℕ

infixl 6 _+_
_+_ : ℕ → ℕ → ℕ
zero      + m  = m
(succ n)  + m  = succ (n + m)

infix 4 _≡_
data _≡_ {A : Set} (x : A) : A → Set where
  refl : x ≡ x

{-
t1 : {n : ℕ} -> zero ≡ n
t1 = refl
-}

data _==_ {A : Set} : A → A → Set where
  refl' : (a : A) → a == a

sym : ∀ x y → x == y → y == x
sym .a .a (refl' a) = refl' a


module product where

open import level
open import unit public

----------------------------------------------------------------------
-- types
----------------------------------------------------------------------

data Σ {ℓ ℓ'} (A : Set ℓ) (B : A → Set ℓ') : Set (ℓ ⊔ ℓ') where
  _,_ : (a : A) → (b : B a) → Σ A B

data Σi {ℓ ℓ'} (A : Set ℓ) (B : A → Set ℓ') : Set (ℓ ⊔ ℓ') where
  ,_ : {a : A} → (b : B a) → Σi A B
_×_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
A × B = Σ A (λ x → B)

_i×_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
A i× B = Σi A (λ x → B)

----------------------------------------------------------------------
-- syntax
----------------------------------------------------------------------

infix 2 Σ-syntax
infixr 3 _×_ _i×_ _∧_
infixr 4 _,_
infix  4 ,_

-- This provides the syntax: Σ[ x ∈ A ] B it is taken from the Agda
-- standard library. This style is nice when working in Set.
Σ-syntax : ∀ {a b} (A : Set a) → (A → Set b) → Set (a ⊔ b)
Σ-syntax = Σ

syntax Σ-syntax A (λ x → B) = Σ[ x ∈ A ] B

----------------------------------------------------------------------
-- operations
----------------------------------------------------------------------
fst : ∀ {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} → A × B → A
fst (a , b) = a

snd : ∀ {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} → A × B → B
snd (a , b) = b

trans-× : ∀{ℓ₁ ℓ₂ ℓ₃}
         {A : Set ℓ₁}{B : Set ℓ₂}
         {C : Set ℓ₃}
       → (C → A)
       → (C → B)
       → (C → A × B)
trans-× f g c = f c , g c

⟨_,_⟩ : ∀{ℓ₁ ℓ₂ ℓ₃ ℓ₄}
         {A : Set ℓ₁}{B : Set ℓ₂}
         {C : Set ℓ₃}{D : Set ℓ₄}
       → (A → C)
       → (B → D)
       → (A × B → C × D)
⟨ f , g ⟩ (a , b) = f a , g b

twist-× : ∀{ℓ₁ ℓ₂}
     {A : Set ℓ₁}{B : Set ℓ₂}
    → A × B
    → B × A
twist-× (a , b) = (b , a)

rl-assoc-× : ∀{ℓ₁ ℓ₂ ℓ₃}
             {A : Set ℓ₁}{B : Set ℓ₂}
             {C : Set ℓ₃}
           → A × (B × C)
           → (A × B) × C
rl-assoc-× (a , b , c) =  ((a , b) , c)

lr-assoc-× : ∀{ℓ₁ ℓ₂ ℓ₃}
             {A : Set ℓ₁}{B : Set ℓ₂}
             {C : Set ℓ₃}
           → (A × B) × C
           → A × (B × C)
lr-assoc-× ((a , b) , c) = (a , b , c)

func-× : ∀{ℓ₁ ℓ₂ ℓ₃ ℓ₄}{A : Set ℓ₁}{B : Set ℓ₂}{C : Set ℓ₃}{D : Set ℓ₄} → (A → C) → (B → D) → (A × B) → (C × D)
func-× f g (x , y) = (f x , g y)

×-diag : ∀{ℓ}{X : Set ℓ} → X → X × X
×-diag x = (x , x)

----------------------------------------------------------------------
-- some logical notation
----------------------------------------------------------------------
_∧_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
_∧_ = _×_

∃ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : A → Set ℓ') → Set (ℓ ⊔ ℓ')
∃ = Σ

∃i : ∀ {ℓ ℓ'} (A : Set ℓ) (B : A → Set ℓ') → Set (ℓ ⊔ ℓ')
∃i = Σi


{-# OPTIONS --without-K --safe #-}

module Categories.NaturalTransformation.NaturalIsomorphism.Functors where

open import Level

open import Categories.Category
open import Categories.Category.Construction.Functors
open import Categories.Functor
open import Categories.NaturalTransformation.NaturalIsomorphism

import Categories.Morphism as Mor

private
  variable
    o ℓ e : Level
    C D : Category o ℓ e

-- isomorphism in Functors category is the same as natural isomorphism
module _ {F G : Functor C D} where
  open Mor (Functors C D)

  Functors-iso⇒NI : F ≅ G → NaturalIsomorphism F G
  Functors-iso⇒NI F≅G = record
    { F⇒G = from
    ; F⇐G = to
    ; iso = λ X → record
      { isoˡ = isoˡ
      ; isoʳ = isoʳ
      }
    }
    where open Mor._≅_ F≅G

  NI⇒Functors-iso : NaturalIsomorphism F G → F ≅ G
  NI⇒Functors-iso α = record
    { from = F⇒G
    ; to   = F⇐G
    ; iso  = record
      { isoˡ = isoˡ (iso _)
      ; isoʳ = isoʳ (iso _)
      }
    }
    where open NaturalIsomorphism α
          open Mor.Iso


module Prelude.Functor where

open import Agda.Primitive
open import Prelude.Function
open import Prelude.Equality

record Functor {a b} (F : Set a → Set b) : Set (lsuc a ⊔ b) where
  infixl 4 _<$>_ _<$_
  field
    fmap : ∀ {A B} → (A → B) → F A → F B
  _<$>_ = fmap

  _<$_ : ∀ {A B} → A → F B → F A
  x <$ m = fmap (const x) m

open Functor {{...}} public

{-# DISPLAY Functor.fmap  _ = fmap  #-}
{-# DISPLAY Functor._<$>_ _ = _<$>_ #-}
{-# DISPLAY Functor._<$_  _ = _<$_  #-}

-- Level polymorphic functors
record Functor′ {a b} (F : ∀ {a} → Set a → Set a) : Set (lsuc (a ⊔ b)) where
  infixl 4 _<$>′_ _<$′_
  field
    fmap′ : {A : Set a} {B : Set b} → (A → B) → F A → F B
  _<$>′_ = fmap′

  _<$′_ : {A : Set a} {B : Set b} → B → F A → F B
  x <$′ m = fmap′ (const x) m

open Functor′ {{...}} public

infixr 0 flip-fmap
syntax flip-fmap a (λ x → y) = for x ← a return y
flip-fmap : ∀ {a b} {F : Set a → Set b} {{_ : Functor F}} {A B} → F A → (A → B) → F B
flip-fmap x f = fmap f x

infixr 0 caseF_of_
caseF_of_ : ∀ {a b} {F : Set a → Set b} {{_ : Functor F}} {A B} → F A → (A → B) → F B
caseF_of_ x f = fmap f x

for = caseF_of_

{-# INLINE for #-}
{-# INLINE caseF_of_ #-}

-- Congruence for _<$>_ --

infixl 4 _=$=_ _=$=′_
_=$=_ : ∀ {a b} {A B : Set a} {F : Set a → Set b} {{_ : Functor F}} {x y : F A}
          (f : A → B) → x ≡ y → (f <$> x) ≡ (f <$> y)
f =$= refl = refl

_=$=′_ : ∀ {a b} {A : Set a} {B : Set b} {F : ∀ {a} → Set a → Set a} {{_ : Functor′ F}} {x y : F A}
          (f : A → B) → x ≡ y → (f <$>′ x) ≡ (f <$>′ y)
f =$=′ refl = refl


open import Coinduction using ( ♭ )
open import Data.Product using ( _,_ )
open import Relation.Binary using ( Poset )
open import Relation.Binary.PropositionalEquality using ( _≡_ ; refl ; sym ; trans ; cong ; subst₂ ) renaming ( setoid to ≡-setoid )
open import System.IO.Transducers using ( _⇒_ ; inp ; out ; done ; ⟦_⟧ ; _≃_ ; _≲_ ; _⟫_ )
open import System.IO.Transducers.Session using ( Session )
open import System.IO.Transducers.Trace using ( Trace ; [] ; _∷_ ; _⊑_ )
open import System.IO.Transducers.Properties.Category using ( ⟫-semantics )

import Relation.Binary.PartialOrderReasoning

module System.IO.Transducers.Properties.TwoCategory where

-- The category is poset-enriched, with order inherited from prefix order on traces.

-- Reflexivity

⊑-refl : ∀ {S} (as : Trace S) → (as ⊑ as)
⊑-refl [] = []
⊑-refl (a ∷ as) = (a ∷ ⊑-refl as)

≡-impl-⊑ : ∀ {S} {as bs : Trace S} → (as ≡ bs) → (as ⊑ bs)
≡-impl-⊑ refl = ⊑-refl _

≲-refl : ∀ {S T} (f : Trace S → Trace T) → (f ≲ f)
≲-refl f as = ⊑-refl (f as)

≃-impl-≲ : ∀ {S T} {f g : Trace S → Trace T} → (f ≃ g) → (f ≲ g)
≃-impl-≲ f≃g as = ≡-impl-⊑ (f≃g as)

-- Transitivity

⊑-trans : ∀ {S} {as bs cs : Trace S} → (as ⊑ bs) → (bs ⊑ cs) → (as ⊑ cs)
⊑-trans []       bs        = []
⊑-trans (a ∷ as) (.a ∷ bs) = (a ∷ ⊑-trans as bs)

≲-trans : ∀ {S T} {f g h : Trace S → Trace T} → (f ≲ g) → (g ≲ h) → (f ≲ h)
≲-trans f≲g g≲h as = ⊑-trans (f≲g as) (g≲h as)

-- Antisymmetry

⊑-antisym : ∀ {S} {as bs : Trace S} → (as ⊑ bs) → (bs ⊑ as) → (as ≡ bs)
⊑-antisym [] [] = refl
⊑-antisym (a ∷ as) (.a ∷ bs) = cong (_∷_ a) (⊑-antisym as bs)

≲-antisym : ∀ {S T} {f g : Trace S → Trace T} → (f ≲ g) → (g ≲ f) → (f ≃ g)
≲-antisym f≲g g≲f as = ⊑-antisym (f≲g as) (g≲f as)

-- ⊑ and ≲ form posets

⊑-poset : Session → Poset _ _ _
⊑-poset S = record
  { Carrier = Trace S
  ; _≈_ = _≡_
  ; _≤_ = _⊑_
  ; isPartialOrder = record
    { antisym = ⊑-antisym
    ; isPreorder = record
      { reflexive = ≡-impl-⊑
      ; trans = ⊑-trans
      ; ∼-resp-≈ = ((λ bs≡cs → subst₂ _⊑_ refl bs≡cs) , (λ as≡bs → subst₂ _⊑_ as≡bs refl))
      ; isEquivalence = Relation.Binary.Setoid.isEquivalence (≡-setoid (Trace S))
      }
    }
  }

≲-poset : Session → Session → Poset _ _ _
≲-poset S T = record
  { Carrier = (Trace S → Trace T)
  ; _≈_ = _≃_
  ; _≤_ = _≲_
  ; isPartialOrder = record
    { antisym = ≲-antisym
    ; isPreorder = record
      { reflexive = ≃-impl-≲
      ; trans = ≲-trans
      ; ∼-resp-≈ = (λ P≃Q P≲R as → subst₂ _⊑_ refl (P≃Q as) (P≲R as)) , λ Q≃R Q≲P as → subst₂ _⊑_ (Q≃R as) refl (Q≲P as)
      ; isEquivalence = record
        { refl = λ as → refl
        ; sym = λ P≃Q as → sym (P≃Q as)
        ; trans = λ P≃Q Q≃R as → trans (P≃Q as) (Q≃R as)
        }
      }
    }
  }

-- Inequational reasoning

module ⊑-Reasoning {S} where
  open Relation.Binary.PartialOrderReasoning (⊑-poset S) public renaming ( _≤⟨_⟩_ to _⊑⟨_⟩_ ; _≈⟨_⟩_ to _≡⟨_⟩_ )

module ≲-Reasoning {S T} where
  open Relation.Binary.PartialOrderReasoning (≲-poset S T) public renaming ( _≤⟨_⟩_ to _≲⟨_⟩_ ; _≈⟨_⟩_ to _≃⟨_⟩_ )

open ⊑-Reasoning

-- Processes are ⊑-monotone

P-monotone : ∀ {S T as bs} → (P : S ⇒ T) → (as ⊑ bs) → (⟦ P ⟧ as ⊑ ⟦ P ⟧ bs)
P-monotone (inp F)   []          = []
P-monotone (inp F)   (a ∷ as⊑bs) = P-monotone (♭ F a) as⊑bs
P-monotone (out b P) as⊑bs       = b ∷ P-monotone P as⊑bs
P-monotone done      as⊑bs       = as⊑bs

-- Composition is ≲-monotone

⟫-monotone : ∀ {S T U} (P₁ P₂ : S ⇒ T) (Q₁ Q₂ : T ⇒ U) →
  (⟦ P₁ ⟧ ≲ ⟦ P₂ ⟧) → (⟦ Q₁ ⟧ ≲ ⟦ Q₂ ⟧) →
    (⟦ P₁ ⟫ Q₁ ⟧ ≲ ⟦ P₂ ⟫ Q₂ ⟧)
⟫-monotone P₁ P₂ Q₁ Q₂ P₁≲P₂ Q₁≲Q₂ as =
  begin
    ⟦ P₁ ⟫ Q₁ ⟧ as
  ≡⟨ ⟫-semantics P₁ Q₁ as ⟩
    ⟦ Q₁ ⟧ (⟦ P₁ ⟧ as)
  ⊑⟨ P-monotone Q₁ (P₁≲P₂ as) ⟩
    ⟦ Q₁ ⟧ (⟦ P₂ ⟧ as)
  ⊑⟨ Q₁≲Q₂ (⟦ P₂ ⟧ as) ⟩
    ⟦ Q₂ ⟧ (⟦ P₂ ⟧ as)
  ≡⟨ sym (⟫-semantics P₂ Q₂ as) ⟩
    ⟦ P₂ ⟫ Q₂ ⟧ as
  ∎


{-# OPTIONS --cubical --safe #-}
module Cubical.Data.Unit.Properties where

open import Cubical.Core.Everything

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels

open import Cubical.Data.Nat
open import Cubical.Data.Unit.Base

isContrUnit : isContr Unit
isContrUnit = tt , λ {tt → refl}

isPropUnit : isProp Unit
isPropUnit _ _ i = tt -- definitionally equal to: isContr→isProp isContrUnit

isOfHLevelUnit : (n : ℕ) → isOfHLevel n Unit
isOfHLevelUnit n = isContr→isOfHLevel n isContrUnit


{-# OPTIONS --without-K --safe #-}

module Categories.Adjoint.Instance.0-Truncation where

-- The adjunction between 0-truncation and the inclusion functor from
-- Setoids to Categories/Groupoids.

open import Level using (Lift)
open import Data.Unit using (⊤)
import Function
open import Relation.Binary using (Setoid)
open import Function.Equality using (Π) renaming (id to idΠ)

open import Categories.Adjoint using (_⊣_)
open import Categories.Category.Construction.0-Groupoid using (0-Groupoid)
open import Categories.Category.Groupoid using (Groupoid)
open import Categories.Category.Instance.Groupoids using (Groupoids)
open import Categories.Category.Instance.Setoids using (Setoids)
open import Categories.Functor renaming (id to idF)
open import Categories.Functor.Instance.0-Truncation using (Trunc)
open import Categories.NaturalTransformation using (NaturalTransformation; ntHelper)
open import Categories.NaturalTransformation.NaturalIsomorphism using (refl)

-- The inclusion functor from Setoids to Groupoids

Inclusion : ∀ {c ℓ} e → Functor (Setoids c ℓ) (Groupoids c ℓ e)
Inclusion {c} {ℓ} e = record
  { F₀           = 0-Groupoid e
  ; F₁           = λ f → record { F₀ = f ⟨$⟩_ ; F₁ = cong f }
  ; identity     = refl
  ; homomorphism = refl
  ; F-resp-≈     = λ {S T f g} f≗g →
    let module S = Setoid S
        module T = Setoid T
    in record
    { F⇒G = record { η = λ _ → f≗g S.refl         }
    ; F⇐G = record { η = λ _ → T.sym (f≗g S.refl) }
    }
  }
  where open Π

-- Trunc is left-adjoint to the inclusion functor from Setoids to Groupoids

TruncAdj : ∀ {o ℓ e} → Trunc ⊣ Inclusion {o} {ℓ} e
TruncAdj {o} {ℓ} {e} = record
  { unit   = unit
  ; counit = counit
  ; zig    = Function.id
  ; zag    = refl
  }
  where
    open Π
    open Groupoid using (category)

    unit : NaturalTransformation idF (Inclusion e ∘F Trunc)
    unit = record
      { η           = λ _ → record { F₀ = Function.id ; F₁ = Function.id }
      ; commute     = λ _ → refl
      ; sym-commute = λ _ → refl
      }

    counit : NaturalTransformation (Trunc ∘F Inclusion e) idF
    counit = ntHelper record { η = λ S → idΠ ; commute = λ f → cong f }


------------------------------------------------------------------------
-- The Agda standard library
--
-- Some derivable properties
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

open import Algebra

module Algebra.Properties.AbelianGroup
         {g₁ g₂} (G : AbelianGroup g₁ g₂) where

open AbelianGroup G
open import Function
open import Relation.Binary.Reasoning.Setoid setoid

------------------------------------------------------------------------
-- Publicly re-export group properties

open import Algebra.Properties.Group group public

------------------------------------------------------------------------
-- Properties of abelian groups

private

  lemma₁ : ∀ x y → x ∙ y ∙ x ⁻¹ ≈ y
  lemma₁ x y = begin
    x ∙ y ∙ x ⁻¹    ≈⟨ ∙-congʳ $ comm _ _ ⟩
    y ∙ x ∙ x ⁻¹    ≈⟨ assoc _ _ _ ⟩
    y ∙ (x ∙ x ⁻¹)  ≈⟨ ∙-congˡ $ inverseʳ _ ⟩
    y ∙ ε           ≈⟨ identityʳ _ ⟩
    y               ∎

  lemma₂ : ∀ x y → x ∙ (y ∙ (x ∙ y) ⁻¹ ∙ y ⁻¹) ≈ y ⁻¹
  lemma₂ x y = begin
    x ∙ (y ∙ (x ∙ y) ⁻¹ ∙ y ⁻¹)  ≈˘⟨ assoc _ _ _ ⟩
    x ∙ (y ∙ (x ∙ y) ⁻¹) ∙ y ⁻¹  ≈˘⟨ ∙-congʳ $ assoc _ _ _ ⟩
    x ∙ y ∙ (x ∙ y) ⁻¹ ∙ y ⁻¹    ≈⟨ ∙-congʳ $ inverseʳ _ ⟩
    ε ∙ y ⁻¹                     ≈⟨ identityˡ _ ⟩
    y ⁻¹                         ∎

⁻¹-∙-comm : ∀ x y → x ⁻¹ ∙ y ⁻¹ ≈ (x ∙ y) ⁻¹
⁻¹-∙-comm x y = begin
  x ⁻¹ ∙ y ⁻¹                         ≈⟨ comm _ _ ⟩
  y ⁻¹ ∙ x ⁻¹                         ≈˘⟨ ∙-congʳ $ lemma₂ x y ⟩
  x ∙ (y ∙ (x ∙ y) ⁻¹ ∙ y ⁻¹) ∙ x ⁻¹  ≈⟨ lemma₁ _ _ ⟩
  y ∙ (x ∙ y) ⁻¹ ∙ y ⁻¹               ≈⟨ lemma₁ _ _ ⟩
  (x ∙ y) ⁻¹                          ∎


---------------------------------------------
-- Consequences of the axiom of regularity
---------------------------------------------
{-# OPTIONS --allow-unsolved-meta #-}

module sv20.assign2.SetTheory.Regularity where

open import sv20.assign2.SetTheory.Logic
open import sv20.assign2.SetTheory.Algebra
open import sv20.assign2.SetTheory.Subset
open import sv20.assign2.SetTheory.ZAxioms
open import sv20.assign2.SetTheory.Pairs

-- Theorem 105, p. 54
A∉A : (A : 𝓢) → A ∉ A
A∉A A h = cont _ (p₄ , notEmpty)
  where
  A∈Aₛ : A ∈ singleton A
  A∈Aₛ = singletonp₂ A

  A∈Aₛ∩A : A ∈ (singleton A ∩ A)
  A∈Aₛ∩A = ∩-d₂ _ _ _ (A∈Aₛ , h)

  notEmpty : (singleton A ∩ A) ≢ ∅
  notEmpty = prop-∅ A _ A∈Aₛ∩A

  Aₛ≢∅ : singleton A ≢ ∅
  Aₛ≢∅ x = prop-∅ _ _ A∈Aₛ x

  reg-step : ∃ (λ x → x ∈ singleton A ∧ ((y : 𝓢) → y ∈ x → y ∉ singleton A))
  reg-step = reg (singleton A) Aₛ≢∅

  aux : 𝓢
  aux = proj₁ reg-step

  aux-p : aux ∈ singleton A ∧ ((y : 𝓢) → y ∈ aux → y ∉ singleton A)
  aux-p = proj₂ _ reg-step

  p : aux ∈ singleton A
  p = ∧-proj₁ aux-p

  aux∈auxₛ : aux ∈ singleton aux
  aux∈auxₛ = singletonp₂ aux

  prop : A ∈ singleton aux → A ∩ singleton aux ≡ ∅
  prop = singletonp₄ A aux

  prop₂ : aux ≡ A
  prop₂ = singletonp _ p

  imp : A ∩ singleton aux ≡ ∅
  imp = prop (subs (λ w → w ∈ singleton aux) (prop₂) aux∈auxₛ)

  p₃ : singleton aux ∩ A ≡ ∅
  p₃ = subs (λ w → w ≡ ∅) (∩-sym _ _) imp

  p₄ : singleton A ∩ A ≡ ∅
  p₄ = subs (λ w → singleton w ∩ A ≡ ∅) prop₂ p₃

reg-cons : (A B : 𝓢) → ¬ (A ∈ B ∧ B ∈ A)
reg-cons A B h = {!!}
  where
  p₁ : A ∈ A ₚ B
  p₁ = pair-d₂ _ _ (inj₁ refl)

  p₂ : A ∈ B
  p₂ = ∧-proj₁ h

  p₃ : A ∈ A ₚ B ∩ B
  p₃ = ∩-d₂ _ _ _ (p₁ , p₂)

  p₄ : (A ₚ B) ≢ ∅
  p₄ = prop-∅ _ _ p₁

  reg-step : ∃ (λ x → x ∈ A ₚ B ∧ ((y : 𝓢) → y ∈ x → y ∉ A ₚ B))
  reg-step = {!!}

  x : 𝓢
  x = proj₁ reg-step

  x-p : x ∈ A ₚ B ∧ ((y : 𝓢) → y ∈ x → y ∉ A ₚ B)
  x-p = proj₂ _ reg-step

  p₆ : (A ₚ B ∩ x) ≡ ∅
  p₆ = {!!}

  p₇ : x ∈ A ₚ B
  p₇ = ∧-proj₁ x-p

  p₈ : x ≡ A ∨ x ≡ B
  p₈ = pair-d₁ _ _ p₇

-- References
--
-- Suppes, Patrick (1960). Axiomatic Set Theory.
-- The University Series in Undergraduate Mathematics.
-- D. Van Nostrand Company, inc.
--
-- Enderton, Herbert B. (1977). Elements of Set Theory.
-- Academic Press Inc.


{-# OPTIONS --cubical --no-import-sorts --safe #-}

open import Cubical.Core.Everything
open import Cubical.Algebra.Magma

module Cubical.Algebra.Magma.Construct.Opposite {ℓ} (M : Magma ℓ) where

open import Cubical.Foundations.Prelude

open Magma M

_•ᵒᵖ_ : Op₂ Carrier
y •ᵒᵖ x = x • y

Op-isMagma : IsMagma Carrier _•ᵒᵖ_
Op-isMagma = record { is-set = is-set }

Mᵒᵖ : Magma ℓ
Mᵒᵖ = record { isMagma = Op-isMagma }


{-# OPTIONS --safe #-}
module Cubical.Algebra.CommAlgebra.Ideal where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Powerset

open import Cubical.Algebra.CommRing
open import Cubical.Algebra.CommRing.Ideal renaming (IdealsIn to IdealsInCommRing;
                                                     makeIdeal to makeIdealCommRing)
open import Cubical.Algebra.CommAlgebra

private
  variable
    ℓ : Level

module _ {R : CommRing ℓ} (A : CommAlgebra R ℓ) where
  IdealsIn : Type _
  IdealsIn = IdealsInCommRing (CommAlgebra→CommRing A)

  open CommAlgebraStr (snd A)

  makeIdeal : (I : fst A → hProp ℓ)
              → (+-closed : {x y : fst A} → x ∈ I → y ∈ I → (x + y) ∈ I)
              → (0-closed : 0a ∈ I)
              → (·-closedLeft : {x : fst A} → (r : fst A) → x ∈ I → r · x ∈ I)
              → IdealsIn
  makeIdeal = makeIdealCommRing {R = CommAlgebra→CommRing A}


module Div2 where

record True : Set where

data False : Set where

data Nat : Set where
  zero : Nat
  suc  : Nat -> Nat

NonZero : Nat -> Set
NonZero  zero   = False
NonZero (suc _) = True

divHelp : Nat -> Nat -> Nat -> Nat
divHelp  zero    zero   c = suc zero
divHelp  zero   (suc y) c = zero
divHelp (suc x)  zero   c = suc (divHelp x c c)
divHelp (suc x) (suc y) c = divHelp x y c

div : (x y : Nat) -> {p : NonZero y} -> Nat
div  x       zero  {}
div  zero   (suc y) = zero
div (suc x) (suc y) = divHelp (suc x) (suc y) y

n1 = suc zero
n2 = suc n1
n3 = suc n2
n4 = suc n3
n5 = suc n4
n6 = suc n5
n7 = suc n6
n8 = suc n7
n9 = suc n8
n10 = suc n9
n11 = suc n10
n12 = suc n11

test1 : Nat
test1 = div n12 n7


{-# OPTIONS --without-K #-}
module PathStructure.Nat where

open import Equivalence
open import PathOperations
open import Types

F : ℕ → ℕ → Set
F = ind (λ _ → ℕ → Set)
  (λ _ r → ind (λ _ → Set) (λ n-1 _ → r n-1) ⊥)
  (        ind (λ _ → Set) (λ _   _ → ⊥)     ⊤)

F-lemma : ∀ n → F n n
F-lemma = ind (λ n → F n n) (λ _ f → f) _

-- Explicit arguments to prevent code littered with curly brackets.
split-path : ∀ x y → x ≡ y → F x y
split-path x _ p = tr (F x) p (F-lemma x)

merge-path : ∀ x y → F x y → x ≡ y
merge-path _ _ f = ind
  (λ x → ∀ y → F x y → x ≡ y)
  (λ x r → ind
    (λ y → F (suc x) y → suc x ≡ y)
    (λ _ _ f → ap suc (r _ f))
    0-elim)
  (ind
    (λ y → F zero y → zero ≡ y)
    (λ _ _ → 0-elim)
    (λ _ → refl))
  _ _ f

-- Lemmas.
ap-refl : ∀ {n} (p : n ≡ n) → p ≡ refl →
  ap suc p ≡ refl
ap-refl _ = J
  (λ p q _ → J (λ x y _ → suc x ≡ suc y) (λ _ → refl) _ _ p ≡ ap suc q)
  (λ _ → refl) _ refl

tr-ap : ∀ m n (f : F m n) →
    tr (F (suc m))       (ap suc (merge-path m n f)) (F-lemma (suc m))
  ≡ tr (F (suc m) ∘ suc)         (merge-path m n f)  (F-lemma (suc m))
tr-ap m n f = J
  (λ x y p → tr (F (suc x))       (ap suc p) (F-lemma (suc x))
           ≡ tr (F (suc x) ∘ suc)         p  (F-lemma (suc x)))
  (λ _ → refl)
  _ _ (merge-path m n f)

split-merge-eq : ∀ {x y} → (x ≡ y) ≃ F x y
split-merge-eq {x = x} {y = y}
  = split-path _ _
  , (merge-path _ _ , λ f → ind
      (λ x → ∀ y (f : F x y) → split-path x y (merge-path x y f) ≡ f)
      (λ x r → ind
        (λ y → (f : F (suc x) y) →
          split-path (suc x) y (merge-path (suc x) y f) ≡ f)
        (λ y _ f → tr-ap x y f · r y f)
        (λ b → 0-elim b))
      (ind
        (λ y → (f : F zero y) →
          split-path zero y (merge-path zero y f) ≡ f)
        (λ _ _ b → 0-elim b)
        (λ _ → refl))
      x y f)
  , (merge-path _ _ , J
      (λ _ _ p → merge-path _ _ (split-path _ _ p) ≡ p)
      (ind
        (λ x → merge-path x x (split-path x x refl) ≡ refl)
        (λ _ → ap-refl _)
        refl)
      _ _)


{-# OPTIONS --without-K --safe #-}

open import Categories.Category

-- Skew closed structure on a category
module SOAS.Construction.Skew.SkewClosed {o ℓ e} (C : Category o ℓ e) where

private
  module C = Category C
  open C
  variable
    A B X X′ Y Y′ Z Z′ U ℐ : Obj
    f g : A ⇒ B

  open Commutation C

open import Level
open import Data.Product using (Σ; _,_)
open import Function.Equality using (_⟶_)
open import Function.Inverse using (_InverseOf_; Inverse)

open import Categories.Category.Product
open import Categories.Functor renaming (id to idF)
open import Categories.Functor.Bifunctor
open import Categories.Functor.Construction.Constant
open import Categories.NaturalTransformation
open import Categories.NaturalTransformation.NaturalIsomorphism
open import Categories.NaturalTransformation.Dinatural

record SkewClosed : Set (levelOfTerm C) where
  field
    -- internal hom
    [-,-] : Bifunctor C.op C C
    unit  : Obj

  [_,-] : Obj → Functor C C
  [_,-] = appˡ [-,-]

  [-,_] : Obj → Functor C.op C
  [-,_] = appʳ [-,-]

  module [-,-] = Functor [-,-]

  [_,_]₀ : Obj → Obj → Obj
  [ X , Y ]₀ = [-,-].F₀ (X , Y)

  [_,_]₁ : A ⇒ B → X ⇒ Y → [ B , X ]₀ ⇒ [ A , Y ]₀
  [ f , g ]₁ = [-,-].F₁ (f , g)

  field
    -- i
    identity : NaturalTransformation [ unit ,-] idF
    -- j
    diagonal : Extranaturalʳ unit [-,-]

  module identity = NaturalTransformation identity
  module diagonal = DinaturalTransformation diagonal

  [[X,-],[X,-]] : Obj → Bifunctor C.op C C
  [[X,-],[X,-]] X = [-,-] ∘F (Functor.op [ X ,-] ⁂ [ X ,-])

  [[-,Y],[-,Z]] : Obj → Obj → Bifunctor C C.op C
  [[-,Y],[-,Z]] Y Z = [-,-] ∘F ((Functor.op [-, Y ]) ⁂ [-, Z ])

  -- L needs to be natural in Y and Z.
  -- it is better to spell out the conditions and then prove that indeed
  -- the naturality conditions hold.
  field
    L : ∀ X Y Z → [ Y , Z ]₀ ⇒ [ [ X , Y ]₀ , [ X , Z ]₀ ]₀
    L-commute : [ [ Y , Z ]₀ ⇒  [ [ X , Y′ ]₀ , [ X , Z′ ]₀ ]₀ ]⟨
                  [ f , g ]₁                          ⇒⟨ [ Y′ , Z′ ]₀ ⟩
                  L X Y′ Z′
                ≈ L X Y Z                             ⇒⟨ [ [ X , Y ]₀ , [ X , Z ]₀ ]₀ ⟩
                  [ [ C.id , f ]₁ , [ C.id , g ]₁ ]₁
                ⟩

  L-natural : NaturalTransformation [-,-] ([[X,-],[X,-]] X)
  L-natural {X} = ntHelper record
    { η       = λ where
      (Y , Z) → L X Y Z
    ; commute = λ _ → L-commute
    }

  module L-natural {X}     = NaturalTransformation (L-natural {X})

  -- other required diagrams
  field
    Lj≈j : [ unit ⇒ [ [ X , Y ]₀ , [ X , Y ]₀ ]₀ ]⟨
             diagonal.α  Y                  ⇒⟨ [ Y , Y ]₀ ⟩
             L X Y Y
           ≈ diagonal.α [ X , Y ]₀
           ⟩
    ijL≈id : [ [ X , Y ]₀ ⇒ [ X , Y ]₀ ]⟨
             L X X Y                   ⇒⟨ [ [ X , X ]₀ , [ X , Y ]₀ ]₀ ⟩
             [ diagonal.α X , C.id ]₁  ⇒⟨ [ unit , [ X , Y ]₀ ]₀ ⟩
             identity.η [ X , Y ]₀
           ≈ C.id
           ⟩
    iL≈i : [ [ Y , Z ]₀ ⇒ [ [ unit , Y ]₀ , Z ]₀ ]⟨
             L unit Y Z                ⇒⟨ [ [ unit , Y ]₀ , [ unit , Z ]₀ ]₀ ⟩
             [ C.id , identity.η Z ]₁
           ≈ [ identity.η Y , C.id ]₁
           ⟩

    ij≈id : [ unit ⇒ unit ]⟨
             diagonal.α unit    ⇒⟨ [ unit , unit ]₀ ⟩
             identity.η unit
           ≈ C.id
           ⟩

    pentagon : [ [ U , ℐ ]₀ ⇒ [ [ Y , U ]₀ , [ [ X , Y ]₀ , [ X , ℐ ]₀ ]₀ ]₀ ]⟨
                 L X U ℐ                            ⇒⟨ [ [ X , U ]₀ , [ X , ℐ ]₀ ]₀ ⟩
                 L [ X , Y ]₀ [ X , U ]₀ [ X , ℐ ]₀ ⇒⟨ [ [ [ X , Y ]₀ , [ X , U ]₀ ]₀ , [ [ X , Y ]₀ , [ X , ℐ ]₀ ]₀ ]₀ ⟩
                 [ L X Y U , C.id ]₁
               ≈ L Y U ℐ                            ⇒⟨ [ [ Y , U ]₀ , [ Y , ℐ ]₀ ]₀ ⟩
                 [ C.id , L X Y ℐ ]₁
               ⟩


module Oscar.Class.Injectivity where

open import Oscar.Level

record Injectivity {a} {A : Set a} {b} {B : Set b} {ℓ₁} (_≋₁_ : A → B → Set ℓ₁)
                   {i} {I : Set i} {ℓ₂} (_≋₂_ : I → I → Set ℓ₂)
                   (f : I → A)
                   (g : I → B)
       : Set (a ⊔ b ⊔ ℓ₁ ⊔ i ⊔ ℓ₂) where
  field
    injectivity : ∀ {x y} → f x ≋₁ g y → x ≋₂ y

open Injectivity ⦃ … ⦄ public

record Injectivityoid a b ℓ₁ i ℓ₂ : Set (lsuc (a ⊔ b ⊔ ℓ₁ ⊔ i ⊔ ℓ₂)) where
  field
    {A} : Set a
    {B} : Set b
    _≋₁_ : A → B → Set ℓ₁
    I : Set i
    _≋₂_ : I → I → Set ℓ₂
    μₗ : I → A
    μᵣ : I → B
    `injectivity : ∀ {x y} → μₗ x ≋₁ μᵣ y → x ≋₂ y


------------------------------------------------------------------------
-- The Agda standard library
--
-- Basic types related to coinduction
------------------------------------------------------------------------

module Coinduction where

import Level

------------------------------------------------------------------------
-- A type used to make recursive arguments coinductive

infix 1000 ♯_

postulate
  ∞  : ∀ {a} (A : Set a) → Set a
  ♯_ : ∀ {a} {A : Set a} → A → ∞ A
  ♭  : ∀ {a} {A : Set a} → ∞ A → A

{-# BUILTIN INFINITY ∞  #-}
{-# BUILTIN SHARP    ♯_ #-}
{-# BUILTIN FLAT     ♭  #-}

------------------------------------------------------------------------
-- Rec, a type which is analogous to the Rec type constructor used in
-- ΠΣ (see Altenkirch, Danielsson, Löh and Oury. ΠΣ: Dependent Types
-- without the Sugar. FLOPS 2010, LNCS 6009.)

data Rec {a} (A : ∞ (Set a)) : Set a where
  fold : (x : ♭ A) → Rec A

unfold : ∀ {a} {A : ∞ (Set a)} → Rec A → ♭ A
unfold (fold x) = x

{-

  -- If --guardedness-preserving-type-constructors is enabled one can
  -- define types like ℕ by recursion:

  open import Data.Sum
  open import Data.Unit

  ℕ : Set
  ℕ = ⊤ ⊎ Rec (♯ ℕ)

  zero : ℕ
  zero = inj₁ _

  suc : ℕ → ℕ
  suc n = inj₂ (fold n)

  ℕ-rec : (P : ℕ → Set) →
          P zero →
          (∀ n → P n → P (suc n)) →
          ∀ n → P n
  ℕ-rec P z s (inj₁ _)        = z
  ℕ-rec P z s (inj₂ (fold n)) = s n (ℕ-rec P z s n)

  -- This feature is very experimental, though: it may lead to
  -- inconsistencies.

-}


open import Data.Bool using (Bool; true; false; _∧_; _∨_; T)
open import Data.Bool.Properties using (∨-identityˡ; ∨-zeroˡ)
open import Data.List using (List; []; _∷_; any; map; foldl)
open import Data.List.Relation.Unary.Any using (Any; here; there; lookup; satisfied)
open import Data.Product as Prod using (∃; _,_; proj₁; proj₂)
open import Data.Unit using (⊤; tt)
open import Relation.Binary.PropositionalEquality
   using (_≡_; refl; cong; subst; sym; trans; module ≡-Reasoning)
open import Relation.Binary.PropositionalEquality as P
open ≡-Reasoning using (begin_; _≡⟨⟩_; _≡⟨_⟩_; _∎)
open import Data.Nat using (ℕ; zero; suc)

≡→T : ∀ {b : Bool} → b ≡ true → T b
≡→T refl = tt

any-val : ∀ {a} {A : Set a} (f) (ns : List A)
        → any f ns ≡ true
        → Any (λ x → T (f x)) ns
any-val f (n ∷ ns) any-f-⟨n∷ns⟩≡true with f n | P.inspect f n
... | true  | P.[ fn≡t ] = here (≡→T fn≡t)
... | false | _          = there (any-val f ns any-f-⟨n∷ns⟩≡true)

get-val : ∀ {a} {A : Set a} {f} (ns : List A)
        → any f ns ≡ true
        → A
get-val {_} {_} {f} ns any≡true = lookup {xs = ns} (any-val f ns any≡true)

get-prop : ∀ {a} {A : Set a} {f} (ns : List A)
         → any f ns ≡ true
         → ∃ (λ x → T (f x))
get-prop {_} {_} {f} ns any≡true = satisfied {xs = ns} (any-val f ns any≡true)

is-not-zero : ℕ → Bool
is-not-zero zero = false
is-not-zero _ = true

eg1 : any is-not-zero (0 ∷ 0 ∷ 3 ∷ []) ≡ true
eg1 = refl
--proj₁ (get-prop {f = λ x → x} (true ∷ false ∷ []) _)
--proj₁ (get-prop {f = is-not-zero} (0 ∷ 0 ∷ 3 ∷ []) refl)

--data Singleton {a} {A : Set a} (x : A) : Set a where
--  _with≡_ : (y : A) → x ≡ y → Singleton x
--
--inspect : ∀ {a} {A : Set a} (x : A) → Singleton x
--inspect x = x with≡ refl

any-val' : ∀ {a} {A : Set a} (f : A → Bool) (ns : List A)
         → any f ns ≡ true
         → (∃ λ x → T (f x))
any-val' f [] ()
any-val' f (n ∷ ns) anyfnns≡true with f n | P.inspect f n
...   | true  | P.[ fn≡t ] = n , ≡→T fn≡t
...   | false | P.[ fn≡f ] = any-val' f ns anyfnns≡true
--  where
--    anyfns≡true =
--      begin
--        any f ns            ≡⟨ sym (∨-identityˡ (any f ns)) ⟩
--        false ∨ any f ns    ≡⟨ cong (_∨ any f ns) (sym ?) ⟩
--        f n ∨ any f ns      ≡⟨ anyfnns≡true ⟩
--        true
--      ∎


{-# OPTIONS --safe --warning=error --without-K #-}

open import LogicalFormulae
open import Groups.Lemmas
open import Groups.Definition
open import Setoids.Setoids
open import Rings.Definition
open import Sets.EquivalenceRelations
open import Rings.IntegralDomains.Definition

module Rings.IntegralDomains.Lemmas {m n : _} {A : Set n} {S : Setoid {n} {m} A} {_+_ _*_ : A → A → A} {R : Ring S _+_ _*_} (I : IntegralDomain R) where

open Setoid S
open Equivalence eq
open Ring R

cancelIntDom : {a b c : A} → (a * b) ∼ (a * c) → ((a ∼ (Ring.0R R)) → False) → (b ∼ c)
cancelIntDom {a} {b} {c} ab=ac a!=0 = transferToRight (Ring.additiveGroup R) t3
  where
    t1 : (a * b) + Group.inverse (Ring.additiveGroup R) (a * c) ∼ Ring.0R R
    t1 = transferToRight'' (Ring.additiveGroup R) ab=ac
    t2 : a * (b + Group.inverse (Ring.additiveGroup R) c) ∼ Ring.0R R
    t2 = transitive (transitive (Ring.*DistributesOver+ R) (Group.+WellDefined (Ring.additiveGroup R) reflexive (transferToRight' (Ring.additiveGroup R) (transitive (symmetric (Ring.*DistributesOver+ R)) (transitive (Ring.*WellDefined R reflexive (Group.invLeft (Ring.additiveGroup R))) (Ring.timesZero R)))))) t1
    t3 : (b + Group.inverse (Ring.additiveGroup R) c) ∼ Ring.0R R
    t3 = IntegralDomain.intDom I t2 a!=0

cancelIntDom' : {a b c : A} → (a * c) ∼ (b * c) → (c ∼ Ring.0R R → False) → a ∼ b
cancelIntDom' pr n = cancelIntDom (transitive *Commutative (transitive pr *Commutative)) n


------------------------------------------------------------------------
-- The Agda standard library
--
-- Some defined operations over Rings
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

-- This module gives the definition of _^_ which is used throughout
-- the library. It's a little different from the normal definition:
--
--   x ^ zero  = 1#
--   x ^ suc i = x * x ^ i
--
-- This is for two reasons. First, we want to avoid unnecessarily
-- multiplying by 1# if possible:
--
--     Standard definition: x ^ 2 = x * x * 1#
--     Our definition:      x ^ 2 = x * x
--
-- This speeds up typechecking and makes for much more readable
-- proofs.
--
-- Secondly, we want to associate to the left:
--
--     Standard definition: x ^ 3 = x * (x * (x * 1#))
--     Our definition:      x ^ 2 = (x * x) * x
--
-- As counterintuitive as it may seem, this also speeds up
-- typechecking.

open import Algebra

module Algebra.Operations.Ring
  {ℓ₁ ℓ₂} (ring : RawRing ℓ₁ ℓ₂)
  where

open import Data.Nat.Base as ℕ using (ℕ; suc; zero)

open RawRing ring

infixr 8 _^_+1
_^_+1 : Carrier → ℕ → Carrier
x ^ zero  +1 = x
x ^ suc n +1 = (x ^ n +1) * x

infixr 8 _^_
_^_ : Carrier → ℕ → Carrier
x ^ zero  = 1#
x ^ suc i = x ^ i +1
{-# INLINE _^_ #-}


{-# OPTIONS --cubical #-}

module Miscellaneous.LimNatural where

import      Lvl
open import Numeral.Natural as ℕ using (ℕ)
open import Numeral.Sign as Sign using (−|+ ; −|0|+ ; ➖ ; ➕)
open import Type.Cubical
open import Type.Cubical.Path.Equality
open import Type

data ℕ∞ : Type{Lvl.𝟎} where
  𝟎 : ℕ∞
  𝐒 : ℕ∞ → ℕ∞
  ∞ : ℕ∞
  𝐒-fixpoint : (𝐒(∞) ≡ ∞)

𝐏₀ : ℕ∞ → ℕ∞
𝐏₀(𝟎)    = 𝟎
𝐏₀(𝐒(n)) = n
𝐏₀(∞)    = ∞
𝐏₀(𝐒-fixpoint i) = ∞

_+_ : ℕ∞ → ℕ∞ → ℕ∞
x + 𝟎    = x
x + 𝐒(y) = 𝐒(x + y)
_ + ∞    = ∞
x + 𝐒-fixpoint i = 𝐒-fixpoint i

_⋅_ : ℕ∞ → ℕ∞ → ℕ∞
x ⋅ 𝟎    = 𝟎
x ⋅ 𝐒(y) = x + (x ⋅ y)
x ⋅ ∞    = ∞
x ⋅ 𝐒-fixpoint i = ∞

infixl 10010 _+_
infixl 10020 _⋅_

open import Structure.Function.Domain
open import Structure.Function
open import Structure.Relator.Properties
open import Syntax.Transitivity
open import Type.Cubical.Path.Proofs

private variable x y z : ℕ∞

𝐒-∞-involutive : (𝐒(𝐒(∞)) ≡ ∞)
𝐒-∞-involutive = congruence₁(𝐒) 𝐒-fixpoint 🝖 𝐒-fixpoint

instance
  𝐒-injectivity : Injective(𝐒)
  Injective.proof 𝐒-injectivity = congruence₁(𝐏₀)

[+]-baseₗ : (𝟎 + x ≡ x)
[+]-baseₗ {𝟎}   = reflexivity(_≡_)
[+]-baseₗ {𝐒 x} = congruence₁(𝐒) ([+]-baseₗ {x})
[+]-baseₗ {∞}   = reflexivity(_≡_)
[+]-baseₗ {𝐒-fixpoint i} = reflexivity(_≡_) {𝐒-fixpoint i}

[+]-stepₗ : (𝐒(x) + y ≡ 𝐒(x + y))
[+]-stepₗ {x} {𝟎}   = reflexivity(_≡_)
[+]-stepₗ {x} {𝐒 y} = congruence₁(𝐒) ([+]-stepₗ {x}{y})
[+]-stepₗ {x} {∞}   = symmetry(_≡_) 𝐒-fixpoint
[+]-stepₗ {x} {𝐒-fixpoint i} = symmetry(_≡_) (Interval.hComp diagram {!!}) where
  diagram : Interval → Interval.Partial(Interval.farBound i) _
  diagram _ (i = Interval.𝟎) = congruence₁(𝐒) 𝐒-fixpoint
  diagram _ (i = Interval.𝟏) = 𝐒-fixpoint
  {-
  i0 j0 𝐒∞
  i0 j1 𝐒𝐒∞
  i1 j0 ∞
  i1 j1 𝐒∞
  -}
  -- test : ∀{i} → (𝐒(𝐒-fixpoint i) ≡ 𝐒-fixpoint i)
  -- test {i} j = {!!}
  {-
  i0 j0 𝐒𝐒∞
  i0 j1 𝐒∞
  i1 j0 𝐒∞
  i1 j1 ∞
  -}


{-# OPTIONS --without-K  #-}
module algebra.group.classifying where

open import level
open import algebra.group.core
open import algebra.group.morphism
open import equality.core
open import function.isomorphism
open import pointed.core
open import sets.unit
open import sum
open import hott.level.core
open import hott.loop.core
open import hott.truncation.core
open import hott.equivalence

module _ {i}(G : Set i) ⦃ gG : IsGroup G ⦄ where
  open import algebra.group.gset G
  open IsGroup ⦃ ... ⦄

  -- G as a G-Set
  G' : GSet i
  G' = (G , GisGSet)

  -- G as a pointed set
  G* : PSet i
  G* = (G , e)

  𝑩 : Set (lsuc i)
  𝑩 = Σ (GSet i) λ X → Trunc 1 (X ≡ G')

  base : 𝑩
  base = (G' , [ refl ])

  𝑩* : PSet (lsuc i)
  𝑩* = (𝑩 , base)

  𝑩-Ω : (base ≡ base) ≅ G
  𝑩-Ω = begin
      (base ≡ base)
    ≅⟨ sym≅ Σ-split-iso ⟩
      ( Σ (G' ≡ G') λ p
      → subst (λ X → Trunc 1 (X ≡ G')) p [ refl ] ≡ [ refl ] )
    ≅⟨ (Σ-ap-iso refl≅ λ p → contr-⊤-iso (Trunc-level 1 _ _)) ·≅ ×-right-unit ⟩
      (G' ≡ G')
    ≅⟨ GSet-univalence G ⦃ xG = GisGSet ⦄ G ⦃ yG = GisGSet ⦄ ⟩
      ( Σ (GSetMorphism G ⦃ xG = GisGSet ⦄ G ⦃ yG = GisGSet ⦄) λ { (f , _)
        → weak-equiv f } )
    ≅⟨ (Σ-ap-iso' (GSet-repr-iso is-set ⦃ xG = GisGSet ⦄) λ _ → refl≅) ⟩
      ( Σ G λ { g → weak-equiv (λ x → x * g) } )
    ≅⟨ ( Σ-ap-iso refl≅ λ g → contr-⊤-iso ( lem g , h1⇒prop (we-h1 _) _ ) )
        ·≅ ×-right-unit ⟩
      G
    ∎
    where
      open ≅-Reasoning
      lem : (g : G) → weak-equiv (λ x → x * g)
      lem g = proj₂ (≅'⇒≈ (≅⇒≅' (right-translation-iso g)))


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

module Data.List.Indexing where

open import Data.List.Base
open import Data.Fin
open import Prelude

infixl 6 _!_
_!_ : (xs : List A) → Fin (length xs) → A
(x ∷ xs) ! f0 = x
(x ∷ xs) ! fs i = xs ! i

tabulate : ∀ n → (Fin n → A) → List A
tabulate zero f = []
tabulate (suc n) f = f f0 ∷ tabulate n (f ∘ fs)