module 747Decidable where

-- Library

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym) -- added sym
open Eq.≡-Reasoning
open import Data.Nat using (ℕ; zero; suc; _≤_; z≤n; s≤s)
open import Data.Product using (_×_) renaming (_,_ to ⟨_,_⟩)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Relation.Nullary using (¬_)
open import Relation.Nullary.Negation using ()
  renaming (contradiction to ¬¬-intro)
open import Data.Unit using (⊤; tt)
open import Data.Empty using (⊥; ⊥-elim)

-- Copied from 747Isomorphism.

record _⇔_ (A B : Set) : Set where
  field
    to   : A → B
    from : B → A
open _⇔_

-- Copied from 747Relations.

infix 4 _<_

data _<_ : ℕ → ℕ → Set where

  z<s : ∀ {n : ℕ}
      ------------
    → zero < suc n

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

-- Recall that the constructors for _≤_ are z≤n and s≤s.

-- Here are a couple of examples to show how to prove inequalities
-- (or their negations).

2≤4 : 2 ≤ 4
2≤4 = {!!}

¬4≤2 : ¬ (4 ≤ 2)
¬4≤2 = {!!}

-- This should be familiar.

data Bool : Set where
  true  : Bool
  false : Bool

-- We can define a Boolean comparison function.

infix 4 _≤ᵇ_

_≤ᵇ_ : ℕ → ℕ → Bool
m ≤ᵇ n = {!!}

-- PLFA steps through these computations using equational reasoning.

_ : (2 ≤ᵇ 4) ≡ true
_ =  refl

_ : (4 ≤ᵇ 2) ≡ false
_ = refl

-- Relating evidence and computation.

T : Bool → Set
T true   =  ⊤
T false  =  ⊥

T→≡ : ∀ (b : Bool) → T b → b ≡ true
T→≡ b t = {!!}

≡→T : ∀ {b : Bool} → b ≡ true → T b
≡→T e = {!!}

≤ᵇ→≤ : ∀ (m n : ℕ) → T (m ≤ᵇ n) → m ≤ n
≤ᵇ→≤ m n t = {!!}

≤→≤ᵇ : ∀ {m n : ℕ} → m ≤ n → T (m ≤ᵇ n)
≤→≤ᵇ m≤n = {!!}

-- Getting the best of both worlds!

data Dec (A : Set) : Set where
  yes :   A → Dec A
  no  : ¬ A → Dec A

-- Helpers for defining _≤?_
-- If you don't use these, the examples below won't normalize.

¬s≤z : ∀ {m : ℕ} → ¬ (suc m ≤ zero)
¬s≤z = {!!}

¬s≤s : ∀ {m n : ℕ} → ¬ (m ≤ n) → ¬ (suc m ≤ suc n)
¬s≤s = {!!}

-- Decidable ≤.

_≤?_ : ∀ (m n : ℕ) → Dec (m ≤ n)
m ≤? n = {!!}

_ : 2 ≤? 4 ≡ yes (s≤s (s≤s z≤n))
_ = refl

_ : 4 ≤? 2 ≡ no (¬s≤s (¬s≤s ¬s≤z))
_ = refl

-- We can also evaluate the LHS of these using C-c C-n.

-- 747/PLFA exercise: DecLT (3 point)
-- Decidable strict equality.
-- You will need these helper functions as we did above.

¬z<z : ¬ (zero < zero)
¬z<z = {!!}

¬s<s : ∀ {m n : ℕ} → ¬ (m < n) → ¬ (suc m < suc n)
¬s<s = {!!}

¬s<z : ∀ {n : ℕ} → ¬ (suc n < zero)
¬s<z = {!!}

_<?_ : ∀ (m n : ℕ) → Dec (m < n)
m <? n = {!!}

-- Some tests.

_ : 2 <? 4 ≡ yes (s<s (s<s (z<s)))
_ = refl

_ : 4 <? 2 ≡ no (¬s<s (¬s<s ¬s<z))
_ = refl

_ : 3 <? 3 ≡ no (¬s<s (¬s<s (¬s<s ¬z<z)))
_ = refl

-- 747/PLFA exercise: DecNatEq (3 points)
-- Decidable equality for natural numbers.

_≡ℕ?_ : ∀ (m n : ℕ) → Dec (m ≡ n) -- split m,n
m ≡ℕ? n = {!!}

-- Reusing ≤ᵇ and proofs of equivalence with ≤ to decide ≤.

_≤?′_ : ∀ (m n : ℕ) → Dec (m ≤ n)
m ≤?′ n = {!!}

-- Erasing Dec down to Bool (or "isYes").

⌊_⌋ : ∀ {A : Set} → Dec A → Bool
⌊ yes x ⌋ = true
⌊ no x ⌋ = false

_≤ᵇ′_ : ℕ → ℕ → Bool
m ≤ᵇ′ n  =  ⌊ m ≤? n ⌋

-- If D is Dec A, then T ⌊ D ⌋ is inhabited exactly when A is inhabited.

toWitness : ∀ {A : Set} {D : Dec A} → T ⌊ D ⌋ → A
toWitness t = {!!}

fromWitness : ∀ {A : Set} {D : Dec A} → A → T ⌊ D ⌋
fromWitness a = {!!}

-- Similar ideas when it is the "no" witnesses we want to handle.

isNo : ∀ {A : Set} → Dec A → Bool
isNo (yes _) = false
isNo (no _)  = true

toWitnessFalse : ∀ {A : Set} {D : Dec A} → T (isNo D) → ¬ A
toWitnessFalse = {!!}

fromWitnessFalse : ∀ {A : Set} {D : Dec A} → ¬ A → T (isNo D)
fromWitnessFalse = {!!}

-- Agda standard library definitions for use of these.

True : ∀ {A : Set} → (D : Dec A) → Set
True Q = T ⌊ Q ⌋

False : ∀ {A : Set} → (D : Dec A) → Set
False Q = T (isNo Q)

-- A concrete example.

≤ᵇ′→≤ : ∀ {m n : ℕ} → T (m ≤ᵇ′ n) → m ≤ n
≤ᵇ′→≤  =  toWitness

≤→≤ᵇ′ : ∀ {m n : ℕ} → m ≤ n → T (m ≤ᵇ′ n)
≤→≤ᵇ′  =  fromWitness

-- Conclusion: use Decidables instead of Booleans!

-- Logical connectives for Decidables.

infixr 6 _∧_

_∧_ : Bool → Bool → Bool
true ∧ true = true
true ∧ false = false
false ∧ y = false

infixr 6 _×-dec_

_×-dec_ : ∀ {A B : Set} → Dec A → Dec B → Dec (A × B)
da ×-dec db = {!!}

infixr 5 _∨_

_∨_ : Bool → Bool → Bool
true ∨ y = true
false ∨ y = y

infixr 5 _⊎-dec_

_⊎-dec_ : ∀ {A B : Set} → Dec A → Dec B → Dec (A ⊎ B)
da ⊎-dec db = {!!}

not : Bool → Bool
not true  = false
not false = true

¬? : ∀ {A : Set} → Dec A → Dec (¬ A)
¬? da = {!!}

-- A Boolean version of implication.

_⊃_ : Bool → Bool → Bool
true ⊃ true = true
true ⊃ false = false
false ⊃ y = true

_→-dec_ : ∀ {A B : Set} → Dec A → Dec B → Dec (A → B)
da →-dec db = {!!}

-- 747/PLFA exercise: ErasBoolDec (3 points)
-- Erasure relates boolean and decidable operations.

∧-× : ∀ {A B : Set} (x : Dec A) (y : Dec B) → ⌊ x ⌋ ∧ ⌊ y ⌋ ≡ ⌊ x ×-dec y ⌋
∧-× da db = {!!}

∨-× : ∀ {A B : Set} (x : Dec A) (y : Dec B) → ⌊ x ⌋ ∨ ⌊ y ⌋ ≡ ⌊ x ⊎-dec y ⌋
∨-× da db = {!!}

not-¬ : ∀ {A : Set} (x : Dec A) → not ⌊ x ⌋ ≡ ⌊ ¬? x ⌋
not-¬ da = {!!}

-- 747/PLFA exercise: iff-erasure.

_iff_ : Bool → Bool → Bool
true iff true = true
true iff false = false
false iff true = false
false iff false = true

_⇔-dec_ : ∀ {A B : Set} → Dec A → Dec B → Dec (A ⇔ B)
da ⇔-dec db = {!!}

iff-⇔ : ∀ {A B : Set} (x : Dec A) (y : Dec B) → ⌊ x ⌋ iff ⌊ y ⌋ ≡ ⌊ x ⇔-dec y ⌋
iff-⇔ da db = {!!}

-- Proof by reflection.
-- Or, getting Agda to construct proofs at compile time.

-- A guarded version of monus.

minus : (m n : ℕ) (n≤m : n ≤ m) → ℕ
minus m zero _ = m
minus (suc m) (suc n) (s≤s m≤n) = minus m n m≤n

-- But we have to provide proofs.

_ : minus 5 3 (s≤s (s≤s (s≤s z≤n))) ≡ 2
_ = refl

-- Agda will fill in an implicit record type if it can fill in all fields.
-- Since ⊤ is defined as a record type with no fields...
-- We can get Agda to compute a value of type True (n ≤? m).

_-_ : (m n : ℕ) {n≤m : True (n ≤? m)} → ℕ
_-_ m n {n≤m} = minus m n (toWitness n≤m)

_ : 5 - 3 ≡ 2
_ = refl

-- We will later use this to get Agda to compute parts of proofs
-- that would be annoying for us to provide.


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

open import Relation.Binary using (Rel; Setoid; IsEquivalence)
module Loop.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 Loop.Definitions _≈_
open import Algebra.Structures _≈_

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


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

open import LogicalFormulae
open import Setoids.Setoids
open import Sets.EquivalenceRelations
open import Rings.Definition
open import Rings.Homomorphisms.Definition

module Rings.Homomorphisms.Image {a b c d : _} {A : Set a} {B : Set c} {S : Setoid {a} {b} A} {T : Setoid {c} {d} B} {_+A_ _*A_ : A → A → A} {_+B_ _*B_ : B → B → B} {R1 : Ring S _+A_ _*A_} {R2 : Ring T _+B_ _*B_} {f : A → B} (hom : RingHom R1 R2 f) where

open import Groups.Homomorphisms.Image (RingHom.groupHom hom)
open import Rings.Subrings.Definition

imageGroupSubring : Subring R2 imageGroupPred
Subring.isSubgroup imageGroupSubring = imageGroupSubgroup
Subring.containsOne imageGroupSubring = Ring.1R R1 , RingHom.preserves1 hom
Subring.closedUnderProduct imageGroupSubring {x} {y} (a , fa=x) (b , fb=y) = (a *A b) , transitive ringHom (Ring.*WellDefined R2 fa=x fb=y)
  where
    open Setoid T
    open Equivalence eq
    open RingHom hom


------------------------------------------------------------------------------
-- Proving properties without using pattern matching on refl
------------------------------------------------------------------------------

{-# OPTIONS --no-pattern-matching      #-}
{-# OPTIONS --exact-split              #-}
{-# OPTIONS --no-sized-types           #-}
{-# OPTIONS --no-universe-polymorphism #-}

module FOT.PA.Axiomatic.Standard.NoPatternMatchingOnRefl where

open import PA.Axiomatic.Standard.Base

------------------------------------------------------------------------------
-- From PA.Axiomatic.Standard.PropertiesI

-- Congruence properties

succCong : ∀ {m n} → m ≡ n → succ m ≡ succ n
succCong {m} h = subst (λ t → succ m ≡ succ t) h refl

+-leftCong : ∀ {m n o} → m ≡ n → m + o ≡ n + o
+-leftCong {m} {o = o} h = subst (λ t → m + o ≡ t + o) h refl

+-rightCong : ∀ {m n o} → n ≡ o → m + n ≡ m + o
+-rightCong {m} {n} h = subst (λ t → m + n ≡ m + t) h refl


{-# OPTIONS --show-implicit #-}
-- {-# OPTIONS --sized-types #-}         -- no longer necessary
-- {-# OPTIONS --termination-depth=2 #-} -- no longer necessary
-- {-# OPTIONS -v term:10 #-}

module SizedBTree where

open import Common.Size

module Old where

  data BTree (A : Set) : {size : Size} → Set where
    leaf : {i : Size} → A → BTree A {↑ i}
    node : {i : Size} → BTree A {i} → BTree A {i} → BTree A {↑ i}

  map : ∀ {A B i} → (A → B) → BTree A {i} → BTree B {i}
  map f (leaf a) = leaf (f a)
  map f (node l r) = node (map f l) (map f r)

  -- deep matching

  deep : ∀ {i A} → BTree A {i} → A
  deep (leaf a) = a
  deep (node (leaf _) r) = deep r
  deep (node (node l r) _) = deep (node l r)

  -- nesting

  -- Jesper 2015-12-18: The new unifier requires the size argument of the first
  -- deep2 to be given explicitly. This is because otherwise the unifier gets
  -- stuck on an equation [↑ i₁ =?= _i_46 {i} {A} l r t]. It's not clear whether
  -- it is safe to instantiate the meta to [↑ _] here.
  deep2 : ∀ {i A} → BTree A {i} → BTree A {i}
  deep2 (leaf a) = leaf a
  deep2 (node (leaf _) r) = r
  deep2 (node (node {i} l r) t) with deep2 {↑ i} (deep2 (node l r))
  ... | leaf a = leaf a
  ... | node l2 r2 = deep2 (node l2 r2)

  -- OUTDATED: -- increasing the termination count does the job!

module New where

  data BTree (A : Set) {i : Size} :  Set where
    leaf : A → BTree A
    node : {i' : Size< i} → BTree A {i'} → BTree A {i'} → BTree A

  map : ∀ {A B i} → (A → B) → BTree A {i} → BTree B {i}
  map f (leaf a)   = leaf (f a)
  map f (node l r) = node (map f l) (map f r)

  -- deep matching

  deep : ∀ {i A} → BTree A {i} → A
  deep (leaf a)            = a
  deep (node (leaf _)   r) = deep r
  deep (node (node l r) _) = deep (node l r)

  -- nesting

  deep2 : ∀ {i A} → BTree A {i} → BTree A {i}
  deep2 (leaf a)            = leaf a
  deep2 (node (leaf _)   r) = r
  deep2 (node (node l r) _) with deep2 (deep2 (node l r))
  ... | leaf a     = leaf a
  ... | node l2 r2 = deep2 (node l2 r2)


{- Diamond operator. -}
module TemporalOps.Diamond.Functor where

open import CategoryTheory.Categories
open import CategoryTheory.Instances.Reactive
open import CategoryTheory.Functor
open import TemporalOps.Common
open import TemporalOps.Next
open import TemporalOps.Delay
open import Data.Product

-- Arbitrary delay
◇_ : τ -> τ
(◇ A) n = Σ[ k ∈ ℕ ] (delay A by k at n)
infixr 65 ◇_

-- ◇ instances
F-◇ : Endofunctor ℝeactive
F-◇ = record
    { omap      = ◇_
    ; fmap      = fmap-◇
    ; fmap-id   = fmap-◇-id
    ; fmap-∘    = fmap-◇-∘
    ; fmap-cong = fmap-◇-cong
    }
    where
    -- Lifting of ◇
    fmap-◇ : {A B : τ} -> A ⇴ B -> ◇ A ⇴ ◇ B
    fmap-◇ f n (k , v) = k , (Functor.fmap (F-delay k) f at n) v
    -- ◇ preserves identities
    fmap-◇-id : ∀ {A : τ} {n : ℕ} {a : (◇ A) n}
             -> (fmap-◇ (id {A}) at n) a ≡ a
    fmap-◇-id {A} {n} {zero , v} = refl
    fmap-◇-id {A} {zero} {suc k , v} = refl
    fmap-◇-id {A} {suc n} {suc k , v}
        rewrite delay-+ {A} 1 k n
              | Functor.fmap-id (F-delay (suc k)) {A} {suc n} {v}
        = refl
    -- ◇ preserves composition
    fmap-◇-∘ : ∀ {A B C : τ} {g : B ⇴ C} {f : A ⇴ B} {n : ℕ} {a : (◇ A) n}
            -> (fmap-◇ (g ∘ f) at n) a ≡ (fmap-◇ g ∘ fmap-◇ f at n) a
    fmap-◇-∘ {n = n} {zero , v} = refl
    fmap-◇-∘ {n = zero} {suc k , v} = refl
    fmap-◇-∘ {A} {B} {C} {g} {f} {suc n} {suc k , v}
        rewrite delay-+ {A} 1 k n
              | Functor.fmap-∘ (F-delay (suc k)) {A} {B} {C} {g} {f} {suc n} {v}
        = refl
    -- ▹ is congruent
    fmap-◇-cong : ∀{A B : τ} {f f′ : A ⇴ B}
            -> ({n : ℕ} {a : A at n}   -> f n a ≡ f′ n a)
            -> ({n : ℕ} {a : ◇ A at n} -> (fmap-◇ f at n) a
                                        ≡ (fmap-◇ f′ at n) a)
    fmap-◇-cong {A} e {n} {zero , a}
        rewrite delay-+-left0 {A} 0 n
              | e {n} {a} = refl
    fmap-◇-cong e {zero} {suc k , a} = refl
    fmap-◇-cong {A} {B} {f} {f′} e {suc n} {suc k , a}
        rewrite delay-+ {A} 1 k n
              | Functor.fmap-cong (F-delay (suc k)) {A} {B} {f} {f′} e {suc n} {a}
              = refl


-- Minimal implicational logic, PHOAS approach, initial encoding

module Pi.ArrMp where

-- Types

infixr 0 _=>_
data Ty : Set where
  UNIT :             Ty
  _=>_ : Ty -> Ty -> Ty

-- Context and truth judgement

Cx : Set1
Cx = Ty -> Set

isTrue : Ty -> Cx -> Set
isTrue a tc = tc a

-- Terms

module ArrMp where
  infixl 1 _$_
  data Tm (tc : Cx) : Ty -> Set where
    var  : forall {a}   -> isTrue a tc               -> Tm tc a
    lam' : forall {a b} -> (isTrue a tc -> Tm tc b)  -> Tm tc (a => b)
    _$_  : forall {a b} -> Tm tc (a => b) -> Tm tc a -> Tm tc b

  lam'' : forall {tc a b} -> (Tm tc a -> Tm tc b) -> Tm tc (a => b)
  lam'' f = lam' \x -> f (var x)

  syntax lam'' (\a -> b) = lam a => b

  Thm : Ty -> Set1
  Thm a = forall {tc} -> Tm tc a
open ArrMp public

-- Example theorems

aI : forall {a} -> Thm (a => a)
aI =
  lam x => x

aK : forall {a b} -> Thm (a => b => a)
aK =
  lam x =>
    lam _ => x

aS : forall {a b c} -> Thm ((a => b => c) => (a => b) => a => c)
aS =
  lam f =>
    lam g =>
      lam x => f $ x $ (g $ x)

tSKK : forall {a} -> Thm (a => a)
tSKK {a = a} =
  aS {b = a => a} $ aK $ aK


------------------------------------------------------------------------
-- The Agda standard library
--
-- Digits and digit expansions
------------------------------------------------------------------------

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

module Data.Digit where

open import Data.Nat using (ℕ; zero; suc; pred; _+_; _*_; _≤?_; _≤′_)
open import Data.Nat.Properties
open import Data.Nat.Solver
open import Data.Fin as Fin using (Fin; zero; suc; toℕ)
open import Data.Char using (Char)
open import Data.List.Base
open import Data.Product
open import Data.Vec as Vec using (Vec; _∷_; [])
open import Data.Nat.DivMod
open import Induction.Nat using (<′-rec; <′-Rec)
open import Relation.Nullary using (yes; no)
open import Relation.Nullary.Decidable
open import Relation.Binary using (Decidable)
open import Relation.Binary.PropositionalEquality as P using (_≡_; refl)
open import Function

open +-*-Solver

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

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

Digit : ℕ → Set
Digit b = Fin b

-- Some specific digit kinds.

Decimal = Digit 10
Bit     = Digit 2

-- Some named digits.

0b : Bit
0b = zero

1b : Bit
1b = suc zero

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

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

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

-- showDigit shows digits in base ≤ 16.

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

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

Expansion : ℕ → Set
Expansion base = List (Fin base)

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

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

-- toDigits b n yields the digits of n, in base b, starting with the
-- _least_ significant digit.
--
-- Note that the list of digits is always non-empty.

toDigits : (base : ℕ) {base≥2 : True (2 ≤? base)} (n : ℕ) →
           ∃ λ (ds : Expansion base) → fromDigits ds ≡ n
toDigits zero       {base≥2 = ()} _
toDigits (suc zero) {base≥2 = ()} _
toDigits (suc (suc k)) n = <′-rec Pred helper n
  where
  base = suc (suc k)
  Pred = λ n → ∃ λ ds → fromDigits ds ≡ n

  cons : ∀ {m} (r : Fin base) → Pred m → Pred (toℕ r + m * base)
  cons r (ds , eq) = (r ∷ ds , P.cong (λ i → toℕ r + i * base) eq)

  open ≤-Reasoning

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

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


------------------------------------------------------------------------
-- Spheres
------------------------------------------------------------------------

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

-- This module follows the HoTT book rather closely.

import Equality.Path as P

module Sphere
  {e⁺} (eq : ∀ {a p} → P.Equality-with-paths a p e⁺) where

open P.Derived-definitions-and-properties eq hiding (elim)

open import Logical-equivalence using (_⇔_)
open import Prelude

open import Bijection equality-with-J using (_↔_)
open import Equality.Path.Isomorphisms eq
open import Equality.Tactic equality-with-J
import Equivalence equality-with-J as Equiv
open import Function-universe equality-with-J as F hiding (_∘_)
open import H-level equality-with-J
open import H-level.Closure equality-with-J
open import Nat equality-with-J as Nat
open import Pointed-type equality-with-J
open import Suspension eq as Suspension

private
  variable
    a b : Level
    A B : Type a
    C   : Pointed-type a
    x   : A
    n   : ℕ

-- Spheres.

𝕊[_-1] : ℕ → Type
𝕊[ zero  -1] = ⊥
𝕊[ suc n -1] = Susp 𝕊[ n -1]

-- Spheres with non-negative dimensions.

𝕊 : ℕ → Type
𝕊 n = 𝕊[ 1 + n -1]

-- The booleans are isomorphic to the 0-dimensional sphere.

Bool↔𝕊⁰ : Bool ↔ 𝕊 0
Bool↔𝕊⁰ = Bool↔Susp-⊥

-- Based maps from spheres with non-negative dimensions (using north
-- as the point) are isomorphic to iterated loop spaces.

𝕊→ᴮ↔ : ∀ n → (𝕊 n , north) →ᴮ C ↔ proj₁ (Ω[ n ] C)
𝕊→ᴮ↔ {C = C} = lemma zero
  where
  lemma : ∀ m n → (𝕊 n , north) →ᴮ Ω[ m ] C ↔ proj₁ (Ω[ m + n ] C)
  lemma m zero =
    (𝕊 0 , north) →ᴮ Ω[ m ] C  ↝⟨ Σ-cong (→-cong ext (inverse Bool↔𝕊⁰) F.id) (λ _ → F.id) ⟩
    (Bool , true) →ᴮ Ω[ m ] C  ↝⟨ Bool→ᴮ↔ ext ⟩
    proj₁ (Ω[ m ] C)           ↝⟨ ≡⇒↝ _ $ cong (λ n → proj₁ (Ω[ n ] C)) $ sym $ Nat.+-right-identity {n = m} ⟩□
    proj₁ (Ω[ m + 0 ] C)       □

  lemma m (suc n) =
    (𝕊 (suc n) , north) →ᴮ Ω[ m ] C  ↝⟨ Susp→ᴮ↔ ⟩
    (𝕊 n , north) →ᴮ Ω[ suc m ] C    ↝⟨ lemma (suc m) n ⟩
    proj₁ (Ω[ suc m + n ] C)         ↝⟨ ≡⇒↝ _ $ cong (λ n → proj₁ (Ω[ n ] C)) $ Nat.suc+≡+suc m ⟩□
    proj₁ (Ω[ m + suc n ] C)         □

-- A corollary.

+↔∀contractible𝕊→ᴮ :
  H-level (1 + n) A ↔
  (∀ x → Contractible ((𝕊 n , north) →ᴮ (A , x)))
+↔∀contractible𝕊→ᴮ {n = n} {A = A} =
  H-level (1 + n) A                                ↔⟨ _↔_.to (Equiv.⇔↔≃ ext (H-level-propositional ext _)
                                                                            (Π-closure ext 1 λ _ →
                                                                             H-level-propositional ext _))
                                                             (+⇔∀contractible-Ω[] _) ⟩
  (∀ x → Contractible (proj₁ $ Ω[ n ] (A , x)))    ↝⟨ (∀-cong ext λ _ → H-level-cong ext 0 (inverse $ 𝕊→ᴮ↔ _)) ⟩□
  (∀ x → Contractible ((𝕊 n , north) →ᴮ (A , x)))  □


------------------------------------------------------------------------
-- Reasoning about _⇔_
--
-- NOTE: we don’t use Relation.Binary.IsEquivalence here, since we’re reasoning
-- about a heterogeneous equivalence relation (i.e., the types of the operands
-- of _⇔_, which are themselves types, can be of different levels). In the proof
-- of Chapter₁₅.problem₁, the fact that _⇔_ is heterogeneous is actually used,
-- so we cannot use a homogeneous version of _⇔_.
------------------------------------------------------------------------

module Function.Equivalence.Reasoning where

open import Function using (_⇔_)
open import Function.Construct.Composition using (_∘-⇔_) public
open import Function.Construct.Identity using (id-⇔) public
open import Function.Construct.Symmetry using (sym-⇔) public
open import Level using (Level)

private
  variable
    a b c : Level

infix  1 begin_
infixr 2 _⇔⟨⟩_ step-⇔ step-⇔˘
infix  3 _∎

begin_ : {A : Set a} {B : Set b} → A ⇔ B → A ⇔ B
begin A⇔B = A⇔B

_∎ : (A : Set a) → A ⇔ A
_∎ = id-⇔

_⇔⟨⟩_ : (A : Set a) {B : Set b} → A ⇔ B → A ⇔ B
A ⇔⟨⟩ A⇔B = A⇔B

step-⇔ : (A : Set a) {B : Set b} {C : Set c} → A ⇔ B → B ⇔ C → A ⇔ C
step-⇔ A = _∘-⇔_

syntax step-⇔ A A⇔B B⇔C = A ⇔⟨ A⇔B ⟩ B⇔C

step-⇔˘ : (A : Set a) {B : Set b} {C : Set c} → B ⇔ A → B ⇔ C → A ⇔ C
step-⇔˘ A B⇔A B⇔C = A ⇔⟨ sym-⇔ B⇔A ⟩ B⇔C

syntax step-⇔˘ A B⇔A B⇔C = A ⇔˘⟨ B⇔A ⟩ B⇔C


module Formalization.ClassicalPropositionalLogic.Syntax where

import      Lvl
open import Functional
open import Sets.PredicateSet using (PredSet)
open import Type

private variable ℓₚ ℓ : Lvl.Level

module _ (P : Type{ℓₚ}) where
  -- Formulas.
  -- Inductive definition of the grammatical elements of the language of propositional logic.
  -- Note: It is possible to reduce the number of formula variants to for example {•,¬,∨} or {•,¬,∧} (This is called propositional adequacy/functional completeness).
  data Formula : Type{ℓₚ} where
    •_ : P → Formula -- Propositional constants

    ⊤ : Formula -- Tautology (Top / True)
    ⊥ : Formula -- Contradiction (Bottom / False)

    ¬_ : Formula → Formula -- Negation (Not)

    _∧_ : Formula → Formula → Formula -- Conjunction (And)
    _∨_ : Formula → Formula → Formula -- Disjunction (Or)
    _⟶_ : Formula → Formula → Formula -- Implication
    _⟷_ : Formula → Formula → Formula -- Equivalence

  Formulas : Type{ℓₚ Lvl.⊔ Lvl.𝐒(ℓ)}
  Formulas{ℓ} = PredSet{ℓ}(Formula)

  infix 1011 •_
  infix 1010 ¬_ ¬¬_
  infixr 1005 _∧_
  infixr 1004 _∨_
  infixr 1000 _⟷_ _⟶_

module _ {P : Type{ℓₚ}} where
  -- Double negation
  -- ¬¬_ : Formula(P) → Formula(P)
  -- ¬¬_ : (¬_) ∘ (¬_)

  -- Reverse implication
  _⟵_ : Formula(P) → Formula(P) → Formula(P)
  _⟵_ = swap(_⟶_)

  -- (Nor)
  _⊽_ : Formula(P) → Formula(P) → Formula(P)
  _⊽_ = (¬_) ∘₂ (_∨_)

  -- (Nand)
  _⊼_ : Formula(P) → Formula(P) → Formula(P)
  _⊼_ = (¬_) ∘₂ (_∧_)

  -- (Exclusive or / Xor)
  _⊻_ : Formula(P) → Formula(P) → Formula(P)
  _⊻_ = (¬_) ∘₂ (_⟷_)

  infixl 1000 _⟵_


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

open import Cubical.Data.FinData
open import Cubical.Data.Nat
open import Cubical.Data.Vec

open import Cubical.Algebra.CommRing
open import Cubical.Algebra.CommRing.FGIdeal renaming (generatedIdeal to generatedIdealCommRing)
open import Cubical.Algebra.CommAlgebra
open import Cubical.Algebra.CommAlgebra.Ideal

private
  variable
    ℓ : Level

module _ {R : CommRing ℓ} (A : CommAlgebra R ℓ) where
  open CommAlgebraStr (snd A)

  generatedIdeal : {n : ℕ} → FinVec (fst A) n → IdealsIn A
  generatedIdeal = generatedIdealCommRing (CommAlgebra→CommRing A)


-- The simpler case of index inductive definitions. (no induction-recursion)
module IID where

open import LF

-- A code for an IID
-- I - index set
-- E = I for general IIDs
-- E = One for restricted IIDs
data OP (I : Set)(E : Set) : Set1 where
  ι : E -> OP I E
  σ : (A : Set)(γ : A -> OP I E) -> OP I E
  δ : (A : Set)(i : A -> I)(γ : OP I E) -> OP I E

-- The type of constructor arguments. Parameterised over
--  U - the inductive type
-- This is the F of the simple polynomial type μF
Args : {I : Set}{E : Set} -> OP I E ->
     (U : I -> Set) -> Set
Args (ι e)     U = One
Args (σ A γ)   U = A × \a -> Args (γ a) U
Args (δ A i γ) U = ((a : A) -> U (i a)) × \_ -> Args γ U

-- Computing the index
index : {I : Set}{E : Set}(γ : OP I E)(U : I -> Set) -> Args γ U -> E
index (ι e)     U _ = e
index (σ A γ)   U a = index (γ (π₀ a)) U (π₁ a)
index (δ A i γ) U a = index γ U (π₁ a)

-- The assumptions of a particular inductive occurrence in a value.
IndArg : {I : Set}{E : Set}
       (γ : OP I E)(U : I -> Set) ->
       Args γ U -> Set
IndArg (ι e)     U _ = Zero
IndArg (σ A γ)   U a = IndArg (γ (π₀ a)) U (π₁ a)
IndArg (δ A i γ) U a = A + IndArg γ U (π₁ a)

-- Given the assumptions of an inductive occurence in a value we can compute
-- its index.
IndIndex : {I : Set}{E : Set}
          (γ : OP I E)(U : I -> Set) ->
          (a : Args γ U) -> IndArg γ U a -> I
IndIndex (ι e)     U _	      ()
IndIndex (σ A γ)   U arg c       = IndIndex (γ (π₀ arg)) U (π₁ arg) c
IndIndex (δ A i γ) U arg (inl a) = i a
IndIndex (δ A i γ) U arg (inr a) = IndIndex γ U (π₁ arg) a

-- Given the assumptions of an inductive occurrence in a value we can compute
-- its value.
Ind : {I : Set}{E : Set}
      (γ : OP I E)(U : I -> Set) ->
      (a : Args γ U)(v : IndArg γ U a) -> U (IndIndex γ U a v)
Ind (ι e)     U _	      ()
Ind (σ A γ)   U arg c       = Ind (γ (π₀ arg)) U (π₁ arg) c
Ind (δ A i γ) U arg (inl a) = (π₀ arg) a
Ind (δ A i γ) U arg (inr a) = Ind γ U (π₁ arg) a

-- The type of induction hypotheses. Basically
--  forall assumptions, the predicate holds for an inductive occurrence with
--  those assumptions
IndHyp : {I : Set}{E : Set}
      (γ : OP I E)(U : I -> Set) ->
      (F : (i : I) -> U i -> Set)(a : Args γ U) -> Set
IndHyp γ U F a = (v : IndArg γ U a) -> F (IndIndex γ U a v) (Ind γ U a v)

IndHyp₁ : {I : Set}{E : Set}
      (γ : OP I E)(U : I -> Set) ->
      (F : (i : I) -> U i -> Set1)(a : Args γ U) -> Set1
IndHyp₁ γ U F a = (v : IndArg γ U a) -> F (IndIndex γ U a v) (Ind γ U a v)

-- If we can prove a predicate F for any values, we can construct the inductive
-- hypotheses for a given value.
-- Termination note: g will only be applied to values smaller than a
induction :
  {I : Set}{E : Set}
  (γ : OP I E)(U : I -> Set)
  (F : (i : I) -> U i -> Set)
  (g : (i : I)(u : U i) -> F i u)
  (a : Args γ U) -> IndHyp γ U F a
induction γ U F g a = \hyp -> g (IndIndex γ U a hyp) (Ind γ U a hyp)

induction₁ :
  {I : Set}{E : Set}
  (γ : OP I E)(U : I -> Set)
  (F : (i : I) -> U i -> Set1)
  (g : (i : I)(u : U i) -> F i u)
  (a : Args γ U) -> IndHyp₁ γ U F a
induction₁ γ U F g a = \hyp -> g (IndIndex γ U a hyp) (Ind γ U a hyp)


module Oscar.Class.Symmetry where

open import Oscar.Class.Extensionality
open import Oscar.Function
open import Oscar.Level

record Symmetry {a} {A : Set a} {ℓ} (_≤_ : A → A → Set ℓ) : Set (a ⊔ ℓ) where
  field
    ⦃ ′extensionality ⦄ : Extensionality _≤_ (λ ⋆ → flip _≤_ ⋆) id id

  symmetry : ∀ {x y} → x ≤ y → y ≤ x
  symmetry = extension (λ ⋆ → flip _≤_ ⋆)

open Symmetry ⦃ … ⦄ public hiding (′extensionality)

instance

  Symmetry⋆ : ∀
    {a} {A : Set a} {ℓ} {_≤_ : A → A → Set ℓ}
    ⦃ _ : Extensionality _≤_ (λ ⋆ → flip _≤_ ⋆) id id ⦄
    → Symmetry _≤_
  Symmetry.′extensionality Symmetry⋆ = it


module DivMod where

open import IO
open import Data.Nat
open import Data.Nat.DivMod
open import Codata.Musical.Notation
open import Data.String.Base
open import Data.Fin.Base using (toℕ)
open import Level using (0ℓ)

g : ℕ
g = 7 div 5

k : ℕ
k = toℕ (7 mod 5)

showNat : ℕ → String
showNat zero = "Z"
showNat (suc x) = "S (" ++ showNat x ++ ")"

main = run {0ℓ} (putStrLn (showNat g) >> putStrLn (showNat k))


{-# OPTIONS --universe-polymorphism #-}

open import Categories.Category

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

open Category C

open import Level

record Initial : Set (o ⊔ ℓ ⊔ e) where
  field
    ⊥ : Obj
    ! : ∀ {A} → (⊥ ⇒ 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


{-

The naive, but incorrect, way to define the integers as a HIT.

This file mainly contains a proof that IsoInt ≢ Int, and ends with a
 demonstration of how the same proof strategy fails for BiInvInt.

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

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

open import Cubical.Data.Int
open import Cubical.Data.Nat
open import Cubical.Data.Empty

open import Cubical.Relation.Nullary

data IsoInt : Type₀ where
  zero : IsoInt
  suc : IsoInt -> IsoInt

  -- suc is an isomorphism:
  pred : IsoInt -> IsoInt
  suc-pred : ∀ z -> suc (pred z) ≡ z
  pred-suc : ∀ z -> pred (suc z) ≡ z

suc-iso : Iso IsoInt IsoInt
suc-iso = record { fun = suc ; inv = pred ; rightInv = suc-pred ; leftInv = pred-suc }

-- this submodule is adapted from Section 5 of
--  http://www.cs.ru.nl/~herman/PUBS/HIT-programming.pdf

module NonTrivial where

  -- these two paths are distinct!
  p₁ p₂ : Path IsoInt (suc (pred (suc zero))) (suc zero)
  p₁ i = suc-pred (suc zero) i
  p₂ i = suc (pred-suc zero i)

  -- to prove this we map into S¹, sending p₁ to refl and p₂ to loop

  open import Cubical.HITs.S1

  toS¹ : IsoInt → S¹
  toS¹ zero           = base
  toS¹ (suc x)        = toS¹ x
  toS¹ (pred x)       = toS¹ x
  toS¹ (suc-pred x i) = refl {x = toS¹ x} i
  toS¹ (pred-suc x i) = rotLoop (toS¹ x) i

  p₁≡refl : cong toS¹ p₁ ≡ refl
  p₁≡refl = refl

  p₂≡loop : cong toS¹ p₂ ≡ loop
  p₂≡loop = refl

  -- this is enough to show that p₁ and p₂ cannot be equal
  p₁≢p₂ : ¬ (p₁ ≡ p₂)
  p₁≢p₂ eq = znots 0≡1
    where -- using winding numbers, p₁ ≡ p₂ implies 0 ≡ 1
          0≡1 : 0 ≡ 1
          0≡1 = injPos (cong (winding ∘ cong toS¹) eq)

¬isSet-IsoInt : ¬ (isSet IsoInt)
¬isSet-IsoInt pf = NonTrivial.p₁≢p₂ (pf _ _ NonTrivial.p₁ NonTrivial.p₂)

¬Int≡IsoInt : ¬ (Int ≡ IsoInt)
¬Int≡IsoInt p = ¬isSet-IsoInt (subst isSet p isSetInt)

private

  -- Note: this same proof strategy fails for BiInvInt!

  open import Cubical.HITs.Ints.BiInvInt hiding (zero; suc; pred; suc-pred; pred-suc)
  import Cubical.HITs.Ints.BiInvInt as BiI

  p₁ p₂ : Path BiInvInt (BiI.suc (BiI.pred (BiI.suc BiI.zero))) (BiI.suc BiI.zero)
  p₁ i = BiI.suc-pred (BiI.suc BiI.zero) i
  p₂ i = BiI.suc (BiI.pred-suc BiI.zero i)

  open import Cubical.HITs.S1

  toS¹ : BiInvInt → S¹
  toS¹ BiI.zero            = base
  toS¹ (BiI.suc x)         = toS¹ x
  toS¹ (BiI.predr x)       = toS¹ x
  toS¹ (BiI.predl x)       = toS¹ x
  toS¹ (BiI.suc-predr x i) = refl {x = toS¹ x} i
  toS¹ (BiI.predl-suc x i) = rotLoop (toS¹ x) i

  -- still p₂ maps to loop...
  p₂≡loop : cong toS¹ p₂ ≡ loop
  p₂≡loop = refl

  open import Cubical.Foundations.GroupoidLaws

  -- ...but now so does p₁!
  p₁≡loop : cong toS¹ p₁ ≡ loop
  p₁≡loop = sym (decodeEncode base (cong toS¹ p₁)) ∙ sym (lUnit loop)

  -- if we use BiI.predr instead of BiI.pred (≡ BiI.predl) in p₁ and p₂,
  --  both paths in S¹ are refl


{-# OPTIONS --cubical --safe #-}
module Cubical.Foundations.FunExtEquiv where

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

private
  variable
    ℓ ℓ₁ ℓ₂ ℓ₃ : Level

-- Function extensionality is an equivalence
module _ {A : Type ℓ} {B : A → Type ℓ₁} {f g : (x : A) → B x} where
  private
    fib : (p : f ≡ g) → fiber funExt p
    fib p = (funExt⁻ p , refl)

    funExt-fiber-isContr : (p : f ≡ g) → (fi : fiber funExt p) → fib p ≡ fi
    funExt-fiber-isContr p (h , eq) i = (funExt⁻ (eq (~ i)) , λ j → eq (~ i ∨ j))

  funExt-isEquiv : isEquiv funExt
  equiv-proof funExt-isEquiv p = (fib p , funExt-fiber-isContr p)

  funExtEquiv : (∀ x → f x ≡ g x) ≃ (f ≡ g)
  funExtEquiv = (funExt {B = B} , funExt-isEquiv)

  funExtPath : (∀ x → f x ≡ g x) ≡ (f ≡ g)
  funExtPath = ua funExtEquiv

-- Function extensionality for binary functions
funExt₂ : {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
            {f g : (x : A) → (y : B x) → C x y}
          → ((x : A) (y : B x) → f x y ≡ g x y) → f ≡ g
funExt₂ p i x y = p x y i

-- Function extensionality for binary functions is an equivalence
module _ {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
         {f g : (x : A) → (y : B x) → C x y} where
  private
    appl₂ : f ≡ g → ∀ x y → f x y ≡ g x y
    appl₂ eq x y i = eq i x y

    fib : (p : f ≡ g) → fiber funExt₂ p
    fib p = (appl₂ p , refl)

    funExt₂-fiber-isContr : (p : f ≡ g) → (fi : fiber funExt₂ p) → fib p ≡ fi
    funExt₂-fiber-isContr p (h , eq) i = (appl₂ (eq (~ i)) , λ j → eq (~ i ∨ j))

  funExt₂-isEquiv : isEquiv funExt₂
  equiv-proof funExt₂-isEquiv p = (fib p , funExt₂-fiber-isContr p)

  funExt₂Equiv : (∀ x y → f x y ≡ g x y) ≃ (f ≡ g)
  funExt₂Equiv = (funExt₂ , funExt₂-isEquiv)

  funExt₂Path : (∀ x y → f x y ≡ g x y) ≡ (f ≡ g)
  funExt₂Path = ua funExt₂Equiv

-- Function extensionality for ternary functions
funExt₃ : {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
          {D : (x : A) → (y : B x) → C x y → Type ℓ₃}
          {f g : (x : A) → (y : B x) → (z : C x y) → D x y z}
        → ((x : A) (y : B x) (z : C x y) → f x y z ≡ g x y z) → f ≡ g
funExt₃ p i x y z = p x y z i

-- Function extensionality for ternary functions is an equivalence
module _ {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
         {D : (x : A) → (y : B x) → C x y → Type ℓ₃}
         {f g : (x : A) → (y : B x) → (z : C x y) → D x y z} where
  private
    appl₃ : f ≡ g → ∀ x y z → f x y z ≡ g x y z
    appl₃ eq x y z i = eq i x y z

    fib : (p : f ≡ g) → fiber funExt₃ p
    fib p = (appl₃ p , refl)

    funExt₃-fiber-isContr : (p : f ≡ g) → (fi : fiber funExt₃ p) → fib p ≡ fi
    funExt₃-fiber-isContr p (h , eq) i = (appl₃ (eq (~ i)) , λ j → eq (~ i ∨ j))

  funExt₃-isEquiv : isEquiv funExt₃
  equiv-proof funExt₃-isEquiv p = (fib p , funExt₃-fiber-isContr p)

  funExt₃Equiv : (∀ x y z → f x y z ≡ g x y z) ≃ (f ≡ g)
  funExt₃Equiv = (funExt₃ , funExt₃-isEquiv)

  funExt₃Path : (∀ x y z → f x y z ≡ g x y z) ≡ (f ≡ g)
  funExt₃Path = ua funExt₃Equiv

-- Puzzle: Can one generalize this to n-ary functions?


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

open import LogicalFormulae
open import Groups.Abelian.Definition
open import Groups.Homomorphisms.Definition
open import Setoids.Setoids
open import Sets.EquivalenceRelations
open import Rings.Definition
open import Lists.Lists
open import Rings.Homomorphisms.Definition

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

open Ring R
open Setoid S
open Equivalence eq
open import Groups.Polynomials.Group additiveGroup
open import Groups.Polynomials.Definition additiveGroup
open import Rings.Polynomial.Multiplication R

polyRing : Ring naivePolySetoid _+P_ _*P_
Ring.additiveGroup polyRing = polyGroup
Ring.*WellDefined polyRing {a} {b} {c} {d} = *PwellDefined {a} {b} {c} {d}
Ring.1R polyRing = 1R :: []
Ring.groupIsAbelian polyRing {x} {y} = AbelianGroup.commutative (abelian (record { commutative = Ring.groupIsAbelian R })) {x} {y}
Ring.*Associative polyRing {a} {b} {c} = *Passoc {a} {b} {c}
Ring.*Commutative polyRing {a} {b} = p*Commutative {a} {b}
Ring.*DistributesOver+ polyRing {a} {b} {c} = *Pdistrib {a} {b} {c}
Ring.identIsIdent polyRing {a} = *Pident {a}

polyInjectionIsHom : RingHom R polyRing polyInjection
RingHom.preserves1 polyInjectionIsHom = reflexive ,, record {}
RingHom.ringHom polyInjectionIsHom = reflexive ,, (reflexive ,, record {})
GroupHom.groupHom (RingHom.groupHom polyInjectionIsHom) = reflexive ,, record {}
GroupHom.wellDefined (RingHom.groupHom polyInjectionIsHom) = SetoidInjection.wellDefined polyInjectionIsInj


------------------------------------------------------------------------------
-- Group theory base
------------------------------------------------------------------------------

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

module GroupTheory.Base where

infix  8 _⁻¹
infixl 7 _·_

------------------------------------------------------------------------------
-- First-order logic with equality.
open import Common.FOL.FOL-Eq public renaming ( D to G )

-- Group theory axioms
postulate
  ε   : G          -- The identity element.
  _·_ : G → G → G  -- The binary operation.
  _⁻¹ : G → G      -- The inverse function.

  -- We choose a non-redundant set of axioms. See for example (Mac
  -- Lane and Garret 1999, exercises 5-7, p. 50-51, or Hodges 1993,
  -- p. 37).
  assoc         : ∀ a b c → a · b · c ≡ a · (b · c)
  leftIdentity  : ∀ a → ε · a         ≡ a
  leftInverse   : ∀ a → a ⁻¹ · a      ≡ ε
{-# ATP axioms assoc leftIdentity leftInverse #-}

------------------------------------------------------------------------------
-- References
--
-- Hodges, W. (1993). Model Theory. Vol. 42. Encyclopedia of
-- Mathematics and its Applications. Cambridge University Press.
--
-- Mac Lane, S. and Birkhof, G. (1999). Algebra. 3rd ed. AMS Chelsea
-- Publishing.


module regular-star where

open import Level renaming ( suc to Suc ; zero to Zero )
open import Data.List
open import Data.Nat hiding ( _≟_ )
open import Data.Fin hiding ( _+_ )
open import Data.Empty
open import Data.Unit
open import Data.Product
-- open import Data.Maybe
open import  Relation.Nullary
open import  Relation.Binary.PropositionalEquality hiding ( [_] )
open import logic
open import nat
open import automaton
open import regular-language

open import nfa
open import sbconst2
open import finiteSet
open import finiteSetUtil
open import Relation.Binary.PropositionalEquality hiding ( [_] )
open import regular-concat

open Automaton
open FiniteSet

open RegularLanguage

Star-NFA :  {Σ : Set} → (A : RegularLanguage Σ ) → NAutomaton (states A ) Σ
Star-NFA {Σ} A  = record { Nδ = δnfa ; Nend = nend }
   module Star-NFA where
       δnfa : states A → Σ → states A → Bool
       δnfa q i q₁ with aend (automaton A) q
       ... | true = equal? (afin A) ( astart A) q₁
       ... | false = equal? (afin A) (δ (automaton A) q i) q₁
       nend : states A → Bool
       nend q = aend (automaton A) q

Star-NFA-start :  {Σ : Set} → (A : RegularLanguage Σ ) → states A  → Bool
Star-NFA-start A q = equal? (afin A) (astart A) q \/  aend (automaton A) q

SNFA-exist : {Σ : Set} → (A : RegularLanguage Σ ) → (states A → Bool) → Bool
SNFA-exist A qs = exists (afin A) qs

M-Star : {Σ : Set} → (A : RegularLanguage Σ ) → RegularLanguage Σ
M-Star {Σ} A  = record {
       states = states A  → Bool
     ; astart = Star-NFA-start A
     ; afin = fin→  (afin A)
     ; automaton = subset-construction (SNFA-exist A ) (Star-NFA A )
   }

open Split

open _∧_

open NAutomaton
open import Data.List.Properties

closed-in-star :  {Σ : Set} → (A B : RegularLanguage Σ ) → ( x : List Σ ) → isRegular (Star (contain A) ) x ( M-Star A  )
closed-in-star {Σ} A B x = ≡-Bool-func closed-in-star→ closed-in-star← where
    NFA = (Star-NFA A )

    closed-in-star→ : Star (contain A)  x ≡ true → contain (M-Star A ) x ≡ true
    closed-in-star→ star = {!!}

    open Found

    closed-in-star← : contain (M-Star A ) x ≡ true → Star (contain A)  x ≡ true
    closed-in-star← C with subset-construction-lemma← (SNFA-exist A ) NFA {!!} x C
    ... | CC = {!!}


-- Copyright:  (c) 2016 Ertugrul Söylemez
-- License:    BSD3
-- Maintainer: Ertugrul Söylemez <esz@posteo.de>

module Data.Int where

open import Algebra.Group
open import Classes
open import Core
open import Data.Int.Core
open import Data.Int.Core public
  using (ℤ; ℤ-Negative; ℤ-Number; negsuc; pos)

ℤ,+ : Group
ℤ,+ =
  record {
    semigroup = record {
      A = ℤ;
      Eq = PropEq ℤ;
      semigroupOver = record {
        _⋄_ = _+_;
        ⋄-cong = cong2 _+_;
        assoc = Props.+-assoc
      }
    };
    isGroup = record {
      isMonoid = record {
        id = 0;
        left-id = Props.+-left-id;
        right-id = Props.+-right-id
      };
      iso = λ x → record {
        inv = neg x;
        left-inv = Props.+-left-inv x;
        right-inv = Props.+-right-inv x
      };
      inv-cong = cong neg
    }
  }

ℤ,* : Monoid
ℤ,* =
  record {
    semigroup = record {
      A = ℤ;
      Eq = PropEq ℤ;
      semigroupOver = record {
        _⋄_ = _*_;
        ⋄-cong = cong2 _*_;
        assoc = Props.*-assoc
      }
    };
    isMonoid = record {
      id = 1;
      left-id = Props.*-left-id;
      right-id = Props.*-right-id
    }
  }


------------------------------------------------------------------------
-- The Agda standard library
--
-- Coprimality
------------------------------------------------------------------------

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

module Data.Integer.Coprimality where

open import Data.Integer
open import Data.Integer.Divisibility
open import Data.Integer.Properties
import Data.Nat.Coprimality as ℕ
import Data.Nat.Divisibility as ℕ
open import Function using (_on_)
open import Level using (0ℓ)
open import Relation.Binary using (Rel; Decidable; Symmetric)
open import Relation.Binary.PropositionalEquality using (subst)

------------------------------------------------------------------------
-- Definition

Coprime : Rel ℤ 0ℓ
Coprime = ℕ.Coprime on ∣_∣

------------------------------------------------------------------------
-- Properties of coprimality

sym : Symmetric Coprime
sym = ℕ.sym

coprime? : Decidable Coprime
coprime? x y = ℕ.coprime? ∣ x ∣ ∣ y ∣

coprime-divisor : ∀ i j k → Coprime i j → i ∣ j * k → i ∣ k
coprime-divisor i j k c eq =
  ℕ.coprime-divisor c (subst (∣ i ∣ ℕ.∣_ ) (abs-*-commute j k) eq)


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

open import Equivalence
open import NTypes.Contractible
open import PathOperations
open import Types

fib : ∀ {a b} {A : Set a} {B : Set b}
  (f : A → B) (y : B) →
  Set _
fib {A = A} f y = Σ A λ x → f x ≡ y

fib→dom : ∀ {a b} {A : Set a} {B : Set b} (f : A → B) →
  Σ B (fib f) → A
fib→dom f (b , a , p) = a

dom→fib : ∀ {a b} {A : Set a} {B : Set b} (f : A → B) →
  A → Σ B (fib f)
dom→fib f a = f a , a , refl

fib-dom-eq :  ∀ {a b} {A : Set a} {B : Set b} (f : A → B) →
  Σ B (fib f) ≃ A
fib-dom-eq {A = A} {B = B} f
  = fib→dom f
  , (dom→fib f , λ _ → refl)
  , (dom→fib f , λ {(b , a , p) →
      ap (swap ∘ _,_ a) (π₂ (pp-space-contr (f a)) (b , p))})
  where
  swap : (Σ A λ x → Σ B λ y → f x ≡ y) → Σ B (fib f)
  swap (b , a , p) = a , b , p


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

open import LogicalFormulae
open import Lists.Definition
open import Lists.Fold.Fold
open import Lists.Concat
open import Lists.Length
open import Numbers.Naturals.Semiring

module Lists.Monad where

open import Lists.Map.Map public

flatten : {a : _} {A : Set a} → (l : List (List A)) → List A
flatten [] = []
flatten (l :: ls) = l ++ flatten ls

flatten' : {a : _} {A : Set a} → (l : List (List A)) → List A
flatten' = fold _++_ []

flatten=flatten' : {a : _} {A : Set a} (l : List (List A)) → flatten l ≡ flatten' l
flatten=flatten' [] = refl
flatten=flatten' (l :: ls) = applyEquality (l ++_) (flatten=flatten' ls)

lengthFlatten : {a : _} {A : Set a} (l : List (List A)) → length (flatten l) ≡ (fold _+N_ zero (map length l))
lengthFlatten [] = refl
lengthFlatten (l :: ls) rewrite lengthConcat l (flatten ls) | lengthFlatten ls = refl

flattenConcat : {a : _} {A : Set a} (l1 l2 : List (List A)) → flatten (l1 ++ l2) ≡ (flatten l1) ++ (flatten l2)
flattenConcat [] l2 = refl
flattenConcat (l1 :: ls) l2 rewrite flattenConcat ls l2 | concatAssoc l1 (flatten ls) (flatten l2) = refl

pure : {a : _} {A : Set a} → A → List A
pure a = [ a ]

bind : {a b : _} {A : Set a} {B : Set b} → (f : A → List B) → List A → List B
bind f l = flatten (map f l)

private
  leftIdentLemma : {a : _} {A : Set a} (xs : List A) → flatten (map pure xs) ≡ xs
  leftIdentLemma [] = refl
  leftIdentLemma (x :: xs) rewrite leftIdentLemma xs = refl

leftIdent : {a b : _} {A : Set a} {B : Set b} → (f : A → List B) → {x : A} → bind pure (f x) ≡ f x
leftIdent f {x} with f x
leftIdent f {x} | [] = refl
leftIdent f {x} | y :: ys rewrite leftIdentLemma ys = refl

rightIdent : {a b : _} {A : Set a} {B : Set b} → (f : A → List B) → {x : A} → bind f (pure x) ≡ f x
rightIdent f {x} with f x
rightIdent f {x} | [] = refl
rightIdent f {x} | y :: ys rewrite appendEmptyList ys = refl

associative : {a b c : _} {A : Set a} {B : Set b} {C : Set c} → (f : A → List B) (g : B → List C) → {x : List A} → bind g (bind f x) ≡ bind (λ a → bind g (f a)) x
associative f g {[]} = refl
associative f g {x :: xs} rewrite mapConcat (f x) (flatten (map f xs)) g | flattenConcat (map g (f x)) (map g (flatten (map f xs))) = applyEquality (flatten (map g (f x)) ++_) (associative f g {xs})


-- Minimal implicational logic, vector-based de Bruijn approach, initial encoding

module Vi.ArrMp where

open import Lib using (Nat; suc; _+_; Fin; fin; Vec; _,_; proj; VMem; mem)

-- Types

infixr 0 _=>_
data Ty : Set where
  UNIT :             Ty
  _=>_ : Ty -> Ty -> Ty

-- Context and truth judgement

Cx : Nat -> Set
Cx n = Vec Ty n

isTrue : forall {tn} -> Ty -> Fin tn -> Cx tn -> Set
isTrue a i tc = VMem a i tc

-- Terms

module ArrMp where
  infixr 0 lam=>_
  infixl 1 _$_
  data Tm {tn} (tc : Cx tn) : Ty -> Set where
    var    : forall {a i} -> isTrue a i tc             -> Tm tc a
    lam=>_ : forall {a b} -> Tm (tc , a) b             -> Tm tc (a => b)
    _$_    : forall {a b} -> Tm tc (a => b) -> Tm tc a -> Tm tc b

  v : forall {tn} (k : Nat) {tc : Cx (suc (k + tn))} -> Tm tc (proj tc (fin k))
  v i = var (mem i)

  Thm : Ty -> Set
  Thm a = forall {tn} {tc : Cx tn} -> Tm tc a
open ArrMp public

-- Example theorems

aI : forall {a} -> Thm (a => a)
aI =
  lam=> v 0

aK : forall {a b} -> Thm (a => b => a)
aK =
  lam=>
    lam=> v 1

aS : forall {a b c} -> Thm ((a => b => c) => (a => b) => a => c)
aS =
  lam=>
    lam=>
      lam=> v 2 $ v 0 $ (v 1 $ v 0)

tSKK : forall {a} -> Thm (a => a)
tSKK {a = a} =
  aS {b = a => a} $ aK $ aK


------------------------------------------------------------------------------
-- Axiomatic Peano arithmetic using Agsy
------------------------------------------------------------------------------

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

module FOT.Agsy.AxiomaticPA where

open import Common.FOL.FOL public renaming ( D to ℕ )

infixl 10 _*_
infix  7  _≐_
infixl 9  _+_

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

-- Non-logical constants
postulate
  zero : ℕ
  succ : ℕ → ℕ
  _+_  : ℕ → ℕ → ℕ
  _*_  : ℕ → ℕ → ℕ
  _≐_  : ℕ → ℕ → Set

-- Proper axioms
-- (From Elliott Mendelson. Introduction to mathematical
-- logic. Chapman & Hall, 4th edition, 1997, p. 155)

-- N.B. We make the recursion in the first argument for _+_ and _*_.

-- S₁. m = n → m = o → n = o
-- S₂. m = n → succ m = succ n
-- S₃. 0 ≠ succ n
-- S₄. succ m = succ n → m = n
-- S₅. 0 + n = n
-- S₆. succ m + n = succ (m + n)
-- S₇. 0 * n = 0
-- S₈. succ m * n = (m * n) + m
-- S₉. P(0) → (∀n.P(n) → P(succ n)) → ∀n.P(n), for any wf P(n) of PA.

postulate
  S₁ : {m n o : ℕ} → m ≐ n → m ≐ o → n ≐ o
  S₂ : ∀ {m n} → m ≐ n → succ m ≐ succ n
  S₃ : ∀ {n} → ¬ (zero ≐ succ n)
  S₄ : ∀ {m n} → succ m ≐ succ n → m ≐ n
  S₅ : ∀ n →   zero   + n ≐ n
  S₆ : ∀ m n → succ m + n ≐ succ (m + n)
  S₇ : ∀ n →   zero   * n ≐ zero
  S₈ : ∀ m n → succ m * n ≐ n + m * n
  S₉ : (A : ℕ → Set) → A zero → (∀ n → A n → A (succ n)) → ∀ n → A n

-- Properties

refl : ∀ {n} → n ≐ n
refl {n} = S₁ (S₅ n) (S₅ n) -- Via Agsy {-m}

sym : ∀ {m n} → m ≐ n → n ≐ m
sym h = S₁ h refl  -- Via Agsy {-m}

trans : ∀ {m n o} → m ≐ n → n ≐ o → m ≐ o
trans h₁ h₂ = S₁ (sym h₁) h₂  -- Via Agsy {-m}

+-rightIdentity : ∀ n → n + zero ≐ n
+-rightIdentity n = {!-t 20 -m!}  -- Agsy fails


import      Lvl
open import Structure.Setoid
open import Type

module Structure.Operator.Vector.Subspaces.Kernel
  {ℓₛ ℓₛₑ}
  {S : Type{ℓₛ}}
  ⦃ equiv-S : Equiv{ℓₛₑ}(S) ⦄
  {_+ₛ_ _⋅ₛ_ : S → S → S}
  where

open import Logic.Predicate
open import Sets.ExtensionalPredicateSet as PredSet using (PredSet ; _∈_ ; [∋]-binaryRelator)
open import Structure.Container.SetLike as SetLike using (SetElement)
open import Structure.Function.Multi
open import Structure.Operator
open import Structure.Operator.Properties
open import Structure.Operator.Vector
open import Structure.Operator.Vector.LinearMap
open import Structure.Operator.Vector.Proofs
open import Structure.Operator.Vector.Subspace
open import Structure.Relator.Properties
open import Syntax.Implication
open import Syntax.Transitivity

open VectorSpace ⦃ … ⦄
open VectorSpaceVObject ⦃ … ⦄ using (_+ᵥ_; _⋅ₛᵥ_)
open VectorSpaceVObject       using (Vector)

private variable ℓ ℓᵥ ℓᵥₑ : Lvl.Level
private variable V W : VectorSpaceVObject {ℓᵥ = ℓᵥ} {ℓᵥₑ = ℓᵥₑ} ⦃ equiv-S = equiv-S ⦄ (_+ₛ_)(_⋅ₛ_)
private variable F : V →ˡⁱⁿᵉᵃʳᵐᵃᵖ W

kernel : (V →ˡⁱⁿᵉᵃʳᵐᵃᵖ W) → PredSet(Vector(V))
kernel {V = V}{W = W} ([∃]-intro f) = PredSet.unapply f(𝟎ᵥ)

kernel-subspace : Subspace(kernel(F))
SetLike.FunctionProperties._closed-under₂_.proof (Subspace.add-closure (kernel-subspace {_} {_} {V} {_} {_} {W} {F = F@([∃]-intro f)})) {x} {y} xkern ykern =
  • (
    xkern         ⇒
    x ∈ kernel(F) ⇒-[]
    f(x) ≡ 𝟎ᵥ     ⇒-end
  )
  • (
    ykern         ⇒
    y ∈ kernel(F) ⇒-[]
    f(y) ≡ 𝟎ᵥ     ⇒-end
  )                       ⇒₂-[ congruence₂{A₁ = Vector(W)}{A₂ = Vector(W)}(_+ᵥ_) ]
  f(x) +ᵥ f(y) ≡ 𝟎ᵥ +ᵥ 𝟎ᵥ ⇒-[ _🝖 identityᵣ(_+ᵥ_)(𝟎ᵥ) ]
  f(x) +ᵥ f(y) ≡ 𝟎ᵥ       ⇒-[ preserving₂(f)(_+ᵥ_)(_+ᵥ_) 🝖_ ]
  f(x +ᵥ y) ≡ 𝟎ᵥ          ⇒-[]
  (x +ᵥ y) ∈ kernel(F)    ⇒-end
  where
    instance _ = V
    instance _ = W
SetLike.FunctionProperties._closed-under₁_.proof (Subspace.mul-closure (kernel-subspace {_}{_}{V}{_}{_}{W} {F = F@([∃]-intro f)}) {s}) {v} vkern =
  vkern ⇒
  v ∈ kernel(F)         ⇒-[]
  f(v) ≡ 𝟎ᵥ             ⇒-[ congruence₂ᵣ(_⋅ₛᵥ_)(s) ]
  s ⋅ₛᵥ f(v) ≡ s ⋅ₛᵥ 𝟎ᵥ ⇒-[ _🝖 [⋅ₛᵥ]-absorberᵣ ]
  s ⋅ₛᵥ f(v) ≡ 𝟎ᵥ       ⇒-[ preserving₁(f)(s ⋅ₛᵥ_)(s ⋅ₛᵥ_) 🝖_ ]
  f(s ⋅ₛᵥ v) ≡ 𝟎ᵥ       ⇒-[]
  (s ⋅ₛᵥ v) ∈ kernel(F) ⇒-end
  where
    instance _ = V
    instance _ = W


------------------------------------------------------------------------------
-- Conversion functions i, j and k.
------------------------------------------------------------------------------

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

module FOT.FOTC.IJK where

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

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

data ℕ : Set where
  z : ℕ
  s : ℕ → ℕ

-- Conversion functions from/to ℕ and N.
i : ℕ → D
i z     = zero
i (s n) = succ₁ (i n)

j : (n : ℕ) → N (i n)
j z     = nzero
j (s n) = nsucc (j n)

k : {n : D} → N n → ℕ
k nzero      = z
k (nsucc Nn) = s (k Nn)

_+_ : ℕ → ℕ → ℕ
z   + n = n
s m + n = s (m + n)


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

open import M-types.Base.Core
open import M-types.Base.Sum
open import M-types.Base.Prod
open import M-types.Base.Eq

module M-types.Base.Equi where
    Qinv : {X : Ty ℓ₀} {Y : Ty ℓ₁} →
        ∏[ f ∈ (X → Y)] Ty (ℓ-max ℓ₀ ℓ₁)
    Qinv {_} {_} {X} {Y} f = ∑[ g ∈ (Y → X) ]
        (∏[ x ∈ X ] g (f x) ≡ x) ×
        (∏[ y ∈ Y ] f (g y) ≡ y)

    IsEqui : {X : Ty ℓ₀} {Y : Ty ℓ₁} →
        ∏[ f ∈ (X → Y) ] Ty (ℓ-max ℓ₀ ℓ₁)
    IsEqui {_} {_} {X} {Y} f =
        (∑[ g ∈ (Y → X) ] ∏[ x ∈ X ] g (f x) ≡ x) ×
        (∑[ g ∈ (Y → X) ] ∏[ y ∈ Y ] f (g y) ≡ y)

    infixr 8 _≃_
    _≃_ : ∏[ X ∈ Ty ℓ₀ ] ∏[ Y ∈ Ty ℓ₁ ] Ty (ℓ-max ℓ₀ ℓ₁)
    X ≃ Y = ∑[ f ∈ (X → Y) ] IsEqui f

    Qinv→IsEqui : {X : Ty ℓ₀} {Y : Ty ℓ₁} {f : X → Y} →
        Qinv f → IsEqui f
    Qinv→IsEqui (g , hom₀ , hom₁) = ((g , hom₀) , (g , hom₁))

    IsEqui→Qinv : {X : Ty ℓ₀} {Y : Ty ℓ₁} {f : X → Y} →
        IsEqui f → Qinv f
    IsEqui→Qinv {_} {_} {_} {_} {f} ((g₀ , hom₀) , (g₁ , hom₁)) =
        (
            g₀ ,
            hom₀ ,
            λ y → ap f (ap g₀ (hom₁ y)⁻¹ · hom₀ (g₁ y)) · hom₁ y
        )

    inv : {X : Ty ℓ₀} {Y : Ty ℓ₁} →
        ∏[ equi ∈ X ≃ Y ] (Y → X)
    inv (fun , isEqui) = pr₀ (IsEqui→Qinv isEqui)

    hom₀ : {X : Ty ℓ₀} {Y : Ty ℓ₁} →
        ∏[ equi ∈ X ≃ Y ] ∏[ x ∈ X ] inv equi (fun equi x) ≡ x
    hom₀ (fun , isEqui) = pr₀ (pr₁ (IsEqui→Qinv isEqui))

    hom₁ : {X : Ty ℓ₀} {Y : Ty ℓ₁} →
        ∏[ equi ∈ X ≃ Y ] ∏[ y ∈ Y ] fun equi (inv equi y) ≡ y
    hom₁ (fun , isEqui) = pr₁ (pr₁ (IsEqui→Qinv isEqui))


------------------------------------------------------------------------------
-- Proving properties without using pattern matching on refl
------------------------------------------------------------------------------

{-# OPTIONS --no-pattern-matching #-}
{-# OPTIONS --exact-split              #-}
{-# OPTIONS --no-sized-types           #-}
{-# OPTIONS --no-universe-polymorphism #-}

module FOT.DistributiveLaws.NoPatternMatchingOnRefl where

open import DistributiveLaws.Base

------------------------------------------------------------------------------
-- From DistributiveLaws.PropertiesI

-- Congruence properties

·-leftCong : ∀ {a b c} → a ≡ b → a · c ≡ b · c
·-leftCong {a} {c = c} h = subst (λ t → a · c ≡ t · c) h refl

·-rightCong : ∀ {a b c} → b ≡ c → a · b ≡ a · c
·-rightCong {a} {b} h = subst (λ t → a · b ≡ a · t) h refl


------------------------------------------------------------------------
-- The Agda standard library
--
-- Bisimilarity for Colists
------------------------------------------------------------------------

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

module Codata.Colist.Bisimilarity where

open import Level using (Level; _⊔_)
open import Size
open import Codata.Thunk
open import Codata.Colist
open import Data.List.Base using (List; []; _∷_)
open import Data.List.Relation.Binary.Pointwise using (Pointwise; []; _∷_)
open import Data.List.NonEmpty as List⁺  using (List⁺; _∷_)
open import Relation.Binary
open import Relation.Binary.PropositionalEquality as Eq using (_≡_)

private
  variable
    a b c p q r : Level
    A : Set a
    B : Set b
    C : Set c
    i : Size

data Bisim {A : Set a} {B : Set b} (R : REL A B r) (i : Size) :
           REL (Colist A ∞) (Colist B ∞) (r ⊔ a ⊔ b) where
  []  : Bisim R i [] []
  _∷_ : ∀ {x y xs ys} → R x y → Thunk^R (Bisim R) i xs ys →
        Bisim R i (x ∷ xs) (y ∷ ys)

module _ {R : Rel A r} where

 reflexive : Reflexive R → Reflexive (Bisim R i)
 reflexive refl^R {[]}     = []
 reflexive refl^R {r ∷ rs} = refl^R ∷ λ where .force → reflexive refl^R

module _ {P : REL A B p} {Q : REL B A q} where

 symmetric : Sym P Q → Sym (Bisim P i) (Bisim Q i)
 symmetric sym^PQ []       = []
 symmetric sym^PQ (p ∷ ps) = sym^PQ p ∷ λ where .force → symmetric sym^PQ (ps .force)

module _ {P : REL A B p} {Q : REL B C q} {R : REL A C r} where

 transitive : Trans P Q R → Trans (Bisim P i) (Bisim Q i) (Bisim R i)
 transitive trans^PQR []       []       = []
 transitive trans^PQR (p ∷ ps) (q ∷ qs) =
   trans^PQR p q ∷ λ where .force → transitive trans^PQR (ps .force) (qs .force)

------------------------------------------------------------------------
-- Congruence rules

module _ {R : REL A B r} where

  ++⁺ : ∀ {as bs xs ys} → Pointwise R as bs →
        Bisim R i xs ys → Bisim R i (fromList as ++ xs) (fromList bs ++ ys)
  ++⁺ []       rs = rs
  ++⁺ (r ∷ pw) rs = r ∷ λ where .force → ++⁺ pw rs

  ⁺++⁺ : ∀ {as bs xs ys} → Pointwise R (List⁺.toList as) (List⁺.toList bs) →
         Thunk^R (Bisim R) i xs ys → Bisim R i (as ⁺++ xs) (bs ⁺++ ys)
  ⁺++⁺ (r ∷ pw) rs = r ∷ λ where .force → ++⁺ pw (rs .force)

------------------------------------------------------------------------
-- Pointwise Equality as a Bisimilarity

module _ {A : Set a} where

  infix 1 _⊢_≈_
  _⊢_≈_ : ∀ i → Colist A ∞ → Colist A ∞ → Set a
  _⊢_≈_ = Bisim _≡_

  refl : Reflexive (i ⊢_≈_)
  refl = reflexive Eq.refl

  fromEq : ∀ {as bs} → as ≡ bs → i ⊢ as ≈ bs
  fromEq Eq.refl = refl

  sym : Symmetric (i ⊢_≈_)
  sym = symmetric Eq.sym

  trans : Transitive (i ⊢_≈_)
  trans = transitive Eq.trans

isEquivalence : {R : Rel A r} → IsEquivalence R → IsEquivalence (Bisim R i)
isEquivalence equiv^R = record
  { refl  = reflexive equiv^R.refl
  ; sym   = symmetric equiv^R.sym
  ; trans = transitive equiv^R.trans
  } where module equiv^R = IsEquivalence equiv^R

setoid : Setoid a r → Size → Setoid a (a ⊔ r)
setoid S i = record
  { isEquivalence = isEquivalence {i = i} (Setoid.isEquivalence S)
  }

module ≈-Reasoning {a} {A : Set a} {i} where

  open import Relation.Binary.Reasoning.Setoid (setoid (Eq.setoid A) i) public


module map-is-foldr where

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; cong)
open Eq.≡-Reasoning
open import lists using (List; []; _∷_; map; foldr)

postulate
  -- 外延性の公理
  extensionality : ∀ {A B : Set} {f g : A → B}
    → (∀ (x : A) → f x ≡ g x)
      -----------------------
    → f ≡ g

-- 外延性の公理を利用した証明のための補題
lemma : ∀ {A B : Set} → (f : A → B) → (xs : List A)
  → map f xs ≡ foldr (λ x xs → f x ∷ xs) [] xs
lemma f [] =
  begin
    map f []
  ≡⟨⟩
    []
  ≡⟨⟩
    foldr (λ x xs → f x ∷ xs) [] []
  ∎
lemma f (x ∷ xs) =
  begin
    map f (x ∷ xs)
  ≡⟨⟩
    f x ∷ map f xs
  ≡⟨ cong (f x ∷_) (lemma f xs) ⟩
    f x ∷ foldr (λ x xs → f x ∷ xs) [] xs
  ≡⟨⟩
    foldr (λ x xs → f x ∷ xs) [] (x ∷ xs)
  ∎

-- mapが畳み込みで表現できることの証明
map-is-foldr : ∀ {A B : Set} → (f : A → B)
  → map f ≡ foldr (λ x xs → f x ∷ xs) []
map-is-foldr f = extensionality (lemma f)


open import Relation.Binary.Core using (Rel)

module GGT.Definitions
  {a b ℓ₁ ℓ₂}
  {G : Set a}      -- The underlying group carrier
  {Ω : Set b}      -- The underlying space
  (_≈_ : Rel G ℓ₁) -- The underlying group equality
  (_≋_ : Rel Ω ℓ₂) -- The underlying space equality
  where

open import Level
open import Algebra.Core
open import Relation.Unary
open import Algebra.Bundles using (Group)
open import Algebra.Definitions _≋_ using (Congruent₁)

ActAssoc : Opᵣ G Ω → Op₂ G → Set _
ActAssoc _·_ _∙_ = ∀ (o : Ω) (g : G) (h : G) → (o · (g ∙ h)) ≋ ((o · g) · h)

ActLeftIdentity : G → Opᵣ G Ω → Set _
ActLeftIdentity ε _·_ = ∀ (o : Ω) → (o · ε) ≋ o

·-≋-Congruence : Opᵣ G Ω → Set _
·-≋-Congruence _·_ = ∀ (g : G) → Congruent₁ (_· g)
-- ∀ (o1 o2 : Ω) (g : G) → o1 ≋ o2 → (o1 · g) ≋ (o2 · g)

≈-Ext : Opᵣ G Ω → Set _
≈-Ext _·_ = ∀ {g h : G} → ∀ {o : Ω} → g ≈ h → (o · g) ≋ (o · h)


-- This file is ported from a part of Martin Escardó's HoTT lecture notes
-- (https://www.cs.bham.ac.uk/~mhe/HoTT-UF-in-Agda-Lecture-Notes/HoTT-UF-Agda.html).

{-# OPTIONS --without-K --safe #-}
module Util.HoTT.Section where

open import Util.HoTT.HLevel.Core
open import Util.Prelude
open import Util.Relation.Binary.PropositionalEquality using
  ( Σ-≡⁺ ; subst-subst-sym )

private
  variable
    α β γ : Level
    A B C : Set α

infix 4 _◁_

record HasSection {A : Set α} {B : Set β} (f : A → B) : Set (α ⊔ℓ β) where
  field
    section : B → A
    isSection : ∀ x → f (section x) ≡ x

open HasSection public

record _◁_ (A : Set α) (B : Set β) : Set (α ⊔ℓ β) where
  field
    retraction : B → A
    hasSection : HasSection retraction

  open HasSection hasSection public renaming (isSection to retraction∘section)

open _◁_ public

◁-refl : A ◁ A
◁-refl = record
  { retraction = id
  ; hasSection = record
    { section = id
    ; isSection = λ _ → refl
    }
  }

◁-trans : A ◁ B → B ◁ C → A ◁ C
◁-trans A◁B B◁C = record
  { retraction = A◁B .retraction ∘ B◁C .retraction
  ; hasSection = record
    { section = B◁C .section ∘ A◁B .section
    ; isSection = λ x
        → trans (cong (A◁B .retraction) (B◁C .retraction∘section _))
            (A◁B .retraction∘section _)
    }
  }

Σ-◁ : {A : Set α} {B : A → Set β} {C : A → Set γ}
  → (∀ a → B a ◁ C a)
  → Σ A B ◁ Σ A C
Σ-◁ B◁C = record
  { retraction = λ { (a , c) → a , B◁C a .retraction c }
  ; hasSection = record
    { section = λ { (a , b) → a , B◁C a .section b }
    ; isSection = λ { (a , b) → cong (a ,_) (B◁C a .retraction∘section b) }
    }
  }

◁-pres-IsContr : A ◁ B → IsContr B → IsContr A
◁-pres-IsContr A◁B (b , canon)
  = A◁B .retraction b
  , λ a
      → trans (cong (A◁B .retraction) (canon (A◁B .section a)))
          (A◁B .retraction∘section a)

Σ-◁-reindexing : {A : Set α} {B : Set β} {P : A → Set γ}
  → (r : A ◁ B)
  → Σ A P ◁ Σ B (P ∘ r .retraction)
Σ-◁-reindexing {P = P} r = record
  { retraction = λ { (b , x) → r .retraction b , x }
  ; hasSection = record
    { section = λ where
        (a , x) → r .section a , subst P (sym (r .retraction∘section a)) x
    ; isSection = λ where
        (a , x) → Σ-≡⁺
          ( r .retraction∘section a
          , subst-subst-sym (r .retraction∘section a)
          )
    }
  }


{-

        Agda Implementors' Meeting VI

                  Göteborg
             May 24 - 3zero, 2zerozero7

                Hello Agda!

                Ulf Norell

-}

-- Records are labeled sigma types.

module R where

{-

  A very simple record.

-}

data Nat : Set where
  zero : Nat
  succ : Nat

record Point : Set where
  field x : Nat
        y : Nat

-- A record can be seen as a one constructor datatype. In this case:
data Point' : Set where
  mkPoint : (x : Nat)(y : Nat) -> Point'

-- There are a few differences, though:

-- To construct a record you use the syntax record { ..; x = e; .. }
origin : Point
origin = record { x = zero; y = zero }

-- instead of
origin' : Point'
origin' = mkPoint zero zero

-- What's more interesting is that you get projection functions
-- for free when you declare a record. More precisely, you get a module
-- parameterised over a record, containing functions corresponding to the
-- fields. In the Point example you get:
{-
  module Point (p : Point) where
    x : Nat
    y : Nat
-}

-- So Point.x : Point -> Nat is the projection function for the field x.
getX : Point -> Nat
getX = Point.x
-- getX = x


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

-- slice category (https://ncatlab.org/nlab/show/over+category)
-- TODO: Forgetful Functor from Slice to 𝒞
module Categories.Category.Slice {o ℓ e} (𝒞 : Category o ℓ e) where

open Category 𝒞
open HomReasoning

open import Level
open import Function using (_$_)
open import Relation.Binary using (Rel)

open import Categories.Morphism.Reasoning 𝒞

record SliceObj (X : Obj) : Set (o ⊔ ℓ) where
  constructor sliceobj
  field
    {Y} : Obj
    arr : Y ⇒ X

private
  variable
    A : Obj
    X Y Z : SliceObj A

record Slice⇒ {A : Obj} (X Y : SliceObj A) : Set (ℓ ⊔ e) where
  constructor slicearr
  module X = SliceObj X
  module Y = SliceObj Y
  field
    {h} : X.Y ⇒ Y.Y
    △   : Y.arr ∘ h ≈ X.arr

Slice : Obj → Category _ _ _
Slice A       = record
  { Obj       = SliceObj A
  ; _⇒_       = Slice⇒
  ; _≈_       = λ where
    (slicearr {f} _) (slicearr {g} _) → f ≈ g
  ; id        = slicearr identityʳ
  ; _∘_       = _∘′_
  ; assoc     = assoc
  ; sym-assoc = sym-assoc
  ; identityˡ = identityˡ
  ; identityʳ = identityʳ
  ; identity² = identity²
  ; equiv     = record -- must be expanded to get levels to work out
    { refl  = refl
    ; sym   = sym
    ; trans = trans
    }
  ; ∘-resp-≈  = ∘-resp-≈
  }
  where _∘′_ : Slice⇒ Y Z → Slice⇒ X Y → Slice⇒ X Z
        _∘′_ {Y = sliceobj y} {Z = sliceobj z} {X = sliceobj x} (slicearr {g} △) (slicearr {f} △′) = slicearr $ begin
          z ∘ g ∘ f ≈⟨ pullˡ △ ⟩
          y ∘ f     ≈⟨ △′ ⟩
          x         ∎


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

open import Functions.Definition
open import LogicalFormulae
open import Numbers.Naturals.Definition
open import Sets.FinSet.Definition
open import Sets.FinSet.Lemmas

module Sets.Cardinality.Finite.Lemmas where

finsetInjectIntoℕ : {n : ℕ} → Injection (toNat {n})
finsetInjectIntoℕ {zero} {()}
finsetInjectIntoℕ {succ n} = ans
  where
    ans : {n : ℕ} → {x y : FinSet (succ n)} → (toNat x ≡ toNat y) → x ≡ y
    ans {zero} {fzero} {fzero} _ = refl
    ans {zero} {fzero} {fsucc ()}
    ans {zero} {fsucc ()} {y}
    ans {succ n} {fzero} {fzero} pr = refl
    ans {succ n} {fzero} {fsucc y} ()
    ans {succ n} {fsucc x} {fzero} ()
    ans {succ n} {fsucc x} {fsucc y} pr with succInjective pr
    ... | pr' = applyEquality fsucc (ans {n} {x} {y} pr')


------------------------------------------------------------------------
-- The Agda standard library
--
-- Properties satisfied by posets
------------------------------------------------------------------------

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

open import Relation.Binary

module Relation.Binary.Properties.Poset
   {p₁ p₂ p₃} (P : Poset p₁ p₂ p₃) where

open Poset P renaming (Carrier to A)

open import Function using (flip)
import Relation.Binary.Construct.NonStrictToStrict _≈_ _≤_ as ToStrict
import Relation.Binary.Properties.Preorder preorder as PreorderProperties
open import Relation.Nullary using (¬_)

private
  _≉_ : Rel A p₂
  x ≉ y = ¬ (x ≈ y)

------------------------------------------------------------------------
-- The _≥_ relation is also a poset.

infix 4 _≥_

_≥_ : Rel A p₃
x ≥ y = y ≤ x

open PreorderProperties public
  using ()
  renaming
  ( invIsPreorder to ≥-isPreorder
  ; invPreorder   to ≥-preorder
  )

≥-isPartialOrder : IsPartialOrder _≈_ _≥_
≥-isPartialOrder = record
  { isPreorder   = PreorderProperties.invIsPreorder
  ; antisym      = flip antisym
  }

≥-poset : Poset p₁ p₂ p₃
≥-poset = record
  { isPartialOrder = ≥-isPartialOrder
  }

open Poset ≥-poset public
  using ()
  renaming
  ( refl      to ≥-refl
  ; reflexive to ≥-reflexive
  ; trans     to ≥-trans
  ; antisym   to ≥-antisym
  )

------------------------------------------------------------------------
-- Partial orders can be turned into strict partial orders

infix 4 _<_

_<_ : Rel A _
_<_ = ToStrict._<_

<-isStrictPartialOrder : IsStrictPartialOrder _≈_ _<_
<-isStrictPartialOrder = ToStrict.<-isStrictPartialOrder isPartialOrder

<-strictPartialOrder : StrictPartialOrder _ _ _
<-strictPartialOrder = record
  { isStrictPartialOrder = <-isStrictPartialOrder
  }

open StrictPartialOrder <-strictPartialOrder public
  using ( <-resp-≈; <-respʳ-≈; <-respˡ-≈)
  renaming
  ( irrefl to <-irrefl
  ; asym   to <-asym
  ; trans  to <-trans
  )

<⇒≉ : ∀ {x y} → x < y → x ≉ y
<⇒≉ = ToStrict.<⇒≉

≤∧≉⇒< : ∀ {x y} → x ≤ y → x ≉ y → x < y
≤∧≉⇒< = ToStrict.≤∧≉⇒<

<⇒≱ : ∀ {x y} → x < y → ¬ (y ≤ x)
<⇒≱ = ToStrict.<⇒≱ antisym

≤⇒≯ : ∀ {x y} → x ≤ y → ¬ (y < x)
≤⇒≯ = ToStrict.≤⇒≯ antisym

------------------------------------------------------------------------
-- DEPRECATED NAMES
------------------------------------------------------------------------
-- Please use the new names as continuing support for the old names is
-- not guaranteed.

-- Version 1.2

invIsPartialOrder = ≥-isPartialOrder
{-# WARNING_ON_USAGE invIsPartialOrder
"Warning: invIsPartialOrder was deprecated in v1.2.
Please use ≥-isPartialOrder instead."
#-}

invPoset = ≥-poset
{-# WARNING_ON_USAGE invPoset
"Warning: invPoset was deprecated in v1.2.
Please use ≥-poset instead."
#-}

strictPartialOrder = <-strictPartialOrder
{-# WARNING_ON_USAGE strictPartialOrder
"Warning: strictPartialOrder was deprecated in v1.2.
Please use <-strictPartialOrder instead."
#-}


{-# OPTIONS --cubical --no-import-sorts --safe #-}
module Cubical.Algebra.Magma.Properties 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.Algebra.Magma.MorphismProperties public
  using (MagmaPath; uaMagma; carac-uaMagma; Magma≡; caracMagma≡)

private
  variable
    ℓ : Level

isPropIsMagma : {M : Type ℓ} {_•_ : Op₂ M} → isProp (IsMagma M _•_)
isPropIsMagma (ismagma x) (ismagma y) = cong ismagma (isPropIsSet x y)


-- This is the preferred version of the integers in the library. Other
-- versions can be found in the MoreInts directory.
{-# OPTIONS --safe #-}
module Cubical.Data.Int.Base where

open import Cubical.Core.Everything
open import Cubical.Data.Bool
open import Cubical.Data.Nat hiding (_+_ ; _·_) renaming (isEven to isEvenℕ ; isOdd to isOddℕ)

infix  8 -_
infixl 7 _·_
infixl 6 _+_ _-_

data ℤ : Type₀ where
  pos    : (n : ℕ) → ℤ
  negsuc : (n : ℕ) → ℤ

neg : (n : ℕ) → ℤ
neg zero    = pos zero
neg (suc n) = negsuc n

sucℤ : ℤ → ℤ
sucℤ (pos n)          = pos (suc n)
sucℤ (negsuc zero)    = pos zero
sucℤ (negsuc (suc n)) = negsuc n

predℤ : ℤ → ℤ
predℤ (pos zero)    = negsuc zero
predℤ (pos (suc n)) = pos n
predℤ (negsuc n)    = negsuc (suc n)

isEven : ℤ → Bool
isEven (pos n) = isEvenℕ n
isEven (negsuc n) = isOddℕ n

isOdd : ℤ → Bool
isOdd (pos n) = isOddℕ n
isOdd (negsuc n) = isEvenℕ n

abs : ℤ → ℕ
abs (pos n) = n
abs (negsuc n) = suc n

_ℕ-_ : ℕ → ℕ → ℤ
a ℕ- 0 = pos a
0 ℕ- suc b = negsuc b
suc a ℕ- suc b = a ℕ- b

_+pos_ : ℤ → ℕ  → ℤ
z +pos 0 = z
z +pos (suc n) = sucℤ (z +pos n)

_+negsuc_ : ℤ → ℕ → ℤ
z +negsuc 0 = predℤ z
z +negsuc (suc n) = predℤ (z +negsuc n)

_+_ : ℤ → ℤ → ℤ
m + pos n = m +pos n
m + negsuc n = m +negsuc n

-_ : ℤ → ℤ
- pos zero = pos zero
- pos (suc n) = negsuc n
- negsuc n = pos (suc n)

_-_ : ℤ → ℤ → ℤ
m - n = m + (- n)

_·_ : ℤ → ℤ → ℤ
pos zero · m = pos zero
pos (suc n) · m = m + pos n · m
negsuc zero · m = - m
negsuc (suc n) · m = - m + negsuc n · m

-- Natural number and negative integer literals for ℤ

open import Cubical.Data.Nat.Literals public

instance
  fromNatℤ : HasFromNat ℤ
  fromNatℤ = record { Constraint = λ _ → Unit ; fromNat = λ n → pos n }

instance
  fromNegℤ : HasFromNeg ℤ
  fromNegℤ = record { Constraint = λ _ → Unit ; fromNeg = λ n → neg n }


module SystemF.Substitutions.Types where

open import Prelude
open import SystemF.Syntax.Type
open import Data.Fin.Substitution
open import Data.Star hiding (map)
open import Data.Vec

module TypeSubst where
  module TypeApp {T} (l : Lift T Type) where
    open Lift l hiding (var)

    infixl 8 _/_

    _/_ : ∀ {m n} → Type m → Sub T m n → Type n
    tc c     / σ = tc c
    tvar x   / σ = lift (lookup x σ)
    (a →' b) / σ = (a / σ) →' (b / σ)
    (a ⟶ b) / σ = (a / σ) ⟶ (b / σ)
    ∀' a     / σ = ∀' (a / σ ↑)

    open Application (record { _/_ = _/_ }) using (_/✶_)

    →'-/✶-↑✶ : ∀ k {m n a b} (ρs : Subs T m n) →
               (a →' b) /✶ ρs ↑✶ k ≡ (a /✶ ρs ↑✶ k) →' (b /✶ ρs ↑✶ k)
    →'-/✶-↑✶ k ε        = refl
    →'-/✶-↑✶ k (ρ ◅ ρs) = cong₂ _/_ (→'-/✶-↑✶ k ρs) refl

    ⟶-/✶-↑✶ : ∀ k {m n a b} (ρs : Subs T m n) →
               (a ⟶ b) /✶ ρs ↑✶ k ≡ (a /✶ ρs ↑✶ k) ⟶ (b /✶ ρs ↑✶ k)
    ⟶-/✶-↑✶ k ε        = refl
    ⟶-/✶-↑✶ k (ρ ◅ ρs) = cong₂ _/_ (⟶-/✶-↑✶ k ρs) refl

    ∀'-/✶-↑✶ : ∀ k {m n a} (ρs : Subs T m n) →
               (∀' a) /✶ ρs ↑✶ k ≡ ∀' (a /✶ ρs ↑✶ (1 + k))
    ∀'-/✶-↑✶ k ε        = refl
    ∀'-/✶-↑✶ k (ρ ◅ ρs) = cong₂ _/_ (∀'-/✶-↑✶ k ρs) refl

    tc-/✶-↑✶ : ∀ k {c m n} (ρs : Subs T m n) →
               (tc c) /✶ ρs ↑✶ k ≡ tc c
    tc-/✶-↑✶ k ε        = refl
    tc-/✶-↑✶ k (r ◅ ρs) = cong₂ _/_ (tc-/✶-↑✶ k ρs) refl

  typeSubst : TermSubst Type
  typeSubst = record { var = tvar; app = TypeApp._/_ }

  open TermSubst typeSubst public hiding (var)

  infix 8 _[/_]

  -- Shorthand for single-variable type substitutions
  _[/_] : ∀ {n} → Type (suc n) → Type n → Type n
  a [/ b ] = a / sub b

open TypeSubst public using ()
  renaming (_/_ to _tp/tp_; _[/_] to _tp[/tp_]; weaken to tp-weaken)


{-# OPTIONS --universe-polymorphism #-}

module Issue293a where

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

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

record RawMonoid c ℓ : Set (suc (c ⊔ ℓ)) where
  infixl 7 _∙_
  infix  4 _≈_
  field
    Carrier : Set c
    _≈_     : Carrier → Carrier → Set ℓ
    _∙_     : Carrier → Carrier → Carrier
    ε       : Carrier

module M (rm : RawMonoid zero zero) where

  open RawMonoid rm

  thm : ∀ x → x ∙ ε ≈ x
  thm = {!!}

  -- Previous agda2-goal-and-context:

  -- rm : RawMonoid zero zero
  -- ------------------------
  -- Goal: (x : RawMonoid.Carrier rm) →
  --       RawMonoid._≈_ rm (RawMonoid._∙_ rm x (RawMonoid.ε rm)) x

  -- Current agda2-goal-and-context:

  -- rm : RawMonoid zero zero
  -- ------------------------
  -- Goal: (x : Carrier) → x ∙ ε ≈ x

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

record RawMonoid′ : Set₁ where
  infixl 7 _∙_
  infix  4 _≈_
  field
    Carrier : Set
    _≈_     : Carrier → Carrier → Set
    _∙_     : Carrier → Carrier → Carrier
    ε       : Carrier

module M′ (rm : RawMonoid′) where

  open RawMonoid′ rm

  thm′ : ∀ x → x ∙ ε ≈ x
  thm′ = {!!}

  -- Previous and current agda2-goal-and-context:

  -- rm : RawMonoid′
  -- ---------------
  -- Goal: (x : Carrier) → x ∙ ε ≈ x

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

-- UP isn't relevant.

record RawMonoid″ (Carrier : Set) : Set₁ where
  infixl 7 _∙_
  infix  4 _≈_
  field
    _≈_     : Carrier → Carrier → Set
    _∙_     : Carrier → Carrier → Carrier
    ε       : Carrier

data Bool : Set where
  true false : Bool

data List (A : Set) : Set where
  []  :                        List A
  _∷_ : (x : A)(xs : List A) → List A

module M″ (rm : RawMonoid″ (List Bool)) where

  open RawMonoid″ rm

  thm″ : ∀ x → x ∙ ε ≈ x
  thm″ = {!!}

  -- Previous agda2-goal-and-context:

  -- rm : RawMonoid″ (List Bool)
  -- ---------------------------
  -- Goal: (x : List Bool) →
  --       RawMonoid″._≈_ rm (RawMonoid″._∙_ rm x (RawMonoid″.ε rm)) x

  -- Current agda2-goal-and-context:

  -- rm : RawMonoid″ (List Bool)
  -- ---------------------------
  -- Goal: (x : List Bool) → x ∙ ε ≈ x


{-# OPTIONS --safe #-}

module Confluence where

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

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

data ℕ : Set where
  Z : ℕ
  S : ℕ → ℕ

add : ℕ → ℕ → ℕ
add n Z = n
add n (S m) = S (add n m)

_ : ∀ {a : ℕ} → add a Z ≡ a
_ = refl

thm : ∀ {a : ℕ} → add Z a ≡ a
thm {a = Z} = refl
thm {a = (S m)} = cong S thm
-- Confluence checking is not supported;
-- Check out Jesper Cockx's Phd thesis for overlapping patterns.


{-

Smith Normal Form

Referrences:
  Guillaume Cano, Cyril Cohen, Maxime Dénès, Anders Mörtberg, Vincent Siles,
  "Formalized linear algebra over Elementary Divisor Rings in Coq"
  (https://arxiv.org/abs/1601.07472)

-}
{-# OPTIONS --safe #-}
module Cubical.Algebra.IntegerMatrix.Smith where

open import Cubical.Algebra.IntegerMatrix.Smith.NormalForm public
open import Cubical.Algebra.IntegerMatrix.Smith.Normalization public using (smith)


module Type.Category.ExtensionalFunctionsCategory{ℓ} where

open import Data
open import Functional
open import Function.Equals
open import Function.Equals.Proofs
open import Logic.Propositional
import      Relator.Equals as Eq
open import Relator.Equals.Proofs.Equiv
open import Structure.Category
open import Structure.Categorical.Properties
open import Type
open import Type.Properties.Singleton

-- The set category but the equality on the morphisms/functions is pointwise/extensional.
typeExtensionalFnCategory : Category{Obj = Type{ℓ}}(_→ᶠ_) ⦃ [⊜]-equiv ⦃ [≡]-equiv ⦄ ⦄
Category._∘_ typeExtensionalFnCategory = _∘_
Category.id  typeExtensionalFnCategory = id
Category.binaryOperator typeExtensionalFnCategory = [⊜][∘]-binaryOperator
Morphism.Associativity.proof (Category.associativity typeExtensionalFnCategory) {x = _} {_} {_} {x = f} {g} {h} = [⊜]-associativity {x = f}{y = g}{z = h}
Category.identity typeExtensionalFnCategory = [∧]-intro (Morphism.intro (Dependent.intro Eq.[≡]-intro)) (Morphism.intro (Dependent.intro Eq.[≡]-intro))

typeExtensionalFnCategoryObject : CategoryObject
typeExtensionalFnCategoryObject = intro typeExtensionalFnCategory

Empty-initialObject : Object.Initial{Obj = Type{ℓ}}(_→ᶠ_) ⦃ [⊜]-equiv ⦃ [≡]-equiv ⦄ ⦄ (Empty)
IsUnit.unit Empty-initialObject = empty
_⊜_.proof (IsUnit.uniqueness Empty-initialObject {f}) {}

Unit-terminalObject : Object.Terminal{Obj = Type{ℓ}}(_→ᶠ_) ⦃ [⊜]-equiv ⦃ [≡]-equiv ⦄ ⦄ (Unit)
IsUnit.unit Unit-terminalObject = const <>
_⊜_.proof (IsUnit.uniqueness Unit-terminalObject {f}) {_} = Eq.[≡]-intro


module VaryingClauseArity where

-- see also thread https://lists.chalmers.se/pipermail/agda-dev/2015-January/000041.html

open import Common.IO
open import Common.Unit
open import Common.Nat

Sum : Nat → Set
Sum 0       = Nat
Sum (suc n) = Nat → Sum n

sum : (acc : Nat) (n : Nat) → Sum n
sum acc 0         = acc
sum acc (suc n) 0 = sum acc n
sum acc (suc n) m = sum (m + acc) n

-- expected:
-- 10
-- 20
-- 33
main : IO Unit
main = printNat (sum 10 0) ,,
  putStr "\n" ,,
  printNat (sum 20 1 0) ,,
  putStr "\n" ,,
  printNat (sum 30 1 3)


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

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

open import LogicalFormulae
open import Setoids.Subset
open import Setoids.Setoids
open import Setoids.Orders.Partial.Definition
open import Setoids.Orders.Total.Definition
open import Sets.EquivalenceRelations
open import Rings.Orders.Total.Definition
open import Rings.Orders.Partial.Definition
open import Rings.Definition
open import Fields.Fields
open import Groups.Definition
open import Sequences
open import Numbers.Naturals.Semiring
open import Numbers.Naturals.Order
open import Semirings.Definition
open import Functions.Definition
open import Fields.Orders.Total.Definition
open import Numbers.Primes.PrimeNumbers

module Fields.Orders.Limits.Lemmas {a b c : _} {A : Set a} {S : Setoid {a} {b} A} {_+_ : A → A → A} {_*_ : A → A → A} {_<_ : Rel {_} {c} A} {R : Ring S _+_ _*_} {pOrder : SetoidPartialOrder S _<_} {F : Field R} {pRing : PartiallyOrderedRing R pOrder} (oF : TotallyOrderedField F pRing) where

open Ring R
open TotallyOrderedField oF
open TotallyOrderedRing oRing
open PartiallyOrderedRing pRing
open import Rings.Orders.Total.Lemmas oRing
open import Rings.Orders.Total.AbsoluteValue oRing
open import Rings.Orders.Partial.Lemmas pRing
open SetoidTotalOrder total
open SetoidPartialOrder pOrder
open Group additiveGroup
open import Groups.Lemmas additiveGroup
open Setoid S
open Equivalence eq
open Field F
open import Fields.CauchyCompletion.Definition (TotallyOrderedField.oRing oF) F
open import Fields.Orders.Limits.Definition oF
open import Fields.Lemmas F
open import Fields.Orders.Total.Lemmas oF
open import Rings.Characteristic R
open import Rings.InitialRing R
open import Rings.Orders.Total.Cauchy oRing

private
  2!=3 : 2 ≡ 3 → False
  2!=3 ()

convergentSequenceCauchy : (nontrivial : 0R ∼ 1R → False) → {a : Sequence A} → {r : A} → a ~> r → cauchy a
convergentSequenceCauchy _ {a} {r} a->r e 0<e with halve (λ i → charNotN 1 (transitive (transitive +Associative identRight) i)) e
... | e/2 , prE/2 with a->r e/2 (halvePositive' prE/2 0<e)
... | N , pr = N , λ {m} {n} → ans m n
  where
    ans : (m n : ℕ) → N <N m → N <N n → abs (index a m + inverse (index a n)) < e
    ans m n N<m N<n = <WellDefined reflexive prE/2 (bothNearImpliesNear {r} e/2 (halvePositive' prE/2 0<e) (pr m N<m) (pr n N<n))


------------------------------------------------------------------------------
-- Definition of the gcd of two natural numbers using the Euclid's algorithm
------------------------------------------------------------------------------

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

module FOTC.Program.GCD.Total.GCD where

open import FOTC.Base
open import FOTC.Data.Nat
open import FOTC.Data.Nat.Inequalities

------------------------------------------------------------------------------
-- In GHC ≥ 7.2.1 the gcd is a total function, i.e. gcd 0 0 = 0.

postulate
  gcd    : D → D → D
  gcd-eq : ∀ m n → gcd m n ≡
           (if (iszero₁ n)
              then m
              else (if (iszero₁ m)
                      then n
                      else (if (gt m n)
                             then gcd (m ∸ n) n
                             else gcd m (n ∸ m))))
{-# ATP axiom gcd-eq #-}


module TLP01 where

open import Data.Bool
open import Data.Nat
open import Data.String
open import Relation.Binary.PropositionalEquality
  as PropEq using (_≡_; refl; sym; cong; cong₂; trans)

_==ℕ_ : ℕ → ℕ → Bool
zero  ==ℕ zero  = true
suc n ==ℕ suc m = n ==ℕ m
_     ==ℕ _     = false

_<ℕ_ : ℕ → ℕ → Bool
_     <ℕ zero  = false
zero  <ℕ suc _ = true
suc n <ℕ suc m = n <ℕ m

-- ----- Star型の定義と同値性 -----
data Star : Set where
  NIL : Star
  TRU : Star
  N   : ℕ → Star
  S   : String → Star
  C   : Star → Star → Star

eqStar : Star → Star → Bool
eqStar NIL NIL = true
eqStar NIL _ = false
eqStar TRU TRU = true
eqStar TRU _ = false
eqStar (N x) (N y) = x ==ℕ y
eqStar (N _) _ = false
eqStar (S x) (S y) = x == y
eqStar (S _) _ = false
eqStar (C x x₁) (C y y₁) = eqStar x y ∧ eqStar x₁ y₁
eqStar (C _ _) _ = false

-- ----- 組込関数の定義 -----
CONS : Star → Star → Star
CONS = C

CAR : Star → Star
CAR (C x _) = x
CAR _ = NIL

CDR : Star → Star
CDR (C _ x₁) = x₁
CDR _ = NIL

ATOM : Star → Star
ATOM (C _ _) = NIL
ATOM _ = TRU

IF : Star → Star → Star → Star
IF TRU a _ = a
IF q a e = if eqStar q NIL then e else a

EQUAL : Star → Star → Star
EQUAL x y = if eqStar x y then TRU else NIL

s-size : Star → ℕ
s-size (C a b) = s-size a + s-size b + 1
s-size _ = 0
SIZE : Star → Star
SIZE x = N (s-size x)

s2n : Star → ℕ
s2n (N x) = x
s2n _ = 0
LT : Star → Star → Star
LT x y = if s2n x <ℕ s2n y then TRU else NIL

-- ----- Starから≡に -----
postulate
  ts : Star → Set
  ~ : Star → Star
  equal-eq : {x y : Star} → ts (EQUAL x y) →  x ≡ y
  ifAP : {q x y : Star} → ts (IF q (EQUAL x y) TRU) → (ts q → x ≡ y)
  ifEP : {q x y : Star} → ts (IF q TRU (EQUAL x y)) → (ts (~ q) → x ≡ y)
-- ----- 公理 -----
  equal-same : (x : Star) → ts (EQUAL x x)
  equal-swap : (x y : Star) → ts (EQUAL (EQUAL x y) (EQUAL y x))
  equal-if : (x y : Star) → ts (IF (EQUAL x y) (EQUAL x y) TRU)
  atom/cons : (x y : Star) → ts (EQUAL (ATOM (CONS x y)) NIL)
  car/cons : (x y : Star) → ts (EQUAL (CAR (CONS x y)) x)
  cdr/cons : (x y : Star) → ts (EQUAL (CDR (CONS x y)) y)
  cons/car+cdr : (x : Star)
    → ts (IF (ATOM x) TRU (EQUAL (CONS (CAR x) (CDR x)) x))
  if-true : (x y : Star) → ts (EQUAL (IF TRU x y) x)
  if-false : (x y : Star) → ts (EQUAL (IF NIL x y) y)
  if-same : (x y : Star) → ts (EQUAL (IF x y y) y)
  if-nest-A : (x y z : Star) → ts (IF x (EQUAL (IF x y z) y) TRU)
  if-nest-E : (x y z : Star) → ts (IF x TRU (EQUAL (IF x y z) z))
  size/car : (x : Star)
    → ts (IF (ATOM x) TRU (EQUAL (LT (SIZE (CAR x)) (SIZE x)) TRU))
  size/cdr : (x : Star)
    → ts (IF (ATOM x) TRU (EQUAL (LT (SIZE (CDR x)) (SIZE x)) TRU))

-- ----- 練習 -----
postulate
  -- a b : Star
  foo : ts (EQUAL TRU NIL)
hoge6 : (a b : Star)
  → (IF (EQUAL TRU NIL) TRU TRU) ≡ (IF (EQUAL TRU NIL) NIL TRU)
hoge6 a b = ifAP (equal-if TRU NIL) foo

hoge2 : (ATOM (CONS TRU TRU)) ≡ NIL
hoge2 = equal-eq (atom/cons TRU TRU)

-- hoge2' : (ATOM (CONS TRU TRU)) ≡ NIL
-- hoge2' rewrite (equal-eq (atom-cons TRU TRU)) = {!!}

hoge3 : (C TRU NIL) ≡ (C TRU NIL)
hoge3 = equal-eq (equal-same (C TRU NIL))

hoge4 : (EQUAL TRU TRU) ≡ TRU
hoge4 = begin
    (if eqStar TRU TRU then TRU else NIL)
  ≡⟨ refl ⟩
    TRU
  ∎
  where open PropEq.≡-Reasoning

hoge5 : (EQUAL NIL NIL) ≡ TRU
hoge5 = refl

postulate
  j : (x : Star) → ts (~ (ATOM x))
hoge7 : (x : ℕ)
  → (IF (ATOM (N x)) TRU (LT (SIZE (CDR (N x))) (SIZE (N x)))) ≡ (IF (ATOM (N x)) TRU TRU)
hoge7 x = ifEP (size/cdr (N x)) (j (N x))
-- -----

{-
-- ----- 停止性で引っかかる -----
memb?' : Star → Star
memb?' xs =
  (IF (ATOM xs)
       NIL
       (IF (EQUAL (CAR xs) (S "?"))
           TRU
           (memb?' (CDR xs))))
-}
-- ----- memb?の停止性 -----
-- ----- SIZEを使う時はℕを引数にとる
postulate
  premise : (xs : Star) → ts (~ (ATOM xs))
measure-memb? : (x : ℕ)
  → (IF (ATOM (N x))
        TRU
        (IF (EQUAL (CAR (N x)) (S "?"))
            TRU
            (LT (SIZE (CDR (N x))) (SIZE (N x)))))
    ≡ TRU
measure-memb? x = begin
    (IF (ATOM (N x))
        TRU
        (IF (EQUAL (CAR (N x)) (S "?"))
            TRU
            (LT (SIZE (CDR (N x))) (SIZE (N x)))))
  ≡⟨ ifEP (size/cdr (N x)) (premise (N x)) ⟩
    (IF (ATOM (N x))
        TRU
        (IF (EQUAL (CAR (N x)) (S "?"))
            TRU
            TRU))
  ≡⟨ equal-eq (if-same (EQUAL (CAR (N x)) (S "?")) TRU) ⟩
    (IF (ATOM (N x))
        TRU
        TRU)
  ≡⟨ equal-eq (if-same (ATOM (N x)) TRU) ⟩
    TRU
  ∎
  where open PropEq.≡-Reasoning

-- ----- memb?の定義 -----
postulate
  memb? : Star → Star
  def-memb? : (xs : Star) →
    memb? xs ≡
      (IF (ATOM xs)
          NIL
          (IF (EQUAL (CAR xs) (S "?"))
              TRU
              (memb? (CDR xs))))
-- ----- rembの定義 -----
postulate
  remb : Star → Star
  def-remb : (xs : Star) →
    remb xs ≡
      (IF (ATOM xs)
          (S "'()")
          (IF (EQUAL (CAR xs) (S "?"))
              (remb (CDR xs))
              (CONS (CAR xs)
                 (remb (CDR xs)))))
-- ----- 帰納的な証明(未完) -----
-- ----- ATOMを使う時はC x yを引数にとる
postulate
  premise2 : (xs : Star) → ts (ATOM xs)
atomt : (ATOM (S "'()")) ≡ TRU
atomt = refl
memb?/remb : (x y : Star)
  → (IF (ATOM (C x y))
        (EQUAL (memb? (remb (C x y))) NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
    ≡      (IF (ATOM (C x y))
        (EQUAL (IF TRU
                    NIL
                    (IF (EQUAL (CAR (S "'()")) (S "?"))
                        TRU
                        (memb? (CDR (S "'()")))))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
memb?/remb x y = begin
    (IF (ATOM (C x y))
        (EQUAL (memb? (remb (C x y))) NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
  ≡⟨ cong (λ t → ((IF (ATOM (C x y))
        (EQUAL (memb? t) NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU)))) (def-remb (C x y)) ⟩
    (IF (ATOM (C x y))
        (EQUAL (memb? (IF (ATOM (C x y))
          (S "'()")
          (IF (EQUAL (CAR (C x y)) (S "?"))
              (remb (CDR (C x y)))
              (CONS (CAR (C x y))
                 (remb (CDR (C x y)))))))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
  ≡⟨ ifAP (if-nest-A (ATOM (C x y)) (S "'()") ((IF (EQUAL (CAR (C x y)) (S "?"))
              (remb (CDR (C x y)))
              (CONS (CAR (C x y))
                 (remb (CDR (C x y))))))) (premise2 (C x y)) ⟩
    (IF (ATOM (C x y))
        (EQUAL (memb?
          (S "'()"))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
  ≡⟨ cong ((λ t → (IF (ATOM (C x y))
        (EQUAL t
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU)))) (def-memb? ((S "'()"))) ⟩
    (IF (ATOM (C x y))
        (EQUAL (IF (ATOM (S "'()"))
                    NIL
                    (IF (EQUAL (CAR (S "'()")) (S "?"))
                        TRU
                        (memb? (CDR (S "'()")))))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
  ≡⟨ cong ((λ t →     (IF (ATOM (C x y))
        (EQUAL (IF t
                    NIL
                    (IF (EQUAL (CAR (S "'()")) (S "?"))
                        TRU
                        (memb? (CDR (S "'()")))))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU)))) atomt ⟩
    (IF (ATOM (C x y))
        (EQUAL (IF TRU
                    NIL
                    (IF (EQUAL (CAR (S "'()")) (S "?"))
                        TRU
                        (memb? (CDR (S "'()")))))
                        NIL)
        (IF (EQUAL (memb? (remb (CDR (C x y)))) NIL)
            (EQUAL (memb? (remb (C x y))) NIL)
            TRU))
  ∎
  where open PropEq.≡-Reasoning


module plfa.part1.Relations where

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; cong)
open import Data.Nat using (ℕ; zero; suc; _+_)
open import Data.Nat.Properties using (+-comm; +-identityʳ)

data _≤_ : ℕ → ℕ → Set where

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

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

infix 4 _≤_

inv-s≤s : ∀ {m n : ℕ}
  → suc m ≤ suc n
    -------------
  → m ≤ n
inv-s≤s (s≤s m≤n) = m≤n

inv-z≤n : ∀ {m : ℕ}
  → m ≤ zero
    --------
  → m ≡ zero
inv-z≤n z≤n = refl

≤-refl : ∀ {n} → n ≤ n
≤-refl {zero} = z≤n
≤-refl {suc n} = s≤s ≤-refl

≤-trans : ∀ {m n p} → m ≤ n → n ≤ p → m ≤ p
≤-trans z≤n n = z≤n
≤-trans (s≤s m) (s≤s n) = s≤s (≤-trans m n)

≤-antisymm : ∀ {m n} → m ≤ n → n ≤ m → m ≡ n
≤-antisymm z≤n z≤n = refl
≤-antisymm (s≤s m) (s≤s n) = cong suc (≤-antisymm m n)

data Total (m n : ℕ) : Set where

  forward :
      m ≤ n
      ---------
    → Total m n

  flipped :
      n ≤ m
      ---------
    → Total m n

≤-total : ∀ (m n : ℕ) → Total m n
≤-total zero n = forward z≤n
≤-total (suc m) (zero) = flipped z≤n
≤-total (suc m) (suc n) with ≤-total m n
...                        | forward a = forward (s≤s a)
...                        | flipped b = flipped (s≤s b)

+-monoʳ-≤ : ∀ (n p q : ℕ)
  → p ≤ q
    -------------
  → n + p ≤ n + q
+-monoʳ-≤ zero    p q p≤q = p≤q
+-monoʳ-≤ (suc n) p q p≤q = s≤s (+-monoʳ-≤ n p q p≤q)

+-monoˡ-≤ : ∀ (m n p : ℕ)
  → m ≤ n
    -------------
  → m + p ≤ n + p
+-monoˡ-≤ m n p m≤n rewrite +-comm m p | +-comm n p = +-monoʳ-≤ p m n m≤n

+-mono-≤ : ∀ (m n p q : ℕ)
  → m ≤ n
  → p ≤ q
    -------------
  → m + p ≤ n + q
+-mono-≤ m n p q m≤n p≤q =
  ≤-trans (+-monoˡ-≤ m n p m≤n) (+-monoʳ-≤ n p q p≤q)

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

data even where

  zero :
      ---------
      even zero

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

data odd where

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

e+e≡e : ∀ {m n : ℕ}
  → even m
  → even n
    ------------
  → even (m + n)

o+e≡o : ∀ {m n : ℕ}
  → odd m
  → even n
    -----------
  → odd (m + n)

e+e≡e zero     en  =  en
e+e≡e (suc om) en  =  suc (o+e≡o om en)

o+e≡o (suc em) en  =  suc (e+e≡e em en)

o+o≡e : ∀ {m n : ℕ}
  → odd m
  → odd n
  → even (m + n)
o+o≡e {suc a} {suc b} (suc m) (suc n)
  rewrite +-comm a (suc b) = suc (o+e≡o (suc n) m)


-- simulating streams by Nat -> A

module Stream where

data Bool : Set where
    true  : Bool
    false : Bool

if_then_else_ : forall {A} -> Bool -> A -> A -> A
if true  then t else e = t
if false then t else e = e

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

Stream : Set -> Set
Stream A = Nat -> A

_::_ : forall {A} -> A -> Stream A -> Stream A
_::_ a as zero     = a
_::_ a as (succ n) = as n

map : forall {A B} -> (A -> B) -> Stream A -> Stream B
map f as n = f (as n)

head : forall {A} -> Stream A -> A
head as = as zero

tail : forall {A} -> Stream A -> Stream A
tail as n = as (succ n)

-- construct the stream a :: f a :: f (f a) :: ...

iterate : forall {A} -> (A -> A) -> A -> Stream A
iterate f a zero = a
iterate f a (succ n) = iterate f (f a) n

zipWith : forall {A B C} -> (A -> B -> C) -> Stream A -> Stream B -> Stream C
zipWith f as bs n = f (as n) (bs n)

-- merge with with
merge : forall {A} -> (A -> A -> Bool) -> Stream A -> Stream A -> Stream A
merge le as bs with le (head as) (head bs)
merge le as bs | true  = head as :: merge le (tail as) bs
merge le as bs | false = head bs :: merge le as (tail bs)

{-
-- without with
merge' : forall {A} -> (A -> A -> Bool) -> Stream A -> Stream A -> Stream A
merge' le as bs = if le (head as) (head bs)
                  then (head as :: merge' le (tail as) bs)
                  else (head bs :: merge' le as (tail bs))
-}

-- BOTH VARIANTS OF MERGE ARE NOT STRUCTURALLY RECURSIVE


-- Kleene's three-valued logic

module bool-kleene where

open import bool
open import eq

data 𝔹ₖ : Set where
  tt : 𝔹ₖ
  ff : 𝔹ₖ
  uu : 𝔹ₖ

infix  7 ~ₖ_
infixr 6 _&&ₖ_
infixr 5 _||ₖ_
--infixr 4 _impₖ_

~ₖ_ : 𝔹ₖ → 𝔹ₖ
~ₖ tt = ff
~ₖ ff = tt
~ₖ uu = uu

-- and
_&&ₖ_ : 𝔹ₖ → 𝔹ₖ → 𝔹ₖ
tt &&ₖ b = b
ff &&ₖ b = ff
uu &&ₖ ff = ff
uu &&ₖ b = uu

-- or
_||ₖ_ : 𝔹ₖ → 𝔹ₖ → 𝔹ₖ
ff ||ₖ b = b
tt ||ₖ b = tt
uu ||ₖ tt = tt
uu ||ₖ b = uu

-- implication
_impₖ_ : 𝔹ₖ → 𝔹ₖ → 𝔹ₖ
tt impₖ b2 = b2
ff impₖ b2 = tt
uu impₖ tt = tt
uu impₖ b = uu

knownₖ : 𝔹ₖ → 𝔹
knownₖ tt = tt
knownₖ ff = tt
knownₖ uu = ff

to-𝔹 : (b : 𝔹ₖ) → knownₖ b ≡ tt → 𝔹
to-𝔹 tt p = tt
to-𝔹 ff p = ff
to-𝔹 uu ()


open import Relation.Binary.Core

module Bound.Lower.Order.Properties {A : Set}
                 (_≤_ : A → A → Set)
                 (trans≤ : Transitive _≤_)  where

open import Bound.Lower A
open import Bound.Lower.Order _≤_

transLeB : {a b c : Bound} → LeB a b → LeB b c → LeB a c
transLeB lebx _ = lebx
transLeB (lexy x≤y) (lexy y≤z) = lexy (trans≤ x≤y y≤z)


module Inductive.Examples.List where

open import Inductive
open import Tuple hiding (_++_)

open import Data.Fin
open import Data.Product hiding (map)
open import Data.List hiding (List; map; foldr; _++_)
open import Data.Vec hiding (map; foldr; _++_)

List : Set → Set
List A = Inductive (([] , []) ∷ (((A ∷ []) , ([] ∷ [])) ∷ []))

nil : {A : Set} → List A
nil = construct zero [] []

cons : {A : Set} → A → List A → List A
cons x xs = construct (suc zero) (x ∷ []) ((λ _ → xs) ∷ [])

map : {A B : Set} → (A → B) → List A → List B
map f = rec (nil ∷ ((λ a as ras → cons (f a) ras) ∷ []))

foldr : {A B : Set} → (A → B → B) → B → List A → B
foldr f b = rec (b ∷ (λ a as ras → f a ras) ∷ [])

_++_ : {A : Set} → List A → List A → List A
xs ++ ys = rec (ys ∷ (λ a as ras → cons a ras) ∷ []) xs