module Cats.Category.Constructions.Iso where

open import Relation.Binary using (IsEquivalence ; Setoid)
open import Level

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

import Relation.Binary.EqReasoning as EqReasoning

import Cats.Category.Constructions.Epi as Epi
import Cats.Category.Constructions.Mono as Mono

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

  private open module Cat = Category Cat
  open Cat.≈-Reasoning
  open Epi.Build Cat
  open Mono.Build Cat

  record _≅_ (A B : Obj) : Set (lo ⊔ la ⊔ l≈) where
    field
      forth : A ⇒ B
      back : B ⇒ A
      back-forth : back ∘ forth ≈ id
      forth-back : forth ∘ back ≈ id

  open _≅_

  instance
    HasArrow-≅ : ∀ {A B} → HasArrow (A ≅ B) lo la l≈
    HasArrow-≅ = record { Cat = Cat ; _⃗ = forth }

  ≅-equiv : IsEquivalence _≅_
  ≅-equiv = record { refl = refl ; sym = sym ; trans = trans }
    where
      refl : ∀ {A} → A ≅ A
      refl {A} = record
          { forth = id
          ; back = id
          ; back-forth = id-l
          ; forth-back = id-l
          }

      sym : ∀ {A B} → A ≅ B → B ≅ A
      sym iso = record
          { forth = back iso
          ; back = forth iso
          ; back-forth = forth-back iso
          ; forth-back = back-forth iso
          }

      trans : ∀ {A B C : Obj} → A ≅ B → B ≅ C → A ≅ C
      trans {A} {B} {C} A≅B B≅C = record
          { forth = forth B≅C ∘ forth A≅B
          ; back = back A≅B ∘ back B≅C
          ; back-forth
              = begin
                  (back A≅B ∘ back B≅C) ∘ forth B≅C ∘ forth A≅B
                ≈⟨ assoc ⟩
                  back A≅B ∘ back B≅C ∘ forth B≅C ∘ forth A≅B
                ≈⟨ ∘-resp-r (≈.trans unassoc (∘-resp-l (back-forth B≅C))) ⟩
                  back A≅B ∘ id ∘ forth A≅B
                ≈⟨ ∘-resp-r id-l ⟩
                  back A≅B ∘ forth A≅B
                ≈⟨ back-forth A≅B ⟩
                  id
                ∎
          ; forth-back
              = begin
                  (forth B≅C ∘ forth A≅B) ∘ back A≅B ∘ back B≅C
                ≈⟨ assoc ⟩
                  forth B≅C ∘ forth A≅B ∘ back A≅B ∘ back B≅C
                ≈⟨ ∘-resp-r (≈.trans unassoc (∘-resp-l (forth-back A≅B))) ⟩
                  forth B≅C ∘ id ∘ back B≅C
                ≈⟨ ∘-resp-r id-l ⟩
                  forth B≅C ∘ back B≅C
                ≈⟨ forth-back B≅C ⟩
                  id
                ∎
          }

  ≅-Setoid : Setoid lo (lo ⊔ la ⊔ l≈)
  ≅-Setoid = record
      { Carrier = Obj
      ; _≈_ = _≅_
      ; isEquivalence = ≅-equiv
      }

  module ≅ = IsEquivalence ≅-equiv
  module ≅-Reasoning = EqReasoning ≅-Setoid

  iso-mono : ∀ {A B} (iso : A ≅ B) → IsMono (forth iso)
  iso-mono iso {g = g} {h} iso∘g≈iso∘h
      = begin
          g
        ≈⟨ ≈.sym id-l ⟩
          id ∘ g
        ≈⟨ ∘-resp-l (≈.sym (back-forth iso)) ⟩
          (back iso ∘ forth iso) ∘ g
        ≈⟨ assoc ⟩
          back iso ∘ forth iso ∘ g
        ≈⟨ ∘-resp-r iso∘g≈iso∘h ⟩
          back iso ∘ forth iso ∘ h
        ≈⟨ unassoc ⟩
          (back iso ∘ forth iso) ∘ h
        ≈⟨ ∘-resp-l (back-forth iso) ⟩
          id ∘ h
        ≈⟨ id-l ⟩
          h
        ∎

  iso-epi : ∀ {A B} (iso : A ≅ B) → IsEpi (forth iso)
  iso-epi iso {g = g} {h} g∘iso≈h∘iso
      = begin
          g
        ≈⟨ ≈.sym id-r ⟩
          g ∘ id
        ≈⟨ ∘-resp-r (≈.sym (forth-back iso)) ⟩
          g ∘ forth iso ∘ back iso
        ≈⟨ unassoc ⟩
          (g ∘ forth iso) ∘ back iso
        ≈⟨ ∘-resp-l g∘iso≈h∘iso ⟩
          (h ∘ forth iso) ∘ back iso
        ≈⟨ assoc ⟩
          h ∘ forth iso ∘ back iso
        ≈⟨ ∘-resp-r (forth-back iso) ⟩
          h ∘ id
        ≈⟨ id-r ⟩
          h
        ∎


------------------------------------------------------------------------------
-- Distributive laws properties
------------------------------------------------------------------------------

{-# OPTIONS --exact-split              #-}
{-# OPTIONS --no-sized-types           #-}
{-# OPTIONS --no-universe-polymorphism #-}
{-# OPTIONS --without-K                #-}

module DistributiveLaws.PropertiesI where

open import DistributiveLaws.Base

------------------------------------------------------------------------------
-- Congruence properties

-- The propositional equality is compatible with the binary operation.

·-leftCong : ∀ {a b c} → a ≡ b → a · c ≡ b · c
·-leftCong refl = refl

·-rightCong : ∀ {a b c} → b ≡ c → a · b ≡ a · c
·-rightCong refl = refl


module MLib.Matrix.Core where

open import MLib.Prelude
open import MLib.Algebra.PropertyCode
open import MLib.Algebra.PropertyCode.Structures

import Relation.Binary.Indexed as I

Matrix : ∀ {a} → Set a → ℕ → ℕ → Set a
Matrix A m n = Fin m → Fin n → A

module _ {a} (A : Set a) where
  row : ∀ {m n} → Fin m → Matrix A m n → Table A n
  row i M .lookup j = M i j

  col : ∀ {m n} → Fin n → Matrix A m n → Table A m
  col j M .lookup i = M i j


{-# OPTIONS --without-K #-}
module combination where

open import Type
open import Data.Nat.NP
open import Data.Nat.DivMod
open import Data.Fin using (Fin; Fin′; zero; suc) renaming (toℕ to Fin▹ℕ)
open import Data.Zero
open import Data.One
open import Data.Two
open import Data.Sum
open import Data.Product
open import Data.Vec
open import Function.NP
open import Function.Related.TypeIsomorphisms.NP
import Function.Inverse.NP as Inv
open Inv using (_↔_; sym; inverses; module Inverse) renaming (_$₁_ to to; _$₂_ to from; id to idI; _∘_ to _∘I_)
open import Relation.Binary.Product.Pointwise
open import Relation.Binary.Sum
import Relation.Binary.PropositionalEquality as ≡

open import factorial

_/_ : ℕ → ℕ → ℕ
x / y = _div_ x y {{!!}}

module v0 where

  C : ℕ → ℕ → ℕ
  C n       zero    = 1
  C zero    (suc k) = 0
  C (suc n) (suc k) = C n k + C n (suc k)

  D : ℕ → ℕ → ★
  D n       zero    = 𝟙
  D zero    (suc k) = 𝟘
  D (suc n) (suc k) = D n k ⊎ D n (suc k)

  FinC≅D : ∀ n k → Fin (C n k) ↔ D n k
  FinC≅D n       zero    = Fin1↔𝟙
  FinC≅D zero    (suc k) = Fin0↔𝟘
  FinC≅D (suc n) (suc k) =  FinC≅D n k ⊎-cong FinC≅D n (suc k)
                         ∘I sym (Fin-⊎-+ (C n k) (C n (suc k)))

module v! where

  C : ℕ → ℕ → ℕ
  C n k = n ! / (k ! * (n ∸ k)!)

module v1 where

  C : ℕ → ℕ → ℕ
  C n 0 = 1
  C n (suc k) = (C n k * (n ∸ k)) / suc k

module v2 where

  C : ℕ → ℕ → ℕ
  C n       zero    = 1
  C zero    (suc k) = 0
  C (suc n) (suc k) = (C n k * suc n) / suc k

{- Σ_{0≤k<n} (C n k) ≡ 2ⁿ -}

Σ𝟙F↔F : ∀ (F : 𝟙 → ★) → Σ 𝟙 F ↔ F _
Σ𝟙F↔F F = inverses proj₂ ,_ (λ _ → ≡.refl) (λ _ → ≡.refl)

Bits = Vec 𝟚
Bits1↔𝟚 : Bits 1 ↔ 𝟚
Bits1↔𝟚 = {!!}

open v0
foo : ∀ n → Σ (Fin (suc n)) (D (suc n) ∘ Fin▹ℕ) ↔ Bits (suc n)
foo zero = ((sym Bits1↔𝟚 ∘I {!!}) ∘I Σ𝟙F↔F _) ∘I first-iso Fin1↔𝟙
foo (suc n) = {!!}


module Nats.Multiply.Assoc where

open import Nats
open import Equality
open import Function

open import Nats.Multiply.Comm
open import Nats.Multiply.Distrib

------------------------------------------------------------------------
-- internal stuffs

private

  a*1+b=a+a*b : ∀ a b → a * suc b ≡ a + a * b
  a*1+b=a+a*b a b
    rewrite nat-multiply-comm a $ suc b
          | nat-multiply-comm a b
            = refl

  a*/b*c/=/a*b/*c : ∀ a b c → a * b * c ≡ a * (b * c)
  a*/b*c/=/a*b/*c  zero   b c = refl
  a*/b*c/=/a*b/*c (suc a) b c
    rewrite a*/b*c/=/a*b/*c a b c
          | nat-multiply-comm a b
          | sym $ nat-multiply-distrib b (b * a) c
          | sym $ a*/b*c/=/a*b/*c a b c
          | nat-multiply-comm a b
            = refl

------------------------------------------------------------------------
-- public aliases

nat-multiply-assoc : ∀ a b c → a * b * c ≡ a * (b * c)
nat-multiply-assoc = a*/b*c/=/a*b/*c


-- {-# OPTIONS -v tc.cover.split.con:20 #-}

open import Common.Prelude renaming (Nat to ℕ)
open import Common.Equality

infix 3 ¬_

¬_ : Set → Set
¬ P = P → ⊥

-- Decidable relations.

data Dec (P : Set) : Set where
  yes : ( p :   P) → Dec P
  no  : (¬p : ¬ P) → Dec P

_≟_ : (m n : ℕ) → Dec (m ≡ n)
zero  ≟ zero   = yes refl
zero  ≟ suc n  = no λ()
suc m ≟ zero   = no λ()
suc m ≟ suc n  with m ≟ n
suc m ≟ suc .m | yes refl = yes refl
suc m ≟ suc n  | no prf   = no (λ x → prf (cong pred x))

data Ty : Set where

data Cxt : Set where
  ε   : Cxt
  _,_ : (Γ : Cxt) (a : Ty) → Cxt

len : Cxt → ℕ
len ε       = 0
len (Γ , _) = suc (len Γ)

-- De Bruijn index

mutual
  Var : Cxt → Ty → Set
  Var Γ a = Var' a Γ

  data Var' (a : Ty) : (Γ : Cxt) → Set where
    zero : ∀ {Γ}                 → Var (Γ , a) a
    suc  : ∀ {Γ b} (x : Var Γ a) → Var (Γ , b) a

-- De Bruijn Level

Lev = ℕ

-- Valid de Bruijn levels.

data LookupLev : (x : Lev) (Γ : Cxt) (a : Ty) (i : Var Γ a) → Set where
  lookupZero : ∀ {Γ a} →
    LookupLev (len Γ) (Γ , a) a zero

  lookupSuc : ∀ {Γ a b x i} →
    LookupLev x Γ a i →
    LookupLev x (Γ , b) a (suc i)

record ValidLev (x : Lev) (Γ : Cxt) : Set where
  constructor validLev
  field
    {type } : Ty
    {index} : Var Γ type
    valid   : LookupLev x Γ type index

weakLev : ∀ {x Γ a} → ValidLev x Γ → ValidLev x (Γ , a)
weakLev (validLev d) = validLev (lookupSuc d)

-- Looking up a de Bruijn level.

lookupLev : ∀ (x : Lev) (Γ : Cxt) → Dec (ValidLev x Γ)
lookupLev x ε = no λ { (validLev ()) }
lookupLev x (Γ , a) with x ≟ len Γ
lookupLev ._ (Γ , a) | yes refl = yes (validLev lookupZero)
lookupLev x (Γ , a) | no _ with lookupLev x Γ
lookupLev x (Γ , a) | no ¬p | yes d = yes (weakLev d)
lookupLev x (Γ , a) | no ¬p | no ¬d = no contra
  where
    contra : ¬ ValidLev x (Γ , a)
    contra (validLev (lookupSuc valid)) = ?

{- Unbound indices showing up in error message:

I'm not sure if there should be a case for the constructor
lookupZero, because I get stuck when trying to solve the following
unification problems (inferred index ≟ expected index):
  len Γ ≟ @8
  Γ , a ≟ @7 , @4
  a ≟ type
  zero ≟ index
when checking the definition of contra -}


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

module Categories.Category.Regular where

-- https://ncatlab.org/nlab/show/regular+category
-- https://en.wikipedia.org/wiki/Regular_category

open import Level

open import Categories.Category.Core
open import Categories.Category.Complete.Finitely using (FinitelyComplete)
open import Categories.Diagram.Coequalizer
open import Categories.Diagram.KernelPair
open import Categories.Diagram.Pullback
open import Categories.Morphism.Regular

record Regular {o ℓ e : Level} (𝒞 : Category o ℓ e) : Set (suc (o ⊔ ℓ ⊔ e)) where
  open Category 𝒞
  open Pullback

  field
    finitely-complete : FinitelyComplete 𝒞
    coeq-of-kernelpairs : {A B : Obj} (f : A ⇒ B) (kp : KernelPair 𝒞 f) → Coequalizer 𝒞 (p₁ kp) (p₂ kp)
    pullback-of-regularepi-is-regularepi : {A B C : Obj} (f : B ⇒ A) {g : C ⇒ A} → RegularEpi 𝒞 f → (p : Pullback 𝒞 f g) → RegularEpi 𝒞 (p₂ p)


open import x1-Base
open import x4-Nat
open import x3-PropositionalEquality using (_≡_; refl; cong; equivalence)
open import x2-Sort _≤?_ totalOrder

module x5-Test where

empty : OList ⊥ ⊤
empty = nil ⊥≤̂

l-9 : OList ⊥ ⊤
l-9 = insert 9 empty ⊥≤̂ ≤̂⊤

_ : l-9 ≡ cons 9 (nil ≤̂⊤) ⊥≤̂
_ = refl

l-5-9 : OList ⊥ ⊤
l-5-9 = insert 5 l-9 ⊥≤̂ ≤̂⊤

_ : l-5-9 ≡ cons 5
                 (cons 9
                       (nil ≤̂⊤)
                       (≤-lift (s≤s (s≤s (s≤s (s≤s (s≤s z≤n)))))))
                 ⊥≤̂
_ = refl

l-1-5-9 : OList ⊥ ⊤
l-1-5-9 = insert 1 l-5-9 ⊥≤̂ ≤̂⊤

_ : l-1-5-9 ≡ cons 1
                   (cons 5
                         (cons 9
                               (nil ≤̂⊤)
                               (≤-lift (s≤s (s≤s (s≤s (s≤s (s≤s z≤n)))))))
                         (≤-lift (s≤s z≤n))) -- NOTE CHANGE
                   ⊥≤̂
_ = refl

sl : List ℕ
sl = t-sort (12 ∷ 3 ∷ 7 ∷ 4 ∷ 40 ∷ 5 ∷ 0 ∷ [])

_ : sl ≡ (0 ∷ 3 ∷ 4 ∷ 5 ∷ 7 ∷ 12 ∷ 40 ∷ [])
_ = refl


module Numeral.Integer where

import      Lvl
open import Numeral.Natural      as ℕ using (ℕ)
import      Numeral.Natural.Oper as ℕ
open import Syntax.Number
open import Type

-- Integers
data ℤ : Type{Lvl.𝟎} where
  +ₙ_  : ℕ → ℤ -- Positive integers including zero from the naturals (0,1,..).
  −𝐒ₙ_ : ℕ → ℤ -- Negative integers from the naturals (..,−2,−1).

{-# BUILTIN INTEGER        ℤ  #-}
{-# BUILTIN INTEGERPOS     +ₙ_ #-}
{-# BUILTIN INTEGERNEGSUC −𝐒ₙ_ #-}

------------------------------------------
-- Constructors and deconstructors

-- Constructing negative number from ℕ
−ₙ_ : ℕ → ℤ
−ₙ (ℕ.𝟎)    = +ₙ ℕ.𝟎
−ₙ (ℕ.𝐒(x)) = −𝐒ₙ(x)

-- Intuitive constructor patterns
pattern 𝟎      = +ₙ(ℕ.𝟎)    -- Zero (0).
pattern +𝐒ₙ_ n = +ₙ(ℕ.𝐒(n)) -- Positive integers from the naturals (1,2,..).
pattern 𝟏      = +ₙ(ℕ.𝟏)    -- One (1).
pattern −𝟏     = −𝐒ₙ(ℕ.𝟎)   -- Negative one (−1).
{-# DISPLAY ℤ.+ₙ_ ℕ.𝟎  = 𝟎 #-}
{-# DISPLAY ℤ.+ₙ_ ℕ.𝟏  = 𝟏 #-}
{-# DISPLAY ℤ.−𝐒ₙ_ ℕ.𝟎 = −𝟏 #-}
{-# DISPLAY ℤ.+ₙ_(ℕ.𝐒(n)) = +𝐒ₙ_ n #-}

-- Absolute value
absₙ : ℤ → ℕ
absₙ(+ₙ x)   = x
absₙ(−𝐒ₙ(x)) = ℕ.𝐒(x)

-- Syntax
instance
  ℤ-InfiniteNegativeNumeral : InfiniteNegativeNumeral(ℤ)
  ℤ-InfiniteNegativeNumeral = InfiniteNegativeNumeral.intro(−ₙ_)

instance
  ℤ-InfiniteNumeral : InfiniteNumeral(ℤ)
  ℤ-InfiniteNumeral = InfiniteNumeral.intro(+ₙ_)


module Prelude.Monoid where

open import Prelude.Function
open import Prelude.Maybe
open import Prelude.List
open import Prelude.Semiring
open import Prelude.Applicative
open import Prelude.Functor

record Monoid {a} (A : Set a) : Set a where
  infixr 6 _<>_
  field
    mempty : A
    _<>_   : A → A → A

open Monoid {{...}} public

{-# DISPLAY Monoid.mempty _ = mempty #-}
{-# DISPLAY Monoid._<>_ _ a b = a <> b #-}

mconcat : ∀ {a} {A : Set a} {{MonA : Monoid A}} → List A → A
mconcat = foldr _<>_ mempty

--- Instances ---

instance
  MonoidList : ∀ {a} {A : Set a} → Monoid (List A)
  mempty {{MonoidList}} = []
  _<>_   {{MonoidList}} = _++_

  MonoidFun : ∀ {a b} {A : Set a} {B : A → Set b} {{_ : ∀ {x} → Monoid (B x)}} → Monoid (∀ x → B x)
  mempty {{MonoidFun}}     _ = mempty
  _<>_   {{MonoidFun}} f g x = f x <> g x

  MonoidMaybe : ∀ {a} {A : Set a} → Monoid (Maybe A)
  mempty {{MonoidMaybe}} = nothing
  _<>_   {{MonoidMaybe}} nothing  y = y
  _<>_   {{MonoidMaybe}} (just x) _ = just x

record Sum {a} (A : Set a) : Set a where
  constructor mkSum
  field getSum : A

open Sum public

instance
  MonoidSum : ∀ {a} {A : Set a} {{_ : Semiring A}} → Monoid (Sum A)
  getSum (mempty {{MonoidSum}})     = zro
  getSum (_<>_   {{MonoidSum}} x y) = getSum x + getSum y

record Product {a} (A : Set a) : Set a where
  constructor mkProduct
  field getProduct : A

open Product public

instance
  MonoidProduct : ∀ {a} {A : Set a} {{_ : Semiring A}} → Monoid (Product A)
  getProduct (mempty {{MonoidProduct}})     = one
  getProduct (_<>_   {{MonoidProduct}} x y) = getProduct x * getProduct y

record Const {a b} (A : Set a) (B : Set b) : Set a where
  constructor mkConst
  field getConst : A

open Const public

module _ {a b} {A : Set a} {{MonA : Monoid A}} where
  instance
    FunctorConst : Functor {a = b} (Const A)
    getConst (fmap {{FunctorConst}} f x) = getConst x

    ApplicativeConst : Applicative (Const A)
    getConst (pure  {{ApplicativeConst}} x)     = mempty
    getConst (_<*>_ {{ApplicativeConst}} wf wx) = getConst wf <> getConst wx


module Structure.Function where

import Lvl
open import Lang.Instance
open import Logic.Predicate
open import Logic
open import Structure.Function.Names
open import Structure.Setoid
open import Type

private variable ℓ ℓₒ ℓₒ₁ ℓₒ₂ ℓₒ₃ ℓₗ ℓₗ₁ ℓₗ₂ ℓₗ₃ : Lvl.Level
private variable A B : Type{ℓ}

-- The function `f` "(behaves like)/is a function" in the context of `_≡_` from the Equiv instance.
-- `congruence` is the defining property of a function.
module _
  ⦃ equiv-A : Equiv{ℓₗ₁}(A) ⦄
  ⦃ equiv-B : Equiv{ℓₗ₂}(B) ⦄
  (f : A → B)
  where

  record Function : Stmt{Lvl.of(A) Lvl.⊔ ℓₗ₁ Lvl.⊔ ℓₗ₂} where
    constructor intro
    field congruence : Congruence₁(f)
  congruence₁ = inst-fn Function.congruence

_→ᶠⁿ_ : (A : Setoid{ℓₗ₁}{ℓₒ₁}) → (B : Setoid{ℓₗ₂}{ℓₒ₂}) → Type{ℓₒ₁ Lvl.⊔ ℓₒ₂ Lvl.⊔ ℓₗ₁ Lvl.⊔ ℓₗ₂}
([∃]-intro A) →ᶠⁿ ([∃]-intro B) = ∃(Function{A = A}{B = B})


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

open import Categories.Category

module Categories.Object.Subobject {o ℓ e} (𝒞 : Category o ℓ e) where

open import Level
open import Data.Product
open import Data.Unit

open import Relation.Binary using (Poset)

open import Categories.Functor
open import Categories.Category.Slice
open import Categories.Category.SubCategory
open import Categories.Category.Construction.Thin
import Categories.Morphism as Mor
import Categories.Morphism.Reasoning as MR
open import Categories.Morphism.Notation

private
  module 𝒞 = Category 𝒞

-- The Full Subcategory of the over category 𝒞/c on monomorphisms
slice-mono : 𝒞.Obj → Category _ _ _
slice-mono c = FullSubCategory (Slice 𝒞 c) {I = Σ[ α ∈ 𝒞.Obj ](α ↣ c)} λ (_ , i) → sliceobj (mor i)
  where open Mor 𝒞
        open _↣_

-- Poset of subobjects for some c ∈ 𝒞
Subobjects : 𝒞.Obj → Poset _ _ _
Subobjects c = record
  { Carrier = 𝒞ᶜ.Obj
  ; _≈_ = 𝒞ᶜ [_≅_]
  ; _≤_ = 𝒞ᶜ [_,_]
  ; isPartialOrder = record
    { isPreorder = record
      { isEquivalence = Mor.≅-isEquivalence 𝒞ᶜ
      ; reflexive = λ iso → Mor._≅_.from iso
      ; trans = λ {(α , f) (β , g) (γ , h)} i j → slicearr (chase f g h i j)
      }
    ; antisym = λ {(α , f) (β , g)} h i → record
      { from = h
      ; to = i
      ; iso = record
        { isoˡ = mono f _ _ (chase f g f h i ○ ⟺ 𝒞.identityʳ)
        ; isoʳ = mono g _ _ (chase g f g i h ○ ⟺ 𝒞.identityʳ)
        }
      }
    }
  }
  where
    𝒞ᶜ : Category _ _ _
    𝒞ᶜ = slice-mono c

    module 𝒞ᶜ = Category 𝒞ᶜ

    open Mor 𝒞 using (_↣_)
    open MR 𝒞
    open 𝒞.HomReasoning
    open _↣_

    chase : ∀ {α β γ : 𝒞.Obj} (f : 𝒞 [ α ↣ c ]) (g : 𝒞 [ β ↣ c ]) (h : 𝒞 [ γ ↣ c ])
            → (i : 𝒞ᶜ [ (α , f) , (β , g) ]) → (j : 𝒞ᶜ [ (β , g) , (γ , h) ])
            → 𝒞 [ 𝒞 [ mor h ∘ 𝒞 [ Slice⇒.h j ∘ Slice⇒.h i ] ] ≈ mor f ]
    chase f g h i j = begin
      𝒞 [ mor h ∘ 𝒞 [ Slice⇒.h j ∘ Slice⇒.h i ] ] ≈⟨ pullˡ (Slice⇒.△ j)  ⟩
      𝒞 [ mor g ∘ Slice⇒.h i ]                    ≈⟨ Slice⇒.△ i ⟩
      mor f ∎


{-# OPTIONS --safe #-}
module Cubical.Algebra.CommRing.Instances.Int where

open import Cubical.Foundations.Prelude

open import Cubical.Algebra.CommRing
open import Cubical.Data.Int as Int
  renaming ( ℤ to ℤType ; _+_ to _+ℤ_; _·_ to _·ℤ_; -_ to -ℤ_)

open CommRingStr

ℤ : CommRing ℓ-zero
fst ℤ = ℤType
0r (snd ℤ) = 0
1r (snd ℤ) = 1
_+_ (snd ℤ) = _+ℤ_
_·_ (snd ℤ) = _·ℤ_
- snd ℤ = -ℤ_
isCommRing (snd ℤ) = isCommRingℤ
  where
  abstract
    isCommRingℤ : IsCommRing 0 1 _+ℤ_ _·ℤ_ -ℤ_
    isCommRingℤ = makeIsCommRing isSetℤ Int.+Assoc (λ _ → refl)
                                 -Cancel Int.+Comm Int.·Assoc
                                 Int.·Rid ·DistR+ Int.·Comm


module Oscar.Class.Substitution where

open import Oscar.Data.Equality
open import Oscar.Function
open import Oscar.Relation
open import Oscar.Level

record Substitution {a} {A : Set a} {b} (B : A → Set b) {c} (C : A → Set c) : Set (a ⊔ b ⊔ c) where
  field
    ε : ∀ {m} → B m → C m
    _◇_ : ∀ {l m n} → (g : B m → C n) (f : B l → C m) → B l → C n
    ◇-left-identity : ∀ {m n} → (f : B m → C n) → ε ◇ f ≡̇ f
    ◇-right-identity : ∀ {m n} → (f : B m → C n) → f ◇ ε ≡̇ f
    ◇-associativity : ∀ {k l m n} (f : B k → C l) (g : B l → C m) (h : B m → C n) → h ◇ (g ◇ f) ≡̇ (h ◇ g) ◇ f

open Substitution ⦃ … ⦄ public

{-# DISPLAY Substitution._◇_ _ = _◇_ #-}

instance Substitution-id : ∀ {a} {A : Set a} {bc} {BC : A → Set bc} → Substitution BC BC
Substitution.ε Substitution-id = id
Substitution._◇_ Substitution-id g f = g ∘ f
Substitution.◇-left-identity Substitution-id _ _ = refl
Substitution.◇-right-identity Substitution-id _ _ = refl
Substitution.◇-associativity Substitution-id _ _ _ _ = refl


module Logic.Operations where

import Logic.Relations as Rel
import Logic.Equivalence as Eq
open Eq using (Equivalence; module Equivalence)

BinOp : Set -> Set
BinOp A = A -> A -> A

module MonoEq {A : Set}(Eq : Equivalence A) where

  module EqEq = Equivalence Eq
  open EqEq

  Commutative : BinOp A -> Set
  Commutative _+_ = (x y : A) -> (x + y) == (y + x)

  Associative : BinOp A -> Set
  Associative _+_ = (x y z : A) -> (x + (y + z)) == ((x + y) + z)

  LeftIdentity : A -> BinOp A -> Set
  LeftIdentity z _+_ = (x : A) -> (z + x) == x

  RightIdentity : A -> BinOp A -> Set
  RightIdentity z _+_ = (x : A) -> (x + z) == x

module Param where

  Commutative : {A : Set}(Eq : Equivalence A) -> BinOp A -> Set
  Commutative Eq = Op.Commutative
    where module Op = MonoEq Eq

  Associative : {A : Set}(Eq : Equivalence A) -> BinOp A -> Set
  Associative Eq = Op.Associative
    where module Op = MonoEq Eq

  LeftIdentity : {A : Set}(Eq : Equivalence A) -> A -> BinOp A -> Set
  LeftIdentity Eq = Op.LeftIdentity
    where module Op = MonoEq Eq

  RightIdentity : {A : Set}(Eq : Equivalence A) -> A -> BinOp A -> Set
  RightIdentity Eq = Op.RightIdentity
    where module Op = MonoEq Eq


module Data.List.First.Membership {ℓ}{A : Set ℓ} where

open import Data.Product
open import Data.List
open import Data.List.Relation.Unary.Any
open import Data.List.First hiding (find)
open import Relation.Nullary
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Level
open import Function
open import Data.Empty

_∈_ : A → List A → Set _
x ∈ l = first x ∈ l ⇒ (_≡_ x)

¬x∈[] : ∀ {x} → ¬ x ∈ []
¬x∈[] ()

find : Decidable (_≡_ {A = A}) → ∀ x l → Dec (x ∈ l)
find _≟_ x [] = no (λ ())
find _≟_ x (y ∷ l) with x ≟ y
... | yes refl = yes (here refl)
... | no  neq  with find _≟_ x l
... | yes p    = yes (there y neq p)
... | no  ¬p   = no (λ{ (here eq) → neq eq ; (there _ _ p) → ¬p p})


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

--  Restriction Functor
module Categories.Functor.Restriction where

open import Level using (Level; _⊔_)

open import Categories.Category using (Category; _[_,_]; _[_≈_])
open import Categories.Category.Restriction using (Restriction)
open import Categories.Functor using (Functor; _∘F_) renaming (id to idF)

private
  variable
    o ℓ e o′ ℓ′ e′ o″ ℓ″ e″ : Level
    C : Category o ℓ e
    D : Category o′ ℓ′ e′
    E : Category o″ ℓ″ e″

record RestrictionF {C : Category o ℓ e} {D : Category o′ ℓ′ e′}
  (RC : Restriction C) (RD : Restriction D) : Set (o ⊔ ℓ ⊔ e ⊔ o′ ⊔ ℓ′ ⊔ e′) where
  private
    module C = Category C using (Obj)
    module RC = Restriction RC
    module RD = Restriction RD
  field
    Func : Functor C D
  open Functor Func using (F₁)
  field
    F-resp-↓ : {A B : C.Obj} → (f : C [ A , B ]) → D [ F₁ (f RC.↓) ≈ (F₁ f) RD.↓ ]

id : {RC : Restriction C} → RestrictionF RC RC
id {C = C} = record { Func = idF ; F-resp-↓ = λ f → Category.Equiv.refl C }

_∘R_ : {RC : Restriction C} {RD : Restriction D} {RE : Restriction E} → RestrictionF RD RE → RestrictionF RC RD → RestrictionF RC RE
_∘R_ {C = C} {E = E} {RC} {RD} {RE} F G = record
  { Func = Func F ∘F Func G
  ; F-resp-↓ = resp
  }
  where
    open RestrictionF
    open Category E using (_≈_; module HomReasoning)
    open HomReasoning
    module F = Functor (Func F)
    module G = Functor (Func G)
    module RC = Restriction RC
    module RD = Restriction RD
    module RE = Restriction RE
    resp : ∀ {A B : Category.Obj C} → (f : C [ A , B ]) → F.₁ (G.₁ (f RC.↓)) ≈ F.₁ (G.₁ f) RE.↓
    resp f = begin
       F.₁ (G.₁ (f RC.↓)) ≈⟨ F.F-resp-≈ (F-resp-↓ G f) ⟩
       F.₁ ((G.₁ f) RD.↓) ≈⟨ F-resp-↓ F _ ⟩
       F.₁ (G.₁ f) RE.↓ ∎


------------------------------------------------------------------------------
-- Testing some inductive predicates for inequalities
------------------------------------------------------------------------------

{-# OPTIONS --exact-split              #-}
{-# OPTIONS --no-sized-types           #-}
{-# OPTIONS --no-universe-polymorphism #-}
{-# OPTIONS --without-K                #-}

module FOT.FOTC.Data.Nat.Inequalities.InductivePredicates where

open import FOTC.Base
open import FOTC.Data.Nat.Type
open import FOTC.Data.Nat.UnaryNumbers

------------------------------------------------------------------------------

module m₁ where
  data _≤_ : D → D → Set where
    z≤n : ∀ n → zero ≤ n
    s≤s : ∀ {m n} → m ≤ n → succ₁ m ≤ succ₁ n

  _<_ : D → D → Set
  m < n = succ₁ m ≤ n

  _≥_ : D → D → Set
  m ≥ n = n ≤ m

  _>_ : D → D → Set
  m > n = n < m

  x≤y→x≤Sy : ∀ {m n} → m ≤ n → m ≤ succ₁ n
  x≤y→x≤Sy {.zero} {n} (z≤n .n)  = z≤n (succ₁ n)
  x≤y→x≤Sy             (s≤s m≤n) = s≤s (x≤y→x≤Sy m≤n)

module m₂ where
  data _≤_ : D → D → Set where
    z≤n : ∀ {n} → N n → zero ≤ n
    s≤s : ∀ {m n} → N m → N n → m ≤ n → succ₁ m ≤ succ₁ n

  _<_ : D → D → Set
  m < n = succ₁ m ≤ n

  _≥_ : D → D → Set
  m ≥ n = n ≤ m

  _>_ : D → D → Set
  m > n = n < m

  x≤y→x≤Sy : ∀ {m n} → m ≤ n → m ≤ succ₁ n
  x≤y→x≤Sy (z≤n Nn)        = z≤n (nsucc Nn)
  x≤y→x≤Sy (s≤s Nm Nn m≤n) = s≤s Nm (nsucc Nn) (x≤y→x≤Sy m≤n)

  postulate
    lt    : D → D → D
    lt-00 : lt zero zero                   ≡ false
    lt-0S : ∀ n → lt zero (succ₁ n)        ≡ true
    lt-S0 : ∀ n → lt (succ₁ n) zero        ≡ false
    lt-SS : ∀ m n → lt (succ₁ m) (succ₁ n) ≡ lt m n

  le : D → D → D
  le m n = lt m (succ₁ n)

  ≤→le : ∀ {m n} → m ≤ n → le m n ≡ true
  ≤→le {n = n} (z≤n Nn) = lt-0S n
  ≤→le (s≤s nzero nzero h) = trans (lt-SS zero 1') (≤→le h)
  ≤→le (s≤s nzero (nsucc {n} Nn) h) = trans (lt-SS zero (succ₁ (succ₁ n))) (≤→le h)
  ≤→le (s≤s (nsucc {m} Nm) nzero h) = trans (lt-SS (succ₁ m) 1') (≤→le h)
  ≤→le (s≤s (nsucc {m} Nm) (nsucc {n} Nn) h) =
    trans (lt-SS (succ₁ m) (succ₁ (succ₁ n))) (≤→le h)

  le→≤ : ∀ {m n} → N m → N n → le m n ≡ true → m ≤ n
  le→≤ nzero Nn h = z≤n Nn
  le→≤ (nsucc nzero) nzero h =
    ⊥-elim (t≢f (trans (sym h) (trans (lt-SS zero zero) lt-00)))
  le→≤ (nsucc (nsucc {m} Nm)) nzero h =
    ⊥-elim (t≢f (trans (sym h) (trans (lt-SS (succ₁ m) zero) (lt-S0 m))))
  {-# CATCHALL #-}
  le→≤ (nsucc {m} Nm) (nsucc {n} Nn) h =
    s≤s Nm Nn (le→≤ Nm Nn (trans (sym (lt-SS m (succ₁ n))) h))

module m₃ where
  data _≤_ : ∀ {m n} → N m → N n → Set where
    z≤n : ∀ {n} → (Nn : N n)                          → nzero ≤ Nn
    s≤s : ∀ {m n} → (Nm : N m) → (Nn : N n) → Nm ≤ Nn → nsucc Nm ≤ nsucc Nn

  _<_ : ∀ {m n} → N m → N n → Set
  Nm < Nn = nsucc Nm ≤ Nn

  _≥_ : ∀ {m n} → N m → N n → Set
  Nm ≥ Nn = Nn ≤ Nm

  _>_ : ∀ {m n} → N m → N n → Set
  Nm > Nn = Nn < Nm

  x≤y→x≤Sy : ∀ {m n} → (Nm : N m) → (Nn : N n) → Nm ≤ Nn → Nm ≤ nsucc Nn
  x≤y→x≤Sy .nzero       Nn         (z≤n .Nn)         = z≤n (nsucc Nn)
  x≤y→x≤Sy .(nsucc Nm) .(nsucc Nn) (s≤s Nm Nn Nm≤Nn) =
    s≤s Nm (nsucc Nn) (x≤y→x≤Sy Nm Nn Nm≤Nn)


module plfa-code.Equality where

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

infix 4 _≡_

sym : ∀ {A : Set} {x y : A}
  → x ≡ y
    -------
  → y ≡ x
sym refl = refl

trans : ∀ {A : Set} {x y z : A}
  → x ≡ y
  → y ≡ z
    -------
  → x ≡ z
trans refl refl = refl

cong : ∀ {A B : Set} (f : A → B) {x y : A}
  → x ≡ y
    -----------
  → f x ≡ f y
cong f refl  =  refl

cong₂ : ∀ {A B C : Set} (f : A → B → C) {u x : A} {v y : B}
  → u ≡ x
  → v ≡ y
    ---------------
  → f u v ≡ f x y
cong₂ _ refl refl  =  refl

cong-app : ∀ {A B : Set} {f g : A → B}
  → f ≡ g
    ------------------------
  → ∀ (x : A) → f x ≡ g x
cong-app refl _ = refl

subst : ∀ {A : Set} {x y : A} (P : A → Set)
  → x ≡ y
    -----------
  → P x → P y
subst _ refl px = px

module ≡-Reasoning {A : Set} where

  infix  1 begin_
  infixr 2 _≡⟨⟩_ _≡⟨_⟩_
  infix  3 _∎

  begin_ : ∀ {x y : A}
    → x ≡ y
      -------
    → x ≡ y
  begin x≡y = x≡y

  _≡⟨⟩_ : ∀ (x : A) {y : A}
    → x ≡ y
      -------
    → x ≡ y
  x ≡⟨⟩ x≡y  =  x≡y

  _≡⟨_⟩_ : ∀ (x : A) {y z : A}
    → x ≡ y
    → y ≡ z
      -------
    → x ≡ z
  x ≡⟨ x≡y ⟩ y≡z  =  trans x≡y y≡z

  _∎ : ∀ (x : A)
      ------
    → x ≡ x
  x ∎  = refl

open ≡-Reasoning

trans′ : ∀ {A : Set} {x y z : A}
  → x ≡ y
  → y ≡ z
    -------
  → x ≡ z
trans′ {A} {x} {y} {z} x≡y y≡z =
  begin
    x
  ≡⟨ x≡y ⟩
    y
  ≡⟨ y≡z ⟩
    z
  ∎

data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ

infixl 6 _+_

_+_ : ℕ → ℕ → ℕ
zero    + n  =  n
(suc m) + n  =  suc (m + n)

-- use postulate
postulate
  +-identity : ∀ (m : ℕ) → m + zero ≡ m
  +-suc : ∀ (m n : ℕ) → m + suc n ≡ suc (m + n)

+-comm : ∀ (m n : ℕ) → m + n ≡ n + m
+-comm m zero =
  begin
    m + zero
  ≡⟨ +-identity m ⟩
    m
  ≡⟨⟩
    zero + m
  ∎
+-comm m (suc n) =
  begin
    m + suc n
  ≡⟨ +-suc m n ⟩
    suc (m + n)
  ≡⟨ cong suc (+-comm m n) ⟩
    suc (n + m)
  ≡⟨⟩
    suc n + m
  ∎

data _≤_ : ℕ → ℕ → Set where

  z≤n : ∀ {n : ℕ}
      ---------
    → zero ≤ n

  s≤s : ∀ {m n : ℕ}
    → m ≤ n
      --------------
    → suc m ≤ suc n

infix 4 _≤_

postulate
  ≤-trans : ∀ {m n p : ℕ} → m ≤ n → n ≤ p → m ≤ p
  ≤-refl : ∀ {n : ℕ} → n ≤ n

≡→≤ : ∀ {x y} → x ≡ y → x ≤ y
≡→≤ refl = ≤-refl

module ≤-Reasoning where

  infix  1 ≤begin_
  infixr 2 _≤⟨⟩_ _≤⟨_⟩_ _≤[_]_
  infix  3 _≤∎

  ≤begin_ : ∀ {x y} → x ≤ y → x ≤ y
  ≤begin x≤y  =  x≤y

  _≤⟨⟩_ : ∀ (x) {y : ℕ} → x ≤ y → x ≤ y
  _ ≤⟨⟩ x≤y  =  x≤y

  _≤⟨_⟩_ : ∀ (x) {y z : ℕ} → x ≤ y → y ≤ z → x ≤ z
  x ≤⟨ x≤y ⟩ y≤z  =  ≤-trans x≤y y≤z

  _≤[_]_ : ∀ (x) {y z : ℕ} → x ≡ y → y ≤ z → x ≤ z
  x ≤[ x≡y ] y≤z = ≤-trans (≡→≤ x≡y) y≤z

  _≤∎ : ∀ x → x ≤ x
  _ ≤∎ = ≤-refl

open ≤-Reasoning

+-monoʳ-≤ : ∀ (n p q : ℕ) → p ≤ q → (n + p) ≤ (n + q)

+-monoʳ-≤ zero p q p≤q =
  ≤begin
    (zero + p)
  ≤⟨⟩
    p
  ≤⟨ p≤q ⟩
    q
  ≤⟨⟩
    zero + q
  ≤∎
+-monoʳ-≤ (suc n) p q p≤q =
  ≤begin
    suc n + p
  ≤⟨⟩
    suc (n + p)
  ≤⟨ s≤s (+-monoʳ-≤ _ _ _ p≤q) ⟩
    suc (n + q)
  ≤⟨⟩
    suc n + q
  ≤∎

+-monoˡ-≤ : ∀ (m n p : ℕ) → m ≤ n → (m + p) ≤ (n + p)
+-monoˡ-≤ m n p m≤n =
  ≤begin
    m + p
  ≤[ +-comm m p ]
    p + m
  ≤⟨ +-monoʳ-≤ p _ _ m≤n ⟩
    p + n
  ≤[ +-comm p n ]
    n + p
  ≤∎

+-mono-≤ : ∀ (m n p q : ℕ) → m ≤ n → p ≤ q → m + p ≤ n + q
+-mono-≤ m n p q m≤n p≤q =
  ≤begin
    m + p
  ≤⟨ +-monoˡ-≤ _ _ _ m≤n ⟩
    n + p
  ≤⟨ +-monoʳ-≤ _ _ _ p≤q ⟩
    n + q
  ≤∎

data even : ℕ → Set
data odd  : ℕ → Set

data even where

  even-zero : even zero

  even-suc : ∀ {n : ℕ}
    → odd n
      -------------
    → even (suc n)

data odd where
  odd-suc : ∀ {n : ℕ}
    → even n
      ------------
    → odd (suc n)

{-# BUILTIN EQUALITY _≡_ #-}

even-comm : ∀ (m n : ℕ)
  → even (m + n)
    -------------
  → even (n + m)
even-comm m n ev rewrite +-comm n m = ev

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

even-comm′ : ∀ (m n : ℕ)
  → even (m + n)
    ------------
  → even (n + m)
even-comm′ m n ev with   m + n  | +-comm m n
...                  | .(n + m) | refl       = ev

_≐_ : ∀ {A : Set} (x y : A) → Set₁
_≐_ {A} x y = ∀ (P : A → Set) → P x → P y

refl-≐ : ∀ {A : Set} {x : A}
  → x ≐ x
refl-≐ P Px = Px

trans-≐ : ∀ {A : Set} {x y z : A}
  → x ≐ y
  → y ≐ z
    ------
  → x ≐ z
trans-≐ x≐y y≐z P Px  =  y≐z P (x≐y P Px)

sym-≐ : ∀ {A : Set} {x y : A}
  → x ≐ y
    ------
  → y ≐ x
sym-≐ {A} {x} {y} x≐y P  =  Qy
  where
    Q : A → Set
    Q z = P z → P x
    Qx : Q x
    Qx = refl-≐ P
    Qy : Q y
    Qy = x≐y Q Qx

≡-implies-≐ : ∀ {A : Set} {x y : A}
  → x ≡ y
    -------
  → x ≐ y
≡-implies-≐ x≡y P  =  subst P x≡y

≐-implies-≡ : ∀ {A : Set} {x y : A}
  → x ≐ y
    -------
  → x ≡ y
≐-implies-≡ {A} {x} {y} x≐y = Qy
  where
    Q : A → Set
    Q z = x ≡ z
    Qx : Q x
    Qx = refl
    Qy : Q y
    Qy = x≐y Q Qx

open import Level using (Level; _⊔_) renaming (zero to lzero; suc to lsuc)

data _≡′_ {ℓ : Level} {A : Set ℓ} (x : A) : A → Set ℓ where
  refl′ : x ≡′ x

sym′ : ∀ {ℓ : Level} {A : Set ℓ} {x y : A}
  → x ≡′ y
    --------
  → y ≡′ x
sym′ refl′ = refl′

_≐′_ : ∀ {ℓ : Level} {A : Set ℓ} (x y : A) → Set (lsuc ℓ)
_≐′_ {ℓ} {A} x y = ∀ (P : A → Set ℓ) → P x → P y


{-# OPTIONS --rewriting #-}

module NewEquations where

open import Common.Prelude hiding (map; _++_)
open import Common.Equality

infixr 5 _++_

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

_++_ : ∀ {A : Set} → List A → List A → List A
[] ++ ys = ys
(x ∷ xs) ++ ys = x ∷ (xs ++ ys)

fold : ∀ {A B : Set} → (A → B → B) → B → List A → B
fold f v [] = v
fold f v (x ∷ xs) = f x (fold f v xs)

++-[] : ∀ {A} {xs : List A} → xs ++ [] ≡ xs
++-[] {xs = []} = refl
++-[] {xs = x ∷ xs} = cong (_∷_ x) ++-[]

++-assoc : ∀ {A} {xs ys zs : List A} → (xs ++ ys) ++ zs ≡ xs ++ (ys ++ zs)
++-assoc {xs = []} = refl
++-assoc {xs = x ∷ xs} = cong (_∷_ x) (++-assoc {xs = xs})

map-id : ∀ {A} {xs : List A} → map (λ x → x) xs ≡ xs
map-id {xs = []} = refl
map-id {xs = x ∷ xs} = cong (_∷_ x) map-id

map-fuse : ∀ {A B C} {f : B → C} {g : A → B} {xs : List A} → map f (map g xs) ≡ map (λ x → f (g x)) xs
map-fuse {xs = []} = refl
map-fuse {xs = x ∷ xs} = cong (_∷_ _) map-fuse

map-++ : ∀ {A B} {f : A → B} {xs ys : List A} → map f (xs ++ ys) ≡ (map f xs) ++ (map f ys)
map-++ {xs = []} = refl
map-++ {xs = x ∷ xs} = cong (_∷_ _) (map-++ {xs = xs})

fold-map : ∀ {A B C} {f : A → B} {c : B → C → C} {n : C} {xs : List A} →
           fold c n (map f xs) ≡ fold (λ x → c (f x)) n xs
fold-map {xs = []} = refl
fold-map {c = c} {xs = x ∷ xs} = cong (c _) (fold-map {xs = xs})

fold-++ : ∀ {A B} {c : A → B → B} {n : B} {xs ys : List A} →
          fold c n (xs ++ ys) ≡ fold c (fold c n ys) xs
fold-++ {xs = []} = refl
fold-++ {c = c} {xs = x ∷ xs} = cong (c _) (fold-++ {xs = xs})

{-# BUILTIN REWRITE _≡_ #-}
{-# REWRITE ++-[] #-}
{-# REWRITE ++-assoc #-}
{-# REWRITE map-id #-}
{-# REWRITE map-fuse #-}
{-# REWRITE map-++ #-}
{-# REWRITE fold-map #-}
{-# REWRITE fold-++ #-}

record _×_ (A B : Set) : Set where
  constructor _,_
  field
    fst : A
    snd : B

swap : ∀ {A B} → A × B → B × A
swap (x , y) = y , x

test₁ : ∀ {A B} {xs : List (A × B)} → map swap (map swap xs) ≡ xs
test₁ = refl


{-# OPTIONS --without-K #-}
module Relation.Path.Operation where

open import Basics
open import Relation.Equality
open import Data.Product

infixr 4 _∙_
infix 9 _⁻¹

-- Path inversion
_⁻¹ : ∀ {a}{A : Set a}{x y : A} → (x ≡ y) → (y ≡ x)
_⁻¹ = ind₌ (λ x y _ → y ≡ x) (λ _ → refl) _ _

-- Composition of paths
_∙_ : ∀ {a}{A : Set a}{x y z : A} → (x ≡ y) → (y ≡ z) → (x ≡ z)
_∙_ {z = z} = ind₌ (λ x y _ → y ≡ z → x ≡ z) (λ _ p → p) _ _

-- Unit laws for Composition

rup : ∀ {i}{A : Set i}{a b : A} → (p : a ≡ b) → (p ∙ refl) ≡ p
rup = ind₌ (λ _ _ p → (p ∙ refl) ≡ p) (λ _ → refl) _ _

lup : ∀ {i}{A : Set i}{a b : A} → (p : a ≡ b) → (refl ∙ p) ≡ p
lup _ = refl

-- Associativity of path composition
assoc : ∀ {i}{A : Set i}{a b c d : A} → (p : a ≡ b) (q : b ≡ c) (r : c ≡ d) → (p ∙ (q ∙ r)) ≡ ((p ∙ q) ∙ r)
assoc {c = c} {d = d} = ind₌
  (λ _ b p → (q : b ≡ c) (r : c ≡ d) → (p ∙ q ∙ r) ≡ ((p ∙ q) ∙ r))
  (λ b → ind₌
    (λ _ c q → (r : c ≡ d) → (refl ∙ q ∙ r) ≡ ((refl ∙ q) ∙ r))
    (λ _ _ → refl) _ _)
    _ _

-- It is a familiar fact in topology that when we concatenate a path p with the
-- reversed path p ⁻¹, we don’t literally obtain a constant path (which
-- corresponds to the equality refl in type theory) — instead we have a
-- homotopy, or higher path, from p ∙ p ⁻¹ to the constant path.

there-and-back-again : ∀ {i} {A : Set i}{x y : A}{p : x ≡ y} → (p ∙ p ⁻¹) ≡ refl
there-and-back-again {i} {A} {x}{y} {p} = ind₌ D d _ _ p where
  D : (x y : A) → (x ≡ y) → Set i
  D x y p = (p ∙ p ⁻¹) ≡ refl

  d : (x₁ : A) → D x₁ x₁ refl
  d = λ x → refl

back-and-there-again : ∀ {i}{A : Set i}{x y : A}{p : x ≡ y} → (p ⁻¹ ∙ p) ≡ refl
back-and-there-again {i} {A} {x}{y} {p} = ind₌ D d _ _ p where
  D : (x y : A) → (p : x ≡ y) → Set i
  D x y p = (p ⁻¹ ∙ p) ≡ refl

  d : (x₁ : A) → D x₁ x₁ refl
  d = λ x → refl

-- Paths are functor looking things.
ap : ∀ {i j} {A : Set i}{B : Set j}{x y : A}{f : A → B} → (x ≡ y) → (f x ≡ f y)
ap {i}{j} {A}{B} {x}{y}{f} p = ind₌ D d x y p where
  D : (x y : A) → (p : x ≡ y) → Set j
  D x y p = f x ≡ f y

  d : (x : A) → D x x refl
  d = λ x → refl

--
ap₂ : ∀ {i j k} {A : Set i}{B : Set j}{C : Set k}{x x′ : A}{y y′ : B}(f : A → B → C) → (x ≡ x′) → (y ≡ y′) → (f x y ≡ f x′ y′)
ap₂ f p q = ap {f = λ _ → f _ _} p ∙ ap {f = f _} q

-- The dependently typed version of `ap` takes a type family and relates its instantiations with p
transport : ∀ {i j} {A : Set i}{P : A → Set j}{x y : A} → (p : x ≡ y) → P x → P y
transport {i}{j} {A}{P} {x}{y} p = ind₌ D d x y p where
    D : (x y : A) → (p : x ≡ y) → Set j
    D x y p = P x → P y

    d : (x : A) → D x x refl
    d = λ x → id

2-11-2 : ∀ {i} {A : Set i} → (a : A) {x₁ x₂ : A} (p : x₁ ≡ x₂) (q : a ≡ x₁) → (transport p q) ≡ (q ∙ p)
2-11-2 a = ind₌
  (λ x _ p → (q : a ≡ x) → (transport {P = (λ x → a ≡ x)} p q) ≡ (q ∙ p))
  (λ _ q → rup q ⁻¹)
  _ _

-- Basically, P respects equality
path-lifting : ∀ {a p}{A : Set a}{x y : A}{P : A → Set p} → (u : P x) → (p : x ≡ y) → (x , u) ≡ (y , u)
path-lifting u = cong (λ z → z , u)

-- Look, transport works in the "upper" space too!
apd : ∀ {i} {A : Set i}{P : A → Set i}{f : (x : A) → P x}{x y : A} → (p : x ≡ y) → (transport p (f x) ≡ f y)
apd {i} {A}{P} {f}{x}{y} p = ind₌ D d x y p where
  D : (x y : A) → (p : x ≡ y) → Set i
  D x y p = transport p (f x) ≡ f y

  d : (x : A) → D x x refl
  d = λ x → refl

-- We can also fix B and make transport work like fmap with equalities.
transportconst : ∀ {i} {A : Set i}{B : Set i}{P : A → B}{x y : A} → (p : x ≡ y) → (b : B) → transport p b ≡ b
transportconst {i} {A}{B}{P} {x}{y} p b = ind₌ D d x y p where
  D : (x y : A) → (x ≡ y) → Set i
  D x y p = transport p b ≡ b

  d : (x : A) → D x x refl
  d = λ x → refl

-- Path Structure for Product Types
split-path₌ : ∀ {a b}{A : Set a}{B : Set b} → (x y : (A × B)) → (x ≡ y) → (proj₁ x ≡ proj₁ y) × (proj₂ x ≡ proj₂ y)
split-path₌ xs ys p = ap {f = proj₁} p , ap {f = proj₂} p

{-
pair₌ : ∀ {a b}{A : Set a}{B : Set b} → (x y : (A × B)) → (proj₁ x ≡ proj₁ y) × (proj₂ x ≡ proj₂ y) → (x ≡ y)
pair₌ (a₁ , b₁) (a₂ , b₂) (p , q) = {!!}
-}


{-# OPTIONS --cubical --no-import-sorts --safe #-}
module Cubical.HITs.Cost.Base where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.HITs.PropositionalTruncation
open import Cubical.Data.Nat
open import Cubical.Data.Sigma

private
  variable
    ℓ : Level
    A B C : Type ℓ

Cost : (A : Type ℓ) → Type ℓ
Cost A = A × ∥ ℕ ∥

-- To compare two elements of Cost A we only need to look at the first parts
Cost≡ : (x y : Cost A) → x .fst ≡ y .fst → x ≡ y
Cost≡ _ _ = Σ≡Prop λ _ → squash

-- To make it easier to program with Cost A we prove that it forms a
-- monad which counts the number of calls to >>=. We could also turn
-- it into a proper state monad which tracks the cost, but for the
-- programs we write later this simple version suffices
_>>=_ : Cost A → (A → Cost B) → Cost B
(x , m) >>= g with g x
... | (y , n) = (y , map suc (map2 _+_ m n))

return : A → Cost A
return x = (x , ∣ 0 ∣)

-- The monad laws all hold by Cost≡

>>=-return : (f : Cost A) → f >>= return ≡ f
>>=-return f = Cost≡ _ _ refl

return->>= : (a : A) (f : A → Cost B) → return a >>= f ≡ f a
return->>= a f = Cost≡ _ _ refl

>>=-assoc : (f : Cost A) (g : A → Cost B) (h : B → Cost C)
          → (f >>= g) >>= h ≡ f >>= (λ x → g x >>= h)
>>=-assoc f g h = Cost≡ _ _ refl

-- An inefficient version of addition which recurses on both arguments
addBad : ℕ → ℕ → Cost ℕ
addBad 0 0       = return 0
addBad 0 (suc y) = do
  x ← addBad 0 y
  return (suc x)
addBad (suc x) y = do
  z ← addBad x y
  return (suc z)

-- More efficient addition which only recurse on the first argument
add : ℕ → ℕ → Cost ℕ
add 0       y = return y
add (suc x) y = do
  z ← add x y
  return (suc z)

private
  -- addBad x y will do x + y calls
  _ : addBad 3 5 ≡ (8 , ∣ 8 ∣)
  _ = refl

  -- add x y will only do x recursive calls
  _ : add 3 5 ≡ (8 , ∣ 3 ∣)
  _ = refl

-- Despite addBad and add having different cost we can still prove
-- that they are equal functions
add≡addBad : add ≡ addBad
add≡addBad i x y = Cost≡ (add x y) (addBad x y) (rem x y) i
  where
  rem : (x y : ℕ) → add x y .fst ≡ addBad x y .fst
  rem 0 0       = refl
  rem 0 (suc y) = cong suc (rem 0 y)
  rem (suc x) y = cong suc (rem x y)

-- Another example: computing Fibonacci numbers

fib : ℕ → Cost ℕ
fib 0 = return 0
fib 1 = return 1
fib (suc (suc x)) = do
  y ← fib (suc x)
  z ← fib x
  return (y + z)

fibTail : ℕ → Cost ℕ
fibTail 0       = return 0
fibTail (suc x) = fibAux x 1 0
  where
  fibAux : ℕ → ℕ → ℕ → Cost ℕ
  fibAux 0 res _          = return res
  fibAux (suc x) res prev = do
    r ← fibAux x (res + prev) res
    return r

private
  _ : fib 10 ≡ (55 , ∣ 176 ∣)
  _ = refl

  _ : fibTail 10 ≡ (55 , ∣ 9 ∣)
  _ = refl

  _ : fib 20 ≡ (6765 , ∣ 21890 ∣)
  _ = refl

  _ : fibTail 20 ≡ (6765 , ∣ 19 ∣)
  _ = refl

-- Exercise left to the reader: prove that fib and fibTail are equal functions
-- fib≡fibTail : fib ≡ fibTail
-- fib≡fibTail i x = Cost≡ (fib x) (fibTail x) (rem x) i
--   where
--   rem : (x : ℕ) → fib x .fst ≡ fibTail x .fst
--   rem zero = refl
--   rem (suc zero) = refl
--   rem (suc (suc x)) = {!!}


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

open import Relation.Binary using (Rel; Setoid; IsEquivalence)
module Structures
  {a ℓ} {A : Set a}  -- The underlying set
  (_≈_ : Rel A ℓ)    -- The underlying equality relation
  where

open import Algebra.Core
open import Level using (_⊔_)
open import Data.Product using (_,_; proj₁; proj₂)
open import Algebra.Definitions _≈_
open import Algebra.Structures _≈_
open import Definitions _≈_

------------------------------------------------------------------------
-- Structures with 1 binary operation
------------------------------------------------------------------------

record IsLatinQuasigroup (∙ : Op₂ A ) : Set (a ⊔ ℓ) where
  field
    isMagma     : IsMagma ∙
    latinSquare : LatinSquare ∙

  open IsMagma isMagma public

  latinSquare₁ : LatinSquare₁ ∙
  latinSquare₁ = proj₁ latinSquare

  latinSquare₂ : LatinSquare₂ ∙
  latinSquare₂ = proj₂ latinSquare

record IsIdempotentMagma (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isMagma : IsMagma ∙
    idem    : Idempotent ∙

  open IsMagma isMagma public

record IsAlternateMagma (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isMagma  : IsMagma ∙
    alter    : Alternative ∙

  open IsMagma isMagma public

record IsFlexibleMagma (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isMagma  : IsMagma ∙
    flex     : Flexible ∙

  open IsMagma isMagma public

record IsMedialMagma (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isMagma : IsMagma ∙
    medial  : Medial ∙

  open IsMagma isMagma public

record IsSemimedialMagma (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isMagma : IsMagma ∙
    semiMedial  : Semimedial ∙

  open IsMagma isMagma public

record IsInverseSemigroup (∙ : Op₂ A) : Set (a ⊔ ℓ) where
  field
    isSemigroup     : IsSemigroup ∙
    pseudoInverse   : PseudoInverse ∙

  open IsSemigroup isSemigroup public

------------------------------------------------------------------------
-- Structures with 1 binary operation and 1 element
------------------------------------------------------------------------

record IsLeftUnitalMagma (∙ : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isMagma  : IsMagma ∙
    identity : LeftIdentity ε ∙

  open IsMagma isMagma public

record IsRightUnitalMagma (∙ : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isMagma  : IsMagma ∙
    identity : RightIdentity ε ∙

  open IsMagma isMagma public

------------------------------------------------------------------------
-- Structures with 2 binary operations, 1 unary operation & 1 element
------------------------------------------------------------------------

record IsNonAssociativeRing (+ * : Op₂ A) (-_ : Op₁ A) (0# 1# : A) : Set (a ⊔ ℓ) where
  field
    +-isAbelianGroup : IsAbelianGroup + 0# -_
    *-cong           : Congruent₂ *
    identity         : Identity 1# *
    distrib          : * DistributesOver +
    zero             : Zero 0# *

  open IsAbelianGroup +-isAbelianGroup public
    renaming
    ( assoc                   to +-assoc
    ; ∙-cong                  to +-cong
    ; ∙-congˡ                 to +-congˡ
    ; ∙-congʳ                 to +-congʳ
    ; identity                to +-identity
    ; identityˡ               to +-identityˡ
    ; identityʳ               to +-identityʳ
    ; inverse                 to -‿inverse
    ; inverseˡ                to -‿inverseˡ
    ; inverseʳ                to -‿inverseʳ
    ; ⁻¹-cong                 to -‿cong
    ; comm                    to +-comm
    ; isMagma                 to +-isMagma
    ; isSemigroup             to +-isSemigroup
    ; isMonoid                to +-isMonoid
    ; isUnitalMagma           to +-isUnitalMagma
    ; isCommutativeMagma      to +-isCommutativeMagma
    ; isCommutativeMonoid     to +-isCommutativeMonoid
    ; isCommutativeSemigroup  to +-isCommutativeSemigroup
    ; isInvertibleMagma       to +-isInvertibleMagma
    ; isInvertibleUnitalMagma to +-isInvertibleUnitalMagma
    ; isGroup                 to +-isGroup
    )

  *-isMagma : IsMagma *
  *-isMagma = record
    { isEquivalence = isEquivalence
    ; ∙-cong        = *-cong
    }

  *-identityˡ : LeftIdentity 1# *
  *-identityˡ = proj₁ identity

  *-identityʳ : RightIdentity 1# *
  *-identityʳ = proj₂ identity

------------------------------------------------------------------------
-- Structures with 3 binary operation and 1 element
------------------------------------------------------------------------

record IsLeftBolLoop (∙ \\ // : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isLoop  : IsLoop ∙ \\ //  ε
    leftBol : LeftBol ∙

  open IsLoop isLoop public

record IsRightBolLoop (∙ \\ // : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isLoop   : IsLoop ∙ \\ //  ε
    rightBol : RightBol ∙

  open IsLoop isLoop public

record IsMoufangLoop (∙ \\ // : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isLoop           : IsLoop ∙ \\ // ε
    moufangIdentity  : MoufangIdentity₁ ∙
    moufangIdentity₂ : MoufangIdentity₂ ∙
    moufangIdentity₃ : MoufangIdentity₃ ∙
    moufangIdentity₄ : MoufangIdentity₄ ∙

  open IsLoop isLoop public

record IsPique (∙ \\ // : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
  field
    isQuasigroup : IsQuasigroup ∙ \\ //
    idem         : Idempotent ∙

  open IsQuasigroup isQuasigroup public


module *-example where

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl)
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _∎)

open import Naturals using (_*_)

*-example : 3 * 4 ≡ 12
*-example =
  begin
    3 * 4
  ≡⟨⟩
    4 + (2 * 4)
  ≡⟨⟩
    4 + (4 + (1 * 4))
  ≡⟨⟩
    4 + (4 + (4 + (0 * 4)))
  ≡⟨⟩
    4 + (4 + (4 + 0))
  ≡⟨⟩
    12
  ∎


-- an example showing how to use sigma types to define a type for non-zero natural numbers
module nat-nonzero where

open import bool
open import eq
open import nat
open import nat-thms
open import product

ℕ⁺ : Set
ℕ⁺ = Σ ℕ (λ n → iszero n ≡ ff)

suc⁺ : ℕ⁺ → ℕ⁺
suc⁺ (x , p) = (suc x , refl)

_+⁺_ : ℕ⁺ → ℕ⁺ → ℕ⁺
(x , p) +⁺ (y , q) = x + y , iszerosum2 x y p

_*⁺_ : ℕ⁺ → ℕ⁺ → ℕ⁺
(x , p) *⁺ (y , q) = (x * y , iszeromult x y p q)


open import Agda.Builtin.Nat renaming (Nat to ℕ)
open import Agda.Builtin.Equality

data Vec (A : Set) : ℕ → Set where
  []   :  Vec A zero
  _∷_  :  ∀{n} (x : A) (xs : Vec A n) → Vec A (suc n)

data All₂ {A : Set} {B : Set} (R : A → B → Set) : ∀ {k} → Vec A k → Vec B k → Set where
  []   :  All₂ R [] []
  _∷_  :  ∀ {k x y} {xs : Vec A k} {ys : Vec B k}
          (r : R x y) (rs : All₂ R xs ys) → All₂ R (x ∷ xs) (y ∷ ys)

Det : ∀ {A : Set} {B : Set} (R : A → B → Set) → Set
Det R = ∀{a b c} → R a b → R a c → b ≡ c

detAll₂ : ∀ {A : Set} {B : Set} (R : A → B → Set) (h : Det R) → Det (All₂ R)
detAll₂ R h rab rac = {!rab!}


module Oscar.Data.Vec.Injectivity where

open import Oscar.Data.Equality
open import Oscar.Data.Vec

Vec-head-inj : ∀ {a} {A : Set a} {x₁ x₂ : A} {N} {xs₁ xs₂ : Vec A N} → x₁ ∷ xs₁ ≡ x₂ ∷ xs₂ → x₁ ≡ x₂
Vec-head-inj refl = refl

Vec-tail-inj : ∀ {a} {A : Set a} {x₁ x₂ : A} {N} {xs₁ xs₂ : Vec A N} → x₁ ∷ xs₁ ≡ x₂ ∷ xs₂ → xs₁ ≡ xs₂
Vec-tail-inj refl = refl


module sets.nat.core where

open import level
open import decidable
open import equality.core
open import function.core
open import function.isomorphism.core
open import sets.empty

infixr 8 _^_
infixl 7 _*_
infixl 6 _+_

data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ

{-# BUILTIN NATURAL ℕ    #-}

pred : ℕ → ℕ
pred zero    = zero
pred (suc n) = n

_+_ : ℕ → ℕ → ℕ
zero  + n = n
suc m + n = suc (m + n)

_*_ : ℕ → ℕ → ℕ
0 * n = zero
suc m * n = n + m * n

_^_ : ℕ → ℕ → ℕ
n ^ 0 = 1
n ^ (suc m) = n * (n ^ m)

suc-inj : injective suc
suc-inj = ap pred

_≟_ : (a b : ℕ) → Dec (a ≡ b)
zero  ≟ zero  = yes refl
zero  ≟ suc _ = no (λ ())
suc _ ≟ zero  = no (λ ())
suc a ≟ suc b with a ≟ b
suc a ≟ suc b | yes a≡b = yes $ ap suc a≡b
suc a ≟ suc b | no ¬a≡b = no $ (λ sa≡sb → ¬a≡b (ap pred sa≡sb))


-- Andreas, 2015-03-12
-- Sizes should be irrelevant in terms, while they are relevant in types!

{-# OPTIONS --experimental-irrelevance #-}

open import Common.Size
open import Common.Equality

module IrrelevantSizes where

  -- Nat i is shape-irrelevant in i.

  data Nat ..(i : Size) : Set where
    zero : .(j : Size< i) → Nat i
    suc  : .(j : Size< i) → Nat j → Nat i

  add : .(i : Size) → Nat i → Nat ∞ → Nat ∞
  add i (zero j) y = y
  add i (suc j x) y = suc ∞ (add j x y)

  -- Proving this lemma is much easier with irrelevant sizes
  -- in constructors zero and suc

  plus0 : .(i : Size) (x : Nat i) → add ∞ x (zero ∞) ≡ x
  plus0 i (zero j) = refl                       -- Goal: zero ∞ = zero j
  plus0 i (suc j x) = cong (suc ∞) (plus0 j x)  -- Goal: suc ∞ (add j x (zero ∞)) ≡ suc j x


module Nat where

open import Data.Product
open import Data.Sum
open import Relation.Binary.PropositionalEquality as Eq
open import Data.Empty
open import Level hiding (zero)

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

open Eq.≡-Reasoning

¬_ : { ℓ : Level} → Set ℓ → Set ℓ
¬ P = P → ⊥

≡-succ : (n m : ℕ) → succ n ≡ succ m → n ≡ m
≡-succ zero .zero refl = refl
≡-succ (succ n) .(succ n) refl = refl

sn≢0 : (n : ℕ) → ¬ (succ n ≡ zero)
sn≢0 _ ()

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

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

+-rUnit : (n : ℕ) → n + zero ≡ n
+-rUnit zero = refl
+-rUnit (succ n) = cong succ (+-rUnit n)

+-lUnit : (n : ℕ) → zero + n ≡ n
+-lUnit _ = refl

+-assoc : (n m l : ℕ) → n + (m + l) ≡ (n + m) + l
+-assoc zero m l = refl
+-assoc (succ n) m l = cong succ (+-assoc n m l)

+-right : (n m : ℕ) → n + succ m ≡ succ (n + m)
+-right zero m = refl
+-right (succ n) m = cong succ (+-right n m)

+-comm : (m n : ℕ) → m + n ≡ n + m
+-comm zero n = sym (+-rUnit n)
+-comm (succ m) n = begin
        succ (m + n)
    ≡⟨ cong succ (+-comm m n) ⟩
        succ (n + m)
    ≡⟨ sym (+-right n m) ⟩
        n + succ m
    ∎

+-lCancel : (n m l : ℕ) → l + n ≡ l + m → n ≡ m
+-lCancel n m zero p = p
+-lCancel n m (succ l) p = +-lCancel n m l (≡-succ (l + n) (l + m) p)

+-rCancel : (n m l : ℕ) → n + l ≡ m + l → n ≡ m
+-rCancel n m zero p =
    begin
        n
    ≡⟨ sym (+-rUnit n) ⟩
        n + zero
    ≡⟨ p ⟩
        m + zero
    ≡⟨ +-rUnit m ⟩
        m
    ∎
+-rCancel n m (succ l) n+sl≡m+sl = +-rCancel n m l (≡-succ (n + l) (m + l)
    (begin
        succ (n + l)
    ≡⟨ sym (+-right n l) ⟩
        n + succ l
    ≡⟨ n+sl≡m+sl ⟩
        m + succ l
    ≡⟨ +-right m l ⟩
        succ (m + l)
    ∎))

*-rAbsorp : (n : ℕ) → n * zero ≡ zero
*-rAbsorp zero = refl
*-rAbsorp (succ n) = begin
        succ n * zero
    ≡⟨ refl ⟩
        zero + (n * zero)
    ≡⟨ cong (λ x → zero + x) (*-rAbsorp n) ⟩
        zero + zero
    ≡⟨ refl ⟩
        zero
    ∎

*-right : (m n : ℕ) → m * succ n ≡ (m * n) + m
*-right zero n = begin
        zero * succ n
    ≡⟨ refl ⟩
        zero
    ≡⟨ refl ⟩
        zero * n
    ≡⟨ +-rUnit (zero * n) ⟩
        (zero * n) + zero
    ∎
*-right (succ m) n = begin
        succ m * succ n
    ≡⟨ refl ⟩
        succ n + (m * succ n)
    ≡⟨ cong (λ x → succ n + x) (*-right m n) ⟩
        succ n + ((m * n) + m)
    ≡⟨ refl ⟩
        succ (n + ((m * n) + m))
    ≡⟨ cong succ (+-assoc n (m * n) m) ⟩
        succ ((n + (m * n)) + m)
    ≡⟨ sym (+-right (n + (m * n)) m) ⟩
        (succ m * n) + succ m
    ∎

+*-rDist : (m n l : ℕ) → (m + n) * l ≡ (m * l) + (n * l)
+*-rDist m n zero = begin
        (m + n) * zero
    ≡⟨ *-rAbsorp (m + n) ⟩
        zero
    ≡⟨ sym (*-rAbsorp m) ⟩
        m * zero
    ≡⟨ sym (+-rUnit (m * zero)) ⟩
        (m * zero) + zero
    ≡⟨ cong (λ x → (m * zero) + x) (sym (*-rAbsorp n)) ⟩
        (m * zero) + (n * zero)
    ∎
+*-rDist m n (succ l) = begin
        (m + n) * succ l
    ≡⟨ *-right (m + n) l ⟩
        ((m + n) * l) + (m + n)
    ≡⟨ cong (λ x → x + (m + n)) (+*-rDist m n l) ⟩
        ((m * l) + (n * l)) + (m + n)
    ≡⟨ +-assoc ((m * l) + (n * l)) m n ⟩
        (((m * l) + (n * l)) + m) + n
    ≡⟨ cong (λ x → x + n) (sym (+-assoc (m * l) (n * l) m)) ⟩
        ((m * l) + ((n * l) + m)) + n
    ≡⟨ cong (λ x → x + n) (cong (λ x → (m * l) + x) (+-comm (n * l) m)) ⟩
        ((m * l) + (m + (n * l))) + n
    ≡⟨ cong (λ x → x + n) (+-assoc (m * l) m (n * l)) ⟩
        (((m * l) + m) + (n * l)) + n
    ≡⟨ sym (+-assoc ((m * l) + m) (n * l) n) ⟩
        ((m * l) + m) + ((n * l) + n)
    ≡⟨ cong (λ x → x + ((n * l) + n)) (sym (*-right m l)) ⟩
        (m * succ l) + ((n * l) + n)
    ≡⟨ cong (λ x → (m * succ l) + x) (sym (*-right n l)) ⟩
        (m * succ l) + (n * succ l)
    ∎

*-assoc : (m n l : ℕ) → m * (n * l) ≡ (m * n) * l
*-assoc zero n l = refl
*-assoc (succ m) n l = begin
        succ m * (n * l)
    ≡⟨ refl ⟩
        (n * l) + (m * (n * l))
    ≡⟨ cong (λ x → (n * l) + x) (*-assoc m n l) ⟩
        (n * l) + ((m * n) * l)
    ≡⟨ sym (+*-rDist n (m * n) l) ⟩
        (n + (m * n)) * l
    ≡⟨ refl ⟩
        (succ m * n) * l
    ∎

*-comm : (m n : ℕ) → m * n ≡ n * m
*-comm zero n = sym (*-rAbsorp n)
*-comm (succ m) n = begin
        succ m * n
    ≡⟨ refl ⟩
        n + (m * n)
    ≡⟨ +-comm n (m * n) ⟩
        (m * n) + n
    ≡⟨ cong (λ x → x + n) (*-comm m n) ⟩
        (n * m) + n
    ≡⟨ sym (*-right n m) ⟩
        n * succ m
    ∎

_≤_ : ℕ → ℕ → Set
n ≤ m = Σ ℕ (λ l → n + l ≡ m)

≤-refl : (n : ℕ) → n ≤ n
≤-refl zero = zero , refl
≤-refl (succ n) = zero ,
    (begin
        (succ n + zero)
    ≡⟨ +-rUnit (succ n) ⟩
        (succ n)
    ∎)

0≤n : (n : ℕ) → zero ≤ n
0≤n zero = ≤-refl zero
0≤n (succ n) = succ n , refl

≤-trans : (n m l : ℕ) → n ≤ m → m ≤ l → n ≤ l
≤-trans zero m l p q = l , refl
≤-trans (succ n) m l (a , succn+a≡m) (b , m+b≡l)
    = (a + b) , (begin
        succ n + (a + b)
    ≡⟨ +-assoc (succ n) a b ⟩
        (succ n + a) + b
    ≡⟨ cong (λ x → x + b) succn+a≡m ⟩
        m + b
    ≡⟨ m+b≡l ⟩
        l
    ∎)

+-lZero : (n m : ℕ) → n + m ≡ zero → n ≡ zero
+-lZero zero m = λ _ → refl
+-lZero (succ n) m ()

≤-antisym : (n m : ℕ) → n ≤ m → m ≤ n → n ≡ m
≤-antisym n m (c , n+c≡m) (d , m+d≡n) = trans (sym n+c≡n) n+c≡m
    where
        c≡0 : c ≡ zero
        c≡0 = +-lZero c d (+-lCancel (c + d) zero n (
            begin
                n + (c + d)
            ≡⟨ +-assoc n c d ⟩
                (n + c) + d
            ≡⟨ cong (λ x → x + d) n+c≡m ⟩
                m + d
            ≡⟨ m+d≡n ⟩
                n
            ≡⟨ sym (+-rUnit n) ⟩
                n + zero
            ∎))
        n+c≡n : n + c ≡ n
        n+c≡n = begin
                n + c
            ≡⟨ cong (λ x → n + x) c≡0 ⟩
                n + zero
            ≡⟨ +-rUnit n ⟩
                n
            ∎

n+s0≡sn : (n : ℕ) → n + succ zero ≡ succ n
n+s0≡sn n = begin
        n + succ zero
    ≡⟨ +-right n zero ⟩
        succ (n + zero)
    ≡⟨ cong succ (+-rUnit n) ⟩
        succ n
    ∎

n≤sn : (n : ℕ) → n ≤ succ n
n≤sn n = succ zero , n+s0≡sn n

ℕ-ω : (n : ℕ) → n ≡ zero ⊎ Σ ℕ (λ c → n ≡ succ c)
ℕ-ω zero = inj₁ refl
ℕ-ω (succ n) = inj₂ (n , refl)

m+sn≡sm+n : (m n : ℕ) → m + succ n ≡ succ m + n
m+sn≡sm+n m zero = begin
        m + succ zero
    ≡⟨ n+s0≡sn m ⟩
        succ m
    ≡⟨ sym (+-rUnit (succ m)) ⟩
        succ m + zero
    ∎
m+sn≡sm+n m (succ n) = begin
        m + succ (succ n)
    ≡⟨ +-right m (succ n) ⟩
        succ (m + succ n)
    ≡⟨ cong succ (m+sn≡sm+n m n) ⟩
        succ (succ m + n)
    ≡⟨ sym (+-right (succ m) n) ⟩
        succ m + succ n
    ∎

sn≤m : (n m : ℕ) → n ≤ m → ¬ (n ≡ m) → succ n ≤ m
sn≤m n m (c , n+c≡m) q = lem (ℕ-ω c)
    where
        n+c≡n : c ≡ zero → n + c ≡ n
        n+c≡n p = begin
                n + c
            ≡⟨ cong (λ x → n + x) p ⟩
                n + zero
            ≡⟨ +-rUnit n ⟩
                n
            ∎
        lem : c ≡ zero ⊎ Σ ℕ (λ d → c ≡ succ d) → succ n ≤ m
        lem (inj₁ x) = ⊥-elim (q (trans (sym (n+c≡n x)) n+c≡m))
        lem (inj₂ (d , c≡sd)) = d , (begin
                succ n + d
            ≡⟨ sym (m+sn≡sm+n n d) ⟩
                n + succ d
            ≡⟨ sym (cong (λ x → n + x) c≡sd) ⟩
                n + c
            ≡⟨ n+c≡m ⟩
                m
            ∎)

≤-all : (m n : ℕ) → m ≤ n ⊎ n ≤ m
≤-all m zero = inj₂ (m , refl)
≤-all m (succ n) = lem (≤-all m n)
    where
        lem : m ≤ n ⊎ n ≤ m → m ≤ succ n ⊎ succ n ≤ m
        lem (inj₁ x) = inj₁ (≤-trans m n (succ n) x (n≤sn n))
        lem (inj₂ (zero , n+zero≡m)) = inj₁ (succ zero , (begin
                m + succ zero
            ≡⟨ +-right m zero ⟩
                succ (m + zero)
            ≡⟨ cong succ (+-rUnit m) ⟩
                succ m
            ≡⟨ cong succ (sym n+zero≡m) ⟩
                succ (n + zero)
            ≡⟨ cong succ (+-rUnit n) ⟩
                succ n
            ∎))
        lem (inj₂ (succ c , n+sc≡m)) = inj₂ (c , (begin
                succ n + c
            ≡⟨ refl ⟩
                succ (n + c)
            ≡⟨ sym (+-right n c) ⟩
                n + succ c
            ≡⟨ n+sc≡m ⟩
                m
            ∎))

+-mono : (m n l : ℕ) → m ≤ n → (m + l) ≤ (n + l)
+-mono m n zero (c , m+c≡n) = c , (begin
        (m + zero) + c
    ≡⟨ cong (λ x → x + c) (+-rUnit m) ⟩
        m + c
    ≡⟨ m+c≡n ⟩
        n
    ≡⟨ sym (+-rUnit n) ⟩
        n + zero
    ∎)
+-mono m n (succ l) (c , m+c≡n) = lem (+-mono m n l (c , m+c≡n))
    where
        lem : (m + l) ≤ (n + l) → (m + succ l) ≤ (n + succ l)
        lem (d , m+l+d≡n+l) = d , (begin
                (m + succ l) + d
            ≡⟨ cong (λ x → x + d) (+-right m l) ⟩
                succ (m + l) + d
            ≡⟨ refl ⟩
                succ ((m + l) + d)
            ≡⟨ cong succ m+l+d≡n+l ⟩
                succ (n + l)
            ≡⟨ sym (+-right n l) ⟩
                n + succ l
            ∎)

*-mono : (m n l : ℕ) → m ≤ n → (m * l) ≤ (n * l)
*-mono m n zero (c , m+c≡n) = zero , (begin
        (m * zero) + zero
    ≡⟨ +-rUnit (m * zero) ⟩
        m * zero
    ≡⟨ trans (*-rAbsorp m) (sym (*-rAbsorp n)) ⟩
        n * zero
    ∎)
*-mono m n (succ l) (c , m+c≡n) = lem (*-mono m n l (c , m+c≡n))
    where
        lem : (m * l) ≤ (n * l) → (m * succ l) ≤ (n * succ l)
        lem (d , m*l+d≡n*l) = (c * succ l) , sym (begin
                n * succ l
            ≡⟨ cong (λ x → x * succ l) (sym m+c≡n) ⟩
                (m + c) * succ l
            ≡⟨ +*-rDist m c (succ l) ⟩
                (m * succ l) + (c * succ l)
            ∎)

s≤s : (m n : ℕ) → m ≤ n → succ m ≤ succ n
s≤s zero n (c , c≡n) = n , refl
s≤s (succ m) n (c , sm+c≡n) = c , cong succ sm+c≡n

data _≲_ : ℕ → ℕ → Set where
    0≲n : {n : ℕ} → zero ≲ n
    s≲s : {n m : ℕ} → n ≲ m → succ n ≲ succ m

≤-≲ : (m n : ℕ) → m ≤ n → m ≲ n
≤-≲ zero _ _ = 0≲n
≤-≲ (succ m) zero (c , ())
≤-≲ (succ m) (succ n) (c , m+c≡n) = s≲s (≤-≲ m n (c , ≡-succ (m + c) n m+c≡n))

≲-≤ : (m n : ℕ) → m ≲ n → m ≤ n
≲-≤ .zero n 0≲n = n , refl
≲-≤ (succ m) (succ n) (s≲s p) = s≤s m n (≲-≤ m n p)


module Type.Properties.Inhabited{ℓ} where

import      Lvl
open import Type

-- An inhabited type, which essentially means non-empty (there exists objects with this type), and this object is pointed out/specified/chosen.
-- This means that there exists objects with such an type, and such an object is extractable constructively (like a witness).
-- Also called: Pointed type.
record ◊ (T : Type{ℓ}) : Type{ℓ} where
  constructor intro
  field
    ⦃ existence ⦄ : T
open ◊ ⦃ ... ⦄ renaming (existence to [◊]-existence) public


module IsLiteralFormula where

open import OscarPrelude
open import PredicateName
open import Term
open import Formula
open import HasNegation

data IsLiteralFormula : Formula → Set
 where
  atomic : (𝑃 : PredicateName) → (τs : Terms) → IsLiteralFormula $ 𝑃[ 𝑃 ♭ τs ]
  logical : (𝑃 : PredicateName) → (τs : Terms) → IsLiteralFormula ∘ ~ $ 𝑃[ 𝑃 ♭ τs ]

eqIsLiteralFormula : ∀ {φ} → (lf₁ lf₂ : IsLiteralFormula φ) → lf₁ ≡ lf₂
eqIsLiteralFormula (atomic _ _) (atomic _ _) = refl
eqIsLiteralFormula (logical _ _) (logical _ _) = refl

instance EqIsLiteralFormula : ∀ {φ} → Eq (IsLiteralFormula φ)
Eq._==_ EqIsLiteralFormula lf₁ lf₂ = yes $ eqIsLiteralFormula lf₁ lf₂


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

open import Categories.Category

module Categories.Category.Construction.Pullbacks {o ℓ e} (C : Category o ℓ e) where

open import Level using (_⊔_)
open import Function using (_$_)
open import Data.Product using (_×_; _,_)

open import Categories.Diagram.Pullback C
open import Categories.Morphism.Reasoning C

open Category C

record PullbackObj W : Set (o ⊔ ℓ ⊔ e) where
  field
    {A} {B}  : Obj
    arr₁     : A ⇒ W
    arr₂     : B ⇒ W
    pullback : Pullback arr₁ arr₂

  module pullback = Pullback pullback

open HomReasoning

record Pullback⇒ W (X Y : PullbackObj W) : Set (o ⊔ ℓ ⊔ e) where
  module X = PullbackObj X
  module Y = PullbackObj Y
  field
    mor₁     : X.A ⇒ Y.A
    mor₂     : X.B ⇒ Y.B
    commute₁ : Y.arr₁ ∘ mor₁ ≈ X.arr₁
    commute₂ : Y.arr₂ ∘ mor₂ ≈ X.arr₂

  pbarr : X.pullback.P ⇒ Y.pullback.P
  pbarr = Y.pullback.universal $ begin
    Y.arr₁ ∘ mor₁ ∘ X.pullback.p₁ ≈⟨ pullˡ commute₁ ⟩
    X.arr₁ ∘ X.pullback.p₁        ≈⟨ X.pullback.commute ⟩
    X.arr₂ ∘ X.pullback.p₂        ≈˘⟨ pullˡ commute₂ ⟩
    Y.arr₂ ∘ mor₂ ∘ X.pullback.p₂ ∎

open Pullback⇒

Pullbacks : Obj → Category (o ⊔ ℓ ⊔ e) (o ⊔ ℓ ⊔ e) e
Pullbacks W = record
  { Obj       = PullbackObj W
  ; _⇒_       = Pullback⇒ W
  ; _≈_       = λ f g → mor₁ f ≈ mor₁ g × mor₂ f ≈ mor₂ g
  ; id        = record
    { mor₁     = id
    ; mor₂     = id
    ; commute₁ = identityʳ
    ; commute₂ = identityʳ
    }
  ; _∘_       = λ f g → record
    { mor₁     = mor₁ f ∘ mor₁ g
    ; mor₂     = mor₂ f ∘ mor₂ g
    ; commute₁ = pullˡ (commute₁ f) ○ commute₁ g
    ; commute₂ = pullˡ (commute₂ f) ○ commute₂ g
    }
  ; assoc     = assoc , assoc
  ; sym-assoc = sym-assoc , sym-assoc
  ; identityˡ = identityˡ , identityˡ
  ; identityʳ = identityʳ , identityʳ
  ; identity² = identity² , identity²
  ; equiv     = record
    { refl  = refl , refl
    ; sym   = λ { (eq₁ , eq₂) → sym eq₁ , sym eq₂ }
    ; trans = λ { (eq₁ , eq₂) (eq₃ , eq₄) → trans eq₁ eq₃ , trans eq₂ eq₄ }
    }
  ; ∘-resp-≈  = λ { (eq₁ , eq₂) (eq₃ , eq₄) → ∘-resp-≈ eq₁ eq₃ , ∘-resp-≈ eq₂ eq₄ }
  }


{-# OPTIONS --cubical --no-import-sorts --safe #-}
module Cubical.Data.Vec.Properties where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence

import Cubical.Data.Empty as ⊥
open import Cubical.Data.Nat
open import Cubical.Data.Vec.Base
open import Cubical.Data.FinData
open import Cubical.Relation.Nullary

private
  variable
    ℓ : Level
    A : Type ℓ

-- This is really cool!
-- Compare with: https://github.com/agda/agda-stdlib/blob/master/src/Data/Vec/Properties/WithK.agda#L32
++-assoc : ∀ {m n k} (xs : Vec A m) (ys : Vec A n) (zs : Vec A k) →
           PathP (λ i → Vec A (+-assoc m n k (~ i))) ((xs ++ ys) ++ zs) (xs ++ ys ++ zs)
++-assoc {m = zero} [] ys zs = refl
++-assoc {m = suc m} (x ∷ xs) ys zs i = x ∷ ++-assoc xs ys zs i

-- Equivalence between Fin n → A and Vec A n

FinVec : (A : Type ℓ) (n : ℕ) → Type ℓ
FinVec A n = Fin n → A

FinVec→Vec : {n : ℕ} → FinVec A n → Vec A n
FinVec→Vec {n = zero}  xs = []
FinVec→Vec {n = suc _} xs = xs zero ∷ FinVec→Vec (λ x → xs (suc x))

Vec→FinVec : {n : ℕ} → Vec A n → FinVec A n
Vec→FinVec xs f = lookup f xs

FinVec→Vec→FinVec : {n : ℕ} (xs : FinVec A n) → Vec→FinVec (FinVec→Vec xs) ≡ xs
FinVec→Vec→FinVec {n = zero} xs = funExt λ f → ⊥.rec (¬Fin0 f)
FinVec→Vec→FinVec {n = suc n} xs = funExt goal
  where
  goal : (f : Fin (suc n))
       → Vec→FinVec (xs zero ∷ FinVec→Vec (λ x → xs (suc x))) f ≡ xs f
  goal zero = refl
  goal (suc f) i = FinVec→Vec→FinVec (λ x → xs (suc x)) i f

Vec→FinVec→Vec : {n : ℕ} (xs : Vec A n) → FinVec→Vec (Vec→FinVec xs) ≡ xs
Vec→FinVec→Vec {n = zero}  [] = refl
Vec→FinVec→Vec {n = suc n} (x ∷ xs) i = x ∷ Vec→FinVec→Vec xs i

FinVecIsoVec : (n : ℕ) → Iso (FinVec A n) (Vec A n)
FinVecIsoVec n = iso FinVec→Vec Vec→FinVec Vec→FinVec→Vec FinVec→Vec→FinVec

FinVec≃Vec : (n : ℕ) → FinVec A n ≃ Vec A n
FinVec≃Vec n = isoToEquiv (FinVecIsoVec n)

FinVec≡Vec : (n : ℕ) → FinVec A n ≡ Vec A n
FinVec≡Vec n = ua (FinVec≃Vec n)

isContrVec0 : isContr (Vec A 0)
isContrVec0 = [] , λ { [] → refl }


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

module Categories.Functor.Cocontinuous where

open import Level
open import Data.Product using (Σ)

open import Categories.Category
open import Categories.Functor
import Categories.Category.Construction.Cocones as Coc
import Categories.Diagram.Cocone.Properties as Cocₚ
import Categories.Diagram.Colimit as Col
import Categories.Morphism as Mor

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

-- G preserves the colimit of F.
CoimitPreserving : (G : Functor C D) {F : Functor J C} (L : Col.Colimit F) → Set _
CoimitPreserving {C = C} {D = D} G {F} L = Σ (Col.Colimit (G ∘F F)) λ L′ → G.F₀ (Col.Colimit.coapex L) ≅ Col.Colimit.coapex L′
  where module F = Functor F
        module G = Functor G
        open Mor D

-- cocontinuous functors preserves all colimits.
Cocontinuous : ∀ (o ℓ e : Level) (G : Functor C D) → Set _
Cocontinuous {C = C} o ℓ e G = ∀ {J : Category o ℓ e} {F : Functor J C} (L : Col.Colimit F) → CoimitPreserving G L


{-# OPTIONS --without-K --safe #-}
module Categories.Functor.Construction.Zero where

-- The Zero functor maps everything to the initial object of a
-- category (when it exists). Note quite const.

open import Level

open import Categories.Category
open import Categories.Functor using (Functor)
open import Categories.Object.Initial

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

Zero : Initial D → Functor C D
Zero {D = D} init = record
  { F₀ = λ _ → ⊥
  ; F₁ = λ _ → id
  ; identity = Equiv.refl
  ; homomorphism = Equiv.sym identity²
  ; F-resp-≈ = λ _ → Equiv.refl
  }
  where
  open Initial init
  open Category D


module Structure.Relator.Ordering.Proofs where

import      Lvl
open import Functional
open import Lang.Instance
open import Logic
open import Structure.Relator.Ordering
open import Structure.Relator.Properties
open import Syntax.Transitivity
open import Type

private variable ℓ : Lvl.Level
private variable A B : Type{ℓ}
private variable _≤_ _≤₁_ _≤₂_ : A → A → Stmt{ℓ}
private variable f : A → B
private variable x : A

module _ ⦃ trans : Transitivity{T = B}(_≤_) ⦄ where
  open Strict.Properties

  -- TODO: Agda bug 20200523 does not allow instance arg
  accessibleₗ-image-by-trans : Accessibleₗ{T = B}(_≤_)(f(x)) → Accessibleₗ((_≤_) on₂ f)(x)
  accessibleₗ-image-by-trans {f = f} {y} (intro ⦃ acc ⦄) = intro ⦃ \{x} ⦃ xy ⦄ → intro ⦃ \{a} ⦃ ax ⦄ → accessibleₗ-image-by-trans (acc {f(a)} ⦃ transitivity(_≤_) ax xy ⦄ ) ⦄ ⦄

  wellfounded-image-by-trans : ∀{f : A → B} → ⦃ _ : WellFounded{T = B}(_≤_) ⦄ → WellFounded((_≤_) on₂ f)
  wellfounded-image-by-trans = accessibleₗ-image-by-trans infer

module _ ⦃ refl : Reflexivity{T = B}(_≤_) ⦄ where
  open Strict.Properties

  accessibleₗ-image-by-refl : ⦃ _ : Accessibleₗ{T = B}(_≤_)(f(x)) ⦄ → Accessibleₗ((_≤_) on₂ f)(x)
  accessibleₗ-image-by-refl {f = f} {y} ⦃ intro ⦃ acc ⦄ ⦄ = accessibleₗ-image-by-refl ⦃ acc{f(y)} ⦃ reflexivity(_≤_) ⦄ ⦄

  wellfounded-image-by-refl : ∀{f : A → B} → ⦃ _ : WellFounded{T = B}(_≤_) ⦄ → WellFounded((_≤_) on₂ f)
  wellfounded-image-by-refl = accessibleₗ-image-by-refl

module _ ⦃ sub : (_≤₁_) ⊆₂ (_≤₂_) ⦄ where
  open Strict.Properties

  accessibleₗ-sub₂ : ⦃ _ : Accessibleₗ(_≤₂_)(x) ⦄ → Accessibleₗ(_≤₁_)(x)
  accessibleₗ-sub₂ {x = y} ⦃ intro ⦃ acc ⦄ ⦄ = intro ⦃ \{x} ⦃ xy ⦄ → accessibleₗ-sub₂ ⦃ acc{x} ⦃ sub₂(_≤₁_)(_≤₂_) xy ⦄ ⦄ ⦄

  wellfounded-sub₂ : ⦃ _ : WellFounded(_≤₂_) ⦄ → WellFounded(_≤₁_)
  wellfounded-sub₂ = accessibleₗ-sub₂


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

open import Agda.Primitive using (Level; lzero; lsuc; _⊔_)
open import LogicalFormulae
open import Numbers.Integers.Integers
open import Numbers.Naturals.Semiring
open import Numbers.Naturals.Subtraction
open import Numbers.Naturals.Naturals
open import Numbers.Naturals.Order
open import Numbers.Naturals.Exponentiation
open import Numbers.Primes.PrimeNumbers
open import Maybe
open import Semirings.Definition
import Semirings.Solver

open module NatSolver = Semirings.Solver ℕSemiring multiplicationNIsCommutative

module LectureNotes.NumbersAndSets.Lecture1 where

a-Na : (a : ℕ) → a -N' a ≡ yes 0
a-Na zero = refl
a-Na (succ a) = a-Na a

-N''lemma : (a b : ℕ) → (a<b : a ≤N b) → b -N' a ≡ yes (subtractionNResult.result (-N a<b))
-N''lemma zero (succ b) (inl x) = refl
-N''lemma (succ a) (succ b) (inl x) = -N''lemma a b (inl (canRemoveSuccFrom<N x))
-N''lemma a b (inr x) rewrite x | a-Na b = ans
  where
    ans : yes 0 ≡ yes (subtractionNResult.result (-N (inr (refl {x = b}))))
    ans with -N (inr (refl {x = b}))
    ans | record { result = result ; pr = pr } with result
    ans | record { result = result ; pr = pr } | zero = refl
    ans | record { result = result ; pr = pr } | succ bl = exFalso (cannotAddAndEnlarge'' pr)

-N'' : (a b : ℕ) (a<b : a ≤N b) → ℕ
-N'' a b a<b with -N''lemma a b a<b
... | bl with b -N' a
-N'' a b a<b | bl | yes x = x

n3Bigger : (n : ℕ) → (n ≡ 0) || (n ≤N n ^N 3)
n3Bigger n = exponentiationIncreases n 2

n3Bigger' : (n : ℕ) → n ≤N n ^N 3
n3Bigger' zero = inr refl
n3Bigger' (succ n) with n3Bigger (succ n)
n3Bigger' (succ n) | inr f = f

-- How to use the semiring solver
-- The process is very mechanical; I haven't yet worked out how to do reflection,
-- so there's quite a bit of transcribing expressions into the Expr form.
-- The first two arguments to from-to-by are totally mindless in construction.
proof : (n : ℕ) → ((n *N n) +N ((2 *N n) +N 1)) ≡ (n +N 1) *N (n +N 1)
proof n =
  from plus (times (const n) (const n)) (plus (times (succ (succ zero)) (const n)) (succ zero))
  to times (plus (const n) (succ zero)) (plus (const n) (succ zero))
  by
    applyEquality (λ i → succ (n *N n) +N (n +N i)) ((from (const n) to (plus (const n) zero) by refl))


open import prelude renaming (_≟String_ to _≟_)

infixl 5 _$_

-- Copied pretty much verbatim

Var = String

data Term : Set where
  var : Var → Term
  fun : Var → Term → Term
  _$_ : Term → Term → Term

data Value : Term → Set where
  fun : (x : Var) → (t : Term) → Value(fun x t)

-- Free variables of a term.
-- (Turns out to be easiest to define when a variable isn't free rather than when it is.)

data _∉FV_ : Var → Term → Set where

  var : ∀ {x y} →

    x ≢ y →
    -------------
    x ∉FV(var y)

  fun₁ : ∀ {x y t} →

    (x ≡ y) →
    ---------------
    x ∉FV(fun y t)

  fun₂ : ∀ {x y t} →

    (x ∉FV(t)) →
    ---------------
    x ∉FV(fun y t)

  app : ∀ {x t₁ t₂} →

    (x ∉FV(t₁)) →
    (x ∉FV(t₂)) →
    -----------------
    (x ∉FV(t₁ $ t₂))

-- Substitution
-- TAPL defines substitution as a partial function, which Agda doesn't implement.
-- So instead we keep track of the derivation tree.

data [_↦_]_is_ : Var → Term → Term → Term → Set where

  yes : ∀ {x y s} →

    (x ≡ y) →
    ----------------------
    [ x ↦ s ] (var y) is s

  no : ∀ {x y s} →

    (x ≢ y) →
    ----------------------------
    [ x ↦ s ] (var y) is (var y)

  fun₁ : ∀ {x y s t} →

    (x ≡ y) →
    --------------------------------
    [ x ↦ s ] (fun y t) is (fun y t)

  fun₂ : ∀ {x y s t t′} →

    (x ≢ y) →
    (y ∉FV(s)) →
    [ x ↦ s ] t is t′ →
    ---------------------------------
    [ x ↦ s ] (fun y t) is (fun y t′)

  app : ∀ {x s t₁ t₁′ t₂ t₂′} →

    [ x ↦ s ] t₁ is t₁′ →
    [ x ↦ s ] t₂ is t₂′ →
    ---------------------------------
    [ x ↦ s ] (t₁ $ t₂) is (t₁′ $ t₂′)

-- Reduction is as per TAPL

data _⟶_ : Term → Term → Set where

  E─App1 : ∀ {t₁ t₁′ t₂} →

     (t₁ ⟶ t₁′) →
     ------------------------
     (t₁ $ t₂) ⟶ (t₁′ $ t₂)

  E─App2 : ∀ {t₁ t₂ t₂′} →

     (t₂ ⟶ t₂′) →
     ------------------------
     (t₁ $ t₂) ⟶ (t₁ $ t₂′)

  E─AppAbs : ∀ {x t₁ t₂ t₃} →

     [ x ↦ t₂ ] t₁ is t₃ →
     ----------------------
     (fun x t₁ $ t₂) ⟶ t₃

-- A redex is a term which can reduce

data Redex  : Term → Set where

  redex : ∀ {t t′} →

    t ⟶ t′ →
    --------
    Redex(t)

-- A closed term is one with no free variables

Closed : Term → Set
Closed(t) = ∀ {x} → x ∉FV(t)

-- Proving that substitution is well-defined for closed terms

data [_↦_]_⇓ : Var → Term → Term → Set where

  subst : ∀ {x s t t′} →
    ([ x ↦ s ] t is t′) →
    ([ x ↦ s ] t ⇓)

substDef : (x : Var) → (s t : Term) → Closed(s) → ([ x ↦ s ] t ⇓)
substDef x s (var y) c = helper (x ≟ y) where

  helper : Dec(x ≡ y) → ([ x ↦ s ] (var y) ⇓)
  helper (yes p) = subst (yes p)
  helper (no  p) = subst (no p)

substDef x s (fun y t) c = helper₁ (x ≟ y) where

  helper₂ : (x ≢ y) → ([ x ↦ s ] t ⇓) → ([ x ↦ s ] (fun y t) ⇓)
  helper₂ p (subst s) = subst (fun₂ p c s)

  helper₁ : Dec(x ≡ y) → ([ x ↦ s ] (fun y t) ⇓)
  helper₁ (yes p) = subst (fun₁ p)
  helper₁ (no  p) = helper₂ p (substDef x s t c)

substDef x s (t₁ $ t₂) c = helper (substDef x s t₁ c) (substDef x s t₂ c) where

  helper : ([ x ↦ s ] t₁ ⇓) → ([ x ↦ s ] t₂ ⇓) → ([ x ↦ s ] (t₁ $ t₂) ⇓)
  helper (subst s₁) (subst s₂) = subst (app s₁ s₂)

-- Proving that closed terms stay closed

closed₁ : ∀ {t₁ t₂ x} → (x ∉FV(t₁ $ t₂)) → (x ∉FV(t₁))
closed₁ (app p₁ p₂) = p₁

closed₂ :  ∀ {t₁ t₂ x} → (x ∉FV(t₁ $ t₂)) → (x ∉FV(t₂))
closed₂ (app p₁ p₂) = p₂

substClosed₁ : ∀ {y s t t′} → (y ∉FV(s)) → ([ y ↦ s ] t is t′) → (y ∉FV(t′))
substClosed₁ p (yes refl) = p
substClosed₁ p (no q) = var q
substClosed₁ p (fun₁ q) = fun₁ q
substClosed₁ p (fun₂ x x₁ q) = fun₂ (substClosed₁ p q)
substClosed₁ p (app q₁ q₂) = app (substClosed₁ p q₁) (substClosed₁ p q₂)

substClosed₂ : ∀ {x y s t t′} → (x ∉FV(t)) → (x ∉FV(s)) → ([ y ↦ s ] t is t′) → (x ∉FV(t′))
substClosed₂ p q (yes refl) = q
substClosed₂ p q (no r) = p
substClosed₂ p q (fun₁ refl) = p
substClosed₂ (fun₁ p) q (fun₂ x x₁ r) = fun₁ p
substClosed₂ (fun₂ p) q (fun₂ x x₁ r) = fun₂ (substClosed₂ p q r)
substClosed₂ (app p₁ p₂) q (app r₁ r₂) = app (substClosed₂ p₁ q r₁) (substClosed₂ p₂ q r₂)

substClosed₃ : ∀ {x y s t t′} → x ∉FV(fun y t) → x ∉FV(s) → ([ y ↦ s ] t is t′) → x ∉FV(t′)
substClosed₃ (fun₁ refl) q r = substClosed₁ q r
substClosed₃ (fun₂ p)    q r = substClosed₂ p q r

redexClosed : ∀ {t t′} → Closed(t) → (t ⟶ t′) → Closed(t′)
redexClosed c (E─App1 r)   = app (redexClosed (closed₁ c) r) (closed₂ c)
redexClosed c (E─App2 r)   = app (closed₁ c) (redexClosed (closed₂ c) r)
redexClosed c (E─AppAbs s) = substClosed₃ (closed₁ c) (closed₂ c) s

-- Proving that every closed term is a value or a redex

data ValueOrRedex : Term → Set where

  value : ∀ {t} →

    (Value(t)) →
    ---------------
    ValueOrRedex(t)

  redex : ∀ {t t′} →

    t ⟶ t′ →
    ---------------
    ValueOrRedex(t)

valueOrRedex : (t : Term) → Closed(t) → ValueOrRedex(t)
valueOrRedex (var x) c = CONTRADICTION (helper c) where

  helper : (x ∉FV(var x)) → FALSE
  helper (var p) = p refl

valueOrRedex (fun x t) c = value (fun x t)
valueOrRedex (t₁ $ t₂) c = helper₁ (valueOrRedex t₁ (closed₁ c)) where

  helper₃ : ∀ {x s t} → ([ x ↦ s ] t ⇓) → ValueOrRedex((fun x t) $ s)
  helper₃ (subst s) = redex (E─AppAbs s)

  helper₂ : ∀ {t₁} → Value(t₁) → ValueOrRedex(t₂) → ValueOrRedex(t₁ $ t₂)
  helper₂ (fun x t) (value v) = helper₃ (substDef x t₂ t (closed₂ c))
  helper₂ (fun x t) (redex r) = redex (E─App2 r)

  helper₁ : ValueOrRedex(t₁) → ValueOrRedex(t₁ $ t₂)
  helper₁ (value v₁) = helper₂ v₁ (valueOrRedex t₂ (closed₂ c))
  helper₁ (redex r) = redex (E─App1 r)

-- Interpreter!

data _⟶*_ : Term → Term → Set where

  done : ∀ {t} →

    --------
    t ⟶* t

  redex : ∀ {t t′ t″} →

    t ⟶ t′ →
    t′ ⟶* t″ →
    ----------
    t ⟶* t″

-- An interpreter result

data Result  : Term → Set where

  result : ∀ {t t′} →

    t ⟶* t′ →
    Value(t′) →
    ---------
    Result(t)

-- The interpreter just calls `valueOrRedex` until it is a value.
-- This might bot terminate!

{-# NON_TERMINATING #-}
interp : (t : Term) → Closed(t) → Result(t)
interp t c = helper₂ (valueOrRedex t c) where

  helper₁ : ∀ {t′} → (t ⟶ t′) → Result(t′) → Result(t)
  helper₁ r (result s v) = result (redex r s) v

  helper₂ : ValueOrRedex(t) → Result(t)
  helper₂ (value v)           = result done v
  helper₂ (redex {t′ = t′} r) = helper₁ r (interp t′ (redexClosed c r))

-- Examples

zer : Term
zer = fun "z" (fun "s" (var "z"))

succ : Term
succ = fun "x" (fun "z" (fun "s" (var "s" $ var "x")))

add : Term
add = fun "x" (fun "y" (var "x" $ var "y" $ succ))

two : Term
two = succ $ (succ $ zer)

four : Term
four = add $ two $ two

zerC : Closed(zer)
zerC {x} with (x ≟ "z")
... | yes refl = fun₁ refl
... | no  p    = fun₂ (fun₂ (var p))

succC : Closed(succ)
succC {x} with (x ≟ "x") | (x ≟ "s")
... | yes refl | _        = fun₁ refl
... | no  p    | yes refl = fun₂ (fun₂ (fun₁ refl))
... | no  p    | no q     = fun₂ (fun₂ (fun₂ (app (var q) (var p))))

addC : Closed(add)
addC {x} with (x ≟ "x") | (x ≟ "y")
... | yes refl | _        = fun₁ refl
... | no  p    | yes refl = fun₂ (fun₁ refl)
... | no  p    | no q     = fun₂ (fun₂ (app (app (var p) (var q)) succC))

twoC : Closed(two)
twoC = app succC (app succC zerC)

fourC : Closed(four)
fourC = app (app addC twoC) twoC


{-# OPTIONS --cubical --no-import-sorts --safe #-}
module Cubical.Algebra.Magma.Submagma where

open import Cubical.Core.Everything
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels

open import Cubical.Algebra
open import Cubical.Algebra.Magma.Morphism

open import Cubical.Relation.Unary
open import Cubical.Relation.Unary.Subtype

record IsSubmagma {c ℓ} (M : Magma c) (Member : Pred ⟨ M ⟩ ℓ) : Type (ℓ-max c ℓ) where
  constructor issubmagma

  private module M = Magma M

  field
    closed : M._•_ Preserves₂ Member

  Carrier : Type _
  Carrier = Subtype Member

  _•_ : Op₂ Carrier
  (x , subx) • (y , suby) = x M.• y , closed subx suby

  is-set : isSet Carrier
  is-set = isSetSubtype Member M.is-set

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

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

  open Magma magma using (set) public

record Submagma {c} (M : Magma c) ℓ : Type (ℓ-max c (ℓ-suc ℓ)) where
  constructor mksubmagma

  field
    Member : Pred ⟨ M ⟩ ℓ
    isSubmagma : IsSubmagma M Member

  open IsSubmagma isSubmagma public

instance
  SubmagmaCarrier : ∀ {c ℓ} {M : Magma c} → HasCarrier (Submagma M ℓ) _
  SubmagmaCarrier = record { ⟨_⟩ = Submagma.Carrier }

module _ {ℓ} (M : Magma ℓ) where
  open Magma M

  ∅-isSubmagma : IsSubmagma M ∅
  ∅-isSubmagma = record { closed = λ () }

  ∅-submagma : Submagma M _
  ∅-submagma = record { isSubmagma = ∅-isSubmagma }

  U-isSubmagma : IsSubmagma M U
  U-isSubmagma = record {} -- trivial

  U-submagma : Submagma M _
  U-submagma = record { isSubmagma = U-isSubmagma }

isPropIsSubmagma : ∀ {c ℓ} {M : Magma c} {Member : Pred ⟨ M ⟩ ℓ} → isProp (IsSubmagma M Member)
isPropIsSubmagma {Member = Member} (issubmagma a) (issubmagma b) =
  cong issubmagma ((isPropImplicitΠ λ _ → isPropImplicitΠ λ _ → isPropΠ2 λ _ _ → isProp[ Member ] _) a b)


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

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

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

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

open HomReasoning

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

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

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

open Initial

to-⊥-is-Epi : ∀ {A : Obj} {i : Initial} → (f : A ⇒ ⊥ i) → Epi f
to-⊥-is-Epi {_} {i} _ = λ g h _ → !-unique₂ i g h

up-to-iso : (i₁ i₂ : Initial) → ⊥ i₁ ≅ ⊥ i₂
up-to-iso i₁ i₂ = record
  { from = ! i₁
  ; to   = ! i₂
  ; iso  = record { isoˡ = ⊥-id i₁ _; isoʳ = ⊥-id i₂ _ }
  }

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

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

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


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

module Cubical.Data.Fin.Base where

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

open import Cubical.Data.Empty
open import Cubical.Data.Nat
open import Cubical.Data.Nat.Order
open import Cubical.Data.Sum

open import Cubical.Relation.Nullary

-- Finite types.
--
-- Currently it is most convenient to define these as a subtype of the
-- natural numbers, because indexed inductive definitions don't behave
-- well with cubical Agda. This definition also has some more general
-- attractive properties, of course, such as easy conversion back to
-- ℕ.
Fin : ℕ → Type₀
Fin n = Σ[ k ∈ ℕ ] k < n

private
  variable
    ℓ : Level
    k : ℕ

fzero : Fin (suc k)
fzero = (0 , suc-≤-suc zero-≤)

-- It is easy, using this representation, to take the successor of a
-- number as a number in the next largest finite type.
fsuc : Fin k → Fin (suc k)
fsuc (k , l) = (suc k , suc-≤-suc l)

-- Conversion back to ℕ is trivial...
toℕ : Fin k → ℕ
toℕ = fst

-- ... and injective.
toℕ-injective : ∀{fj fk : Fin k} → toℕ fj ≡ toℕ fk → fj ≡ fk
toℕ-injective {fj = fj} {fk} = ΣProp≡ (λ _ → m≤n-isProp)

-- A case analysis helper for induction.
fsplit
  : ∀(fj : Fin (suc k))
  → (fzero ≡ fj) ⊎ (Σ[ fk ∈ Fin k ] fsuc fk ≡ fj)
fsplit (0 , k<sn) = inl (toℕ-injective refl)
fsplit (suc k , k<sn) = inr ((k , pred-≤-pred k<sn) , toℕ-injective refl)

-- Fin 0 is empty
¬Fin0 : ¬ Fin 0
¬Fin0 (k , k<0) = ¬-<-zero k<0

-- The full inductive family eliminator for finite types.
finduction
  : ∀(P : ∀{k} → Fin k → Type ℓ)
  → (∀{k} → P {suc k} fzero)
  → (∀{k} {fn : Fin k} → P fn → P (fsuc fn))
  → {k : ℕ} → (fn : Fin k) → P fn
finduction P fz fs {zero} = ⊥-elim ∘ ¬Fin0
finduction P fz fs {suc k} fj
  = case fsplit fj return (λ _ → P fj) of λ
  { (inl p) → subst P p fz
  ; (inr (fk , p)) → subst P p (fs (finduction P fz fs fk))
  }


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

open import Cubical.Core.Everything
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Data.Empty
open import Cubical.Data.Nat

open import Cubical.Data.Sum.Base

-- Path space of sum type
module SumPath {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} where

  Cover : A ⊎ B → A ⊎ B → Type (ℓ-max ℓ ℓ')
  Cover (inl a) (inl a') = Lift {j = ℓ-max ℓ ℓ'} (a ≡ a')
  Cover (inl _) (inr _) = Lift ⊥
  Cover (inr _) (inl _) = Lift ⊥
  Cover (inr b) (inr b') = Lift {j = ℓ-max ℓ ℓ'} (b ≡ b')

  reflCode : (c : A ⊎ B) → Cover c c
  reflCode (inl a) = lift refl
  reflCode (inr b) = lift refl

  encode : ∀ c c' → c ≡ c' → Cover c c'
  encode c _ = J (λ c' _ → Cover c c') (reflCode c)

  encodeRefl : ∀ c → encode c c refl ≡ reflCode c
  encodeRefl c = JRefl (λ c' _ → Cover c c') (reflCode c)

  decode : ∀ c c' → Cover c c' → c ≡ c'
  decode (inl a) (inl a') (lift p) = cong inl p
  decode (inl a) (inr b') ()
  decode (inr b) (inl a') ()
  decode (inr b) (inr b') (lift q) = cong inr q

  decodeRefl : ∀ c → decode c c (reflCode c) ≡ refl
  decodeRefl (inl a) = refl
  decodeRefl (inr b) = refl

  decodeEncode : ∀ c c' → (p : c ≡ c') → decode c c' (encode c c' p) ≡ p
  decodeEncode c _ =
    J (λ c' p → decode c c' (encode c c' p) ≡ p)
      (cong (decode c c) (encodeRefl c) ∙ decodeRefl c)

  isOfHLevelCover : (n : ℕ)
    → isOfHLevel (suc (suc n)) A
    → isOfHLevel (suc (suc n)) B
    → ∀ c c' → isOfHLevel (suc n) (Cover c c')
  isOfHLevelCover n p q (inl a) (inl a') = isOfHLevelLift (suc n) (p a a')
  isOfHLevelCover n p q (inl a) (inr b') =
    isOfHLevelLift (suc n)
    (subst (λ m → isOfHLevel m ⊥) (+-comm n 1)
      (hLevelLift n isProp⊥))
  isOfHLevelCover n p q (inr b) (inl a') =
    isOfHLevelLift (suc n)
      (subst (λ m → isOfHLevel m ⊥) (+-comm n 1)
        (hLevelLift n isProp⊥))
  isOfHLevelCover n p q (inr b) (inr b') = isOfHLevelLift (suc n) (q b b')

isOfHLevelSum : ∀ {ℓ ℓ'} (n : ℕ) {A : Type ℓ} {B : Type ℓ'}
  → isOfHLevel (suc (suc n)) A
  → isOfHLevel (suc (suc n)) B
  → isOfHLevel (suc (suc n)) (A ⊎ B)
isOfHLevelSum n lA lB c c' =
  retractIsOfHLevel (suc n)
    (SumPath.encode c c')
    (SumPath.decode c c')
    (SumPath.decodeEncode c c')
    (SumPath.isOfHLevelCover n lA lB c c')


{-# OPTIONS --without-K --rewriting #-}

open import HoTT
import homotopy.ConstantToSetExtendsToProp as ConstExt

module homotopy.RelativelyConstantToSetExtendsViaSurjection
  {i j k} {A : Type i} {B : Type j} {C : B → Type k}
  (C-is-set : ∀ b → is-set (C b))
  (f : A → B) (f-is-surj : is-surj f)
  (g : (a : A) → C (f a))
  (g-is-const : ∀ a₁ a₂ → (p : f a₁ == f a₂) → g a₁ == g a₂ [ C ↓ p ])
  where

{-
  (b : A) ----> [ hfiber f b ] ----?----> C ?
                      ^
                      |
                  hfiber f b
-}

  private
    lemma : ∀ b → hfiber f b → C b
    lemma b (a , fa=b) = transport C fa=b (g a)

    lemma-const : ∀ b → (h₁ h₂ : hfiber f b) → lemma b h₁ == lemma b h₂
    lemma-const ._ (a₁ , fa₁=fa₂) (a₂ , idp) =
      to-transp (g-is-const a₁ a₂ fa₁=fa₂)

    module CE (b : B) =
      ConstExt {A = hfiber f b} {B = C b}
        (C-is-set b) (lemma b) (lemma-const b)

  ext : Π B C
  ext b = CE.ext b (f-is-surj b)

  β : (a : A) → ext (f a) == g a
  β a = ap (CE.ext (f a))
    (prop-has-all-paths Trunc-level (f-is-surj (f a)) [ a , idp ])


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

open import LogicalFormulae
open import Setoids.Setoids
open import Rings.Definition
open import Rings.Ideals.Definition

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

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

record PrimeIdeal : Set (a ⊔ c) where
  field
    isPrime : {a b : A} → pred (a * b) → ((pred a) → False) → pred b
    notContained : A
    notContainedIsNotContained : (pred notContained) → False


{-# OPTIONS --without-K --exact-split #-}

module 02-natural-numbers where

import 00-preamble
open 00-preamble public

-- Definition 2.2.3
id : {i : Level} {A : UU i} → A → A
id a = a

-- Definition 2.2.4
_∘_ :
  {i j k : Level} {A : UU i} {B : UU j} {C : UU k} →
  (B → C) → ((A → B) → (A → C))
(g ∘ f) a = g (f a)

data ℕ : UU lzero where
  zero-ℕ : ℕ
  succ-ℕ : ℕ → ℕ

one-ℕ : ℕ
one-ℕ = succ-ℕ zero-ℕ

-- induction: for any dependent type P over ℕ, define a section of P
-- built out of a term in P 0 and a section of P n → P(Nsucc n)
ind-ℕ : {i : Level} {P : ℕ → UU i} → P zero-ℕ → ((n : ℕ) → P n → P(succ-ℕ n)) → ((n : ℕ) → P n)
ind-ℕ p0 pS zero-ℕ = p0
ind-ℕ p0 pS (succ-ℕ n) = pS n (ind-ℕ p0 pS n)

-- use the general induction principle to define addition
-- in this case P is ℕ, the special non-dependent type over ℕ, and
-- so sections of P (dependent functions Π_{x:ℕ} P(x)) are functions ℕ → ℕ

add-ℕ : ℕ → ℕ → ℕ
add-ℕ zero-ℕ y = y
add-ℕ (succ-ℕ x) y = succ-ℕ (add-ℕ x y)

-- Exercise 2.2
const : {i j : Level} (A : UU i) (B : UU j) (b : B) → A → B
const A B b x = b

-- Exercise 2.3

-- In this exercise we are asked to construct some standard functions on the
-- natural numbers.

-- Exercise 2.3(a)
max-ℕ : ℕ → (ℕ → ℕ)
max-ℕ zero-ℕ n = n
max-ℕ (succ-ℕ m) zero-ℕ = succ-ℕ m
max-ℕ (succ-ℕ m) (succ-ℕ n) = succ-ℕ (max-ℕ m n)

min-ℕ : ℕ → (ℕ → ℕ)
min-ℕ zero-ℕ n = zero-ℕ
min-ℕ (succ-ℕ m) zero-ℕ = zero-ℕ
min-ℕ (succ-ℕ m) (succ-ℕ n) = succ-ℕ (min-ℕ m n)

-- Exercise 2.3(b)
mul-ℕ : ℕ → (ℕ → ℕ)
mul-ℕ zero-ℕ n = zero-ℕ
mul-ℕ (succ-ℕ m) n = add-ℕ (mul-ℕ m n) n

-- Exercise 2.3(c)
_^_ : ℕ → (ℕ → ℕ)
m ^ zero-ℕ = one-ℕ
m ^ (succ-ℕ n) = mul-ℕ m (m ^ n)

-- Exercise 2.3(d)
factorial : ℕ → ℕ
factorial zero-ℕ = one-ℕ
factorial (succ-ℕ m) = mul-ℕ (succ-ℕ m) (factorial m)

-- Exercise 2.3(e)
_choose_ : ℕ → ℕ → ℕ
zero-ℕ choose zero-ℕ = one-ℕ
zero-ℕ choose succ-ℕ k = zero-ℕ
(succ-ℕ n) choose zero-ℕ = one-ℕ
(succ-ℕ n) choose (succ-ℕ k) = add-ℕ (n choose k) (n choose (succ-ℕ k))

-- Exercise 2.3(f)
Fibonacci : ℕ → ℕ
Fibonacci zero-ℕ = zero-ℕ
Fibonacci (succ-ℕ zero-ℕ) = one-ℕ
Fibonacci (succ-ℕ (succ-ℕ n)) = add-ℕ (Fibonacci n) (Fibonacci (succ-ℕ n))

-- Exercise 2.4
_∘'_ :
  {i j k : Level} {A : UU i} {B : A → UU j} {C : (x : A) → B x → UU k} →
  (g : (x : A) → (y : B x) → C x y) (f : (x : A) → B x) → (x : A) → C x (f x)
(g ∘' f) x = g x (f x)

-- Exercise 2.5
Π-swap : {i j k : Level} {A : UU i} {B : UU j} {C : A → (B → UU k)} →
  ((x : A) (y : B) → C x y) → ((y : B) (x : A) → C x y)
Π-swap f y x = f x y

-- Note: apparently Agda still allows us to define a sequence of universe levels indexed by ℕ

Level-ℕ : ℕ → Level
Level-ℕ zero-ℕ = lzero
Level-ℕ (succ-ℕ n) = lsuc (Level-ℕ n)

sequence-UU : (n : ℕ) → UU (Level-ℕ (succ-ℕ n))
sequence-UU n = UU (Level-ℕ n)

-- However, the following definition is unacceptable for Agda, since it runs
-- into Setω.

{-
Π-sequence-UU : Setω
Π-sequence-UU = (n : ℕ) → sequence-UU n
-}


module Cat where

open import Agda.Primitive
open import CS410-Prelude
open import CS410-Nat
open import CS410-Monoid
open import CS410-Vec

record Cat {k}{l}(O : Set k)(_>>_ : O -> O -> Set l) : Set (lsuc (k ⊔ l)) where
  field
    -- OPERATIONS ---------------------------------------------------------
    iden  : {X : O} -> X >> X
    comp  : {R S T : O} -> S >> T -> R >> S -> R >> T
    -- KLUDGE -------------------------------------------------------------
    Eq : {S T : O} -> S >> T -> S >> T -> Set l
    -- LAWS ---------------------------------------------------------------
    idenL : {S T : O}(f : S >> T) -> Eq (comp iden f) f
    idenR : {S T : O}(f : S >> T) -> Eq (comp f iden) f
    assoc : {Q R S T : O}(f : S >> T)(g : R >> S)(h : Q >> R) ->
            Eq (comp f (comp g h)) (comp (comp f g) h)

SetCat : Cat Set (\ S T -> S -> T)
SetCat = record
           { iden = id
           ; comp = _o_
           ; Eq    = \ f g -> forall x -> f x == g x
           ; idenL = λ {S} {T} f x → refl
           ; idenR = λ {S} {T} f x → refl
           ; assoc = λ {Q} {R} {S} {T} f g h x → refl
           }

N>=Cat : Cat Nat _N>=_
N>=Cat = record
           { iden = \ {n} -> N>=refl n
           ; comp = \ {l}{m}{n} -> N>=trans l m n
           ; Eq = \ _ _ -> One
           ; idenL = λ {S} {T} f → <>
           ; idenR = λ {S} {T} f → <>
           ; assoc = λ {Q} {R} {S} {T} f g h → <>
           } where
           N>=refl : (n : Nat) -> n N>= n
           N>=refl zero = <>
           N>=refl (suc n) = N>=refl n
           N>=trans : forall l m n -> m N>= n -> l N>= m -> l N>= n
           N>=trans l m zero mn lm = <>
           N>=trans l zero (suc n) () lm
           N>=trans zero (suc m) (suc n) mn ()
           N>=trans (suc l) (suc m) (suc n) mn lm = N>=trans l m n mn lm

MonCat : forall {X} -> Monoid X -> Cat One \ _ _ -> X
MonCat M = record
             { iden = e
             ; comp = op
             ; Eq = _==_
             ; idenL = lunit
             ; idenR = runit
             ; assoc = assoc
             } where open Monoid M

record Functor {k l}{ObjS : Set k}{_>S>_ : ObjS -> ObjS -> Set l}
               {m n}{ObjT : Set m}{_>T>_ : ObjT -> ObjT -> Set n}
               (CS : Cat ObjS _>S>_)(CT : Cat ObjT _>T>_)
               : Set (lsuc (k ⊔ l ⊔ m ⊔ n)) where
  open Cat
  field
    -- OPERATIONS ---------------------------------------------------------
    Map      : ObjS -> ObjT
    map      : {A B : ObjS} -> A >S> B -> Map A >T> Map B
    -- LAWS ---------------------------------------------------------------
    mapId    : {A : ObjS} -> Eq CT (map (iden CS {A})) (iden CT {Map A})
    mapComp  : {A B C : ObjS}(f : B >S> C)(g : A >S> B) ->
               Eq CT (map (comp CS f g)) (comp CT (map f) (map g))
    mapEq    : {A B : ObjS}{f g : A >S> B} ->
               Eq CS f g -> Eq CT (map f) (map g)

data List (X : Set) : Set where  -- X scopes over the whole declaration...
  []    : List X                 -- ...so you can use it here...
  _::_  : X -> List X -> List X  -- ...and here.
infixr 3 _::_

listMap : {A B : Set} → (A → B) → List A → List B
listMap f [] = []
listMap f (a :: as) = f a :: listMap f as

list : Functor SetCat SetCat
list = record
  { Map = List
  ; map = listMap
  ; mapId = {!!}
  ; mapComp = {!!}
  ; mapEq = {!!}
  }

{-
goo : Functor (MonCat +Mon) SetCat
goo = ?
-}

hoo : (X : Set) -> Functor N>=Cat SetCat
hoo X = record
  { Map = Vec X
  ; map = {!!}
  ; mapId = {!!}
  ; mapComp = {!!}
  ; mapEq = {!!}
  }


module IdemInvo where

open import Relation.Binary.PropositionalEquality

module MainResult
  (A : Set)
  (f : A → A)
  (idem : ∀ x → f (f x) ≡ f x)
  (invo : ∀ x → f (f x) ≡ x)
  where

  -- an idempotent and involutive function is an identity function
  iden : ∀ x → f x ≡ x
  iden x = trans (sym (idem x)) (invo x)


import      Lvl
open import Type

module FormalLanguage.RegularExpression {ℓ} (Σ : Type{ℓ}) where

open import Data.Boolean
open import Data.Boolean.Stmt.Proofs
open import Data.List as List using (List)
open import FormalLanguage
open import FormalLanguage.Proofs
open import Functional
open import Logic
open import Logic.Propositional
open import Numeral.Natural
open import Relator.Equals

data RegExp : Type{ℓ} where
  ∅ : RegExp     -- Empty language (Consisting of no words).
  ε : RegExp     -- Empty word language (Consisting of a single empty word).
  • : Σ → RegExp -- Singleton language (Consisting of a single one letter word).
  _++_ : RegExp → RegExp → RegExp -- Concatenation language (Consisting of the words concatenated pairwise).
  _‖_  : RegExp → RegExp → RegExp -- Union language (Consisting of the words in both languages).
  _*   : RegExp → RegExp          -- Infinite concatenations language (Consisting of the words concatenated with themselves any number of times).

-- Non-empty infinite concatenations language.
_+ : RegExp → RegExp
e + = e ++ (e *)

-- Optional expression language
_?? : RegExp → RegExp
e ?? = ε ‖ e

-- Finitely repeated expression language
exactly : ℕ → RegExp → RegExp
exactly 𝟎      e = ε
exactly (𝐒(n)) e = e ++ (exactly n e)

-- Minimum repetitions of an expression language
at-least : ℕ → RegExp → RegExp
at-least 𝟎      e = e *
at-least (𝐒(n)) e = e ++ (at-least n e)

-- Maximum repetitions of an expression language
at-most : ℕ → RegExp → RegExp
at-most 𝟎      e = ε
at-most (𝐒(n)) e = ε ‖ (e ++ (at-most n e))

-- Relation for whether a pattern/expression matches a word (whether the word is in the language that the pattern/expression describes).
data _matches_ : RegExp → List(Σ) → Stmt{ℓ} where
  empty-word : ε matches List.∅
  concatenation : ∀{r₁ r₂}{l₁ l₂} → (r₁ matches l₁) → (r₂ matches l₂) → ((r₁ ++ r₂) matches (l₁ List.++ l₂))
  disjunctionₗ : ∀{rₗ rᵣ}{l} → (rₗ matches l) → ((rₗ ‖ rᵣ) matches l)
  disjunctionᵣ : ∀{rₗ rᵣ}{l} → (rᵣ matches l) → ((rₗ ‖ rᵣ) matches l)
  iteration : ∀{r}{l₁ l₂} → (r matches l₁) → ((r *) matches l₂) → ((r *) matches (l₁ List.++ l₂))
  literal : ∀{a} → ((• a) matches List.singleton(a))

-- optional-empty : ∀{e} → ((e ??) matches List.∅)
pattern optional-empty = disjunctionₗ empty-word

optional-self : ∀{e}{l} → (e matches l) → ((e ??) matches l)
optional-self = disjunctionᵣ

empty-none : ∀{l} → ¬(∅ matches l)
empty-none ()

module _ ⦃ _ : ComputablyDecidable(_≡_) ⦄ where
  language : RegExp → Language(Σ)
  language ∅        = Oper.∅
  language ε        = Oper.ε
  language (• x)    = Oper.single x
  language (x ++ y) = language(x) Oper.𝁼 language(y)
  language (x ‖ y)  = language(x) Oper.∪ language(y)
  language (x *)    = language(x) Oper.*

  postulate matches-language : ∀{e}{l} → (e matches l) → (l Oper.∈ language(e))
  {-matches-language {ε} {List.∅} empty-word = [⊤]-intro
  matches-language {• a} {.a List.⊰ .List.∅} literal = {!!}
  matches-language {e₁ ++ e₂} {List.∅}     p = {!!}
  matches-language {e₁ ++ e₂} {x List.⊰ l} p = {!!}
  matches-language {e₁ ‖ e₂} {List.∅} (disjunctionₗ p) = IsTrue.[∨]-introₗ(matches-language {e₁} p)
  matches-language {e₁ ‖ e₂} {List.∅} (disjunctionᵣ p) = IsTrue.[∨]-introᵣ(matches-language {e₂} p)
    matches-language {e₁ ‖ e₂} {x List.⊰ l} (disjunctionₗ p) = [↔]-to-[←] ([∪]-containment {x = x List.⊰ l}{A = language(e₁)}{B = language(e₂)}) ([∨]-introₗ (matches-language {e₁} p))
    matches-language {e₁ ‖ e₂} {x List.⊰ l} (disjunctionᵣ p) = [↔]-to-[←] ([∪]-containment {x = x List.⊰ l}{A = language(e₁)}{B = language(e₂)}) ([∨]-introᵣ (matches-language {e₂} p))
  matches-language {e *} {List.∅}     p = {!!}
  matches-language {e *} {x List.⊰ l} p = {!!}
  -}

  postulate language-matches : ∀{e}{l} → (l Oper.∈ language(e)) → (e matches l)
  {-language-matches {∅}        {x List.⊰ l} p with () ← language-matches {∅} {l} p
  language-matches {ε}        {List.∅}     [⊤]-intro = empty-word
  language-matches {ε}        {x List.⊰ l} p with () ← [↔]-to-[→] ([ε]-containment {x = x List.⊰ l}) p
  language-matches {• a}      {x List.⊰ l} p with [≡]-intro ← [↔]-to-[→] (single-containment {x = x List.⊰ l}) p = literal
  language-matches {e₁ ++ e₂} {List.∅}     p = {!!}
  language-matches {e₁ ++ e₂} {x List.⊰ l} p = {!!}
  language-matches {e₁ ‖ e₂}  {l} p = [∨]-elim (disjunctionₗ ∘ language-matches) (disjunctionᵣ ∘ language-matches) ([↔]-to-[→] ([∪]-containment {x = l} {A = language(e₁)} {B = language(e₂)}) p)
  language-matches {e *}      {List.∅} [⊤]-intro = {![*]-containment!}
  language-matches {e *}      {x List.⊰ l} p = {!!}
  -}