{-# OPTIONS --sized-types --guardedness --cubical #-}

-- Note: This module is not meant to be imported.
module All where

-- import All
import Automaton.Deterministic.Accessible
import Automaton.Deterministic.Finite
-- import Automaton.Deterministic.FormalLanguage
import Automaton.Deterministic.Oper
import Automaton.Deterministic
-- import Automaton.NonDeterministic
-- import Automaton.Pushdown
-- import Automaton.TuringMachine
import Data.Any
import Data.BinaryTree.Heap
import Data.BinaryTree.Properties
import Data.BinaryTree
import Data.Boolean.Equiv.Path
import Data.Boolean.Functions
import Data.Boolean.NaryOperators
import Data.Boolean.Numeral
import Data.Boolean.Operators
import Data.Boolean.Proofs
import Data.Boolean.Stmt.Proofs
import Data.Boolean.Stmt
import Data.Boolean
import Data.DependentWidthTree
import Data.DynamicTree
import Data.Either.Equiv.Id
import Data.Either.Equiv
import Data.Either.Multi
import Data.Either.Proofs
import Data.Either.Setoid
import Data.Either
import Data.FixedTree.Properties
import Data.FixedTree
import Data.IndexedList
import Data.Iterator
import Data.List.Categorical
import Data.List.Combinatorics.Proofs
import Data.List.Combinatorics
import Data.List.Decidable
import Data.List.Equiv.Id
import Data.List.Equiv
import Data.List.Functions.Multi
import Data.List.Functions.Positional
import Data.List.Functions
import Data.List.FunctionsProven
import Data.List.Iterable
import Data.List.Proofs.Length
import Data.List.Proofs
import Data.List.Relation.Membership.Proofs
import Data.List.Relation.Membership
import Data.List.Relation.Pairwise.Proofs
import Data.List.Relation.Pairwise
import Data.List.Relation.Permutation
import Data.List.Relation.Quantification.Proofs
import Data.List.Relation.Quantification
import Data.List.Relation.Sublist.Proofs
import Data.List.Relation.Sublist
import Data.List.Relation
import Data.List.Setoid
import Data.List.Size
import Data.List.SizeOrdering
import Data.List.Sorting.Functions
import Data.List.Sorting.HeapSort
import Data.List.Sorting.InsertionSort
import Data.List.Sorting.MergeSort
import Data.List.Sorting.Proofs
import Data.List.Sorting.QuickSort
import Data.List.Sorting.SelectionSort
import Data.List.Sorting
import Data.List
import Data.ListNonEmpty
import Data.ListSized.Functions
import Data.ListSized.Proofs
import Data.ListSized
import Data.Option.Categorical
import Data.Option.Equiv.Id
import Data.Option.Equiv.Path
import Data.Option.Equiv
import Data.Option.Functions
import Data.Option.Iterable
import Data.Option.Proofs
import Data.Option.Setoid
import Data.Option
import Data.Proofs
import Data.Tuple.Category
import Data.Tuple.Equiv.Id
import Data.Tuple.Equiv
import Data.Tuple.Equivalence
import Data.Tuple.Function
import Data.Tuple.List
import Data.Tuple.Proofs
import Data.Tuple.Raise
import Data.Tuple.RaiseTypeᵣ.Functions
import Data.Tuple.RaiseTypeᵣ
import Data.Tuple.Raiseᵣ.Functions
import Data.Tuple.Raiseᵣ.Iterable
import Data.Tuple.Raiseᵣ.Proofs
import Data.Tuple.Raiseᵣ
import Data.Tuple.Raiseₗ
import Data.Tuple
import Data
import FFI.IO
import FFI.MachineWord
import Float
-- import FormalLanguage.ContextFreeGrammar
-- import FormalLanguage.Equals
-- import FormalLanguage.Proofs
-- import FormalLanguage.RegularExpression
-- import FormalLanguage
import Formalization.ClassicalPredicateLogic.Semantics
import Formalization.ClassicalPredicateLogic.Syntax.Substitution
import Formalization.ClassicalPredicateLogic.Syntax
import Formalization.ClassicalPropositionalLogic.NaturalDeduction.Consistency
import Formalization.ClassicalPropositionalLogic.NaturalDeduction.Proofs
-- import Formalization.ClassicalPropositionalLogic.NaturalDeduction.Tree
import Formalization.ClassicalPropositionalLogic.NaturalDeduction
import Formalization.ClassicalPropositionalLogic.Place
import Formalization.ClassicalPropositionalLogic.Semantics.Proofs
import Formalization.ClassicalPropositionalLogic.Semantics
-- import Formalization.ClassicalPropositionalLogic.SequentCalculus
import Formalization.ClassicalPropositionalLogic.Syntax.Proofs
import Formalization.ClassicalPropositionalLogic.Syntax
import Formalization.ClassicalPropositionalLogic.TruthTable
-- import Formalization.ClassicalPropositionalLogic
-- import Formalization.FunctionalML
import Formalization.ImperativePL
import Formalization.LambdaCalculus.Semantics.CallByName
import Formalization.LambdaCalculus.Semantics.CallByValue
import Formalization.LambdaCalculus.Semantics.Reduction
import Formalization.LambdaCalculus.Semantics
import Formalization.LambdaCalculus.SyntaxTransformation
import Formalization.LambdaCalculus.Terms.Combinators
import Formalization.LambdaCalculus
import Formalization.Monoid
import Formalization.Polynomial
import Formalization.PredicateLogic.Classical.NaturalDeduction
-- import Formalization.PredicateLogic.Classical.Semantics.Homomorphism
import Formalization.PredicateLogic.Classical.Semantics.Satisfaction
import Formalization.PredicateLogic.Classical.Semantics
import Formalization.PredicateLogic.Classical.SequentCalculus
import Formalization.PredicateLogic.Constructive.NaturalDeduction
-- import Formalization.PredicateLogic.Constructive.SequentCalculus
-- import Formalization.PredicateLogic.Minimal.NaturalDeduction.NegativeTranslations
import Formalization.PredicateLogic.Minimal.NaturalDeduction.Tree
import Formalization.PredicateLogic.Minimal.NaturalDeduction
-- import Formalization.PredicateLogic.Minimal.SequentCalculus
import Formalization.PredicateLogic.Signature
import Formalization.PredicateLogic.Syntax.NegativeTranslations
import Formalization.PredicateLogic.Syntax.Substitution
import Formalization.PredicateLogic.Syntax.Tree
import Formalization.PredicateLogic.Syntax
import Formalization.PrimitiveRecursion
-- import Formalization.PureTypeSystem
import Formalization.RecursiveFunction
import Formalization.SKICombinatorCalculus
import Formalization.SimplyTypedLambdaCalculus
import Function.Axioms
import Function.DomainRaise
import Function.Domains.Functions
import Function.Domains.Id
import Function.Domains.Proofs
import Function.Domains
import Function.Equals.Multi
import Function.Equals.Proofs
import Function.Equals
import Function.Inverse
import Function.Inverseᵣ
import Function.Inverseₗ
import Function.Iteration.Order
import Function.Iteration.Proofs
import Function.Iteration
import Function.Multi.Functions
import Function.Multi
import Function.Multi₌.Functions
import Function.Multi₌
import Function.Names
import Function.PointwiseStructure
import Function.Proofs
import Function
import Functional.Combinations
import Functional.Dependent
import Functional
-- import Geometry.Axioms
-- import Geometry.HilbertAxioms
import Graph.Category
import Graph.Oper
import Graph.Properties.Proofs
import Graph.Properties
import Graph.Walk.Functions.Proofs
import Graph.Walk.Functions
import Graph.Walk.Proofs
import Graph.Walk.Properties
import Graph.Walk
import Graph
import Iterator
import Js
import Lang.Function
import Lang.Inspect
import Lang.Instance
import Lang.Irrelevance
import Lang.Reflection
import Lang.Size
import Lang.Vars.Structure.Operator
import Logic.Classical.DoubleNegated
import Logic.Classical
import Logic.DiagonalMethod
import Logic.IntroInstances
import Logic.Names
import Logic.Predicate.Equiv
import Logic.Predicate.Multi
import Logic.Predicate.Theorems
import Logic.Predicate
import Logic.Propositional.Equiv
import Logic.Propositional.Proofs.Structures
import Logic.Propositional.Theorems
import Logic.Propositional.Xor
import Logic.Propositional
import Logic.WeaklyClassical
import Logic
import Lvl.Decidable
import Lvl.Functions
import Lvl.MultiFunctions.Proofs
import Lvl.MultiFunctions
import Lvl.Proofs
import Lvl
import Main
import Numeral.CoordinateVector.Proofs
import Numeral.CoordinateVector
import Numeral.Finite.Bound
import Numeral.Finite.Category
import Numeral.Finite.Conversions
import Numeral.Finite.Equiv
import Numeral.Finite.Functions
import Numeral.Finite.LinearSearch
import Numeral.Finite.Oper.Comparisons.Proofs
import Numeral.Finite.Oper.Comparisons
import Numeral.Finite.Oper
import Numeral.Finite.Proofs
import Numeral.Finite.Relation.Order
import Numeral.Finite.Sequence
import Numeral.Finite
import Numeral.FixedPositional
import Numeral.Integer.Function
import Numeral.Integer.Oper
import Numeral.Integer.Proofs
import Numeral.Integer.Relation.Divisibility.Proofs
import Numeral.Integer.Relation.Divisibility
import Numeral.Integer.Relation.Order
-- import Numeral.Integer.Relation
import Numeral.Integer.Sign
import Numeral.Integer
-- import Numeral.Matrix.OverField
import Numeral.Matrix.Proofs
-- import Numeral.Matrix.Relations
import Numeral.Matrix
import Numeral.Natural.Combinatorics.Proofs
import Numeral.Natural.Combinatorics
import Numeral.Natural.Coprime.Proofs
import Numeral.Natural.Coprime
import Numeral.Natural.Decidable
import Numeral.Natural.Equiv.Path
import Numeral.Natural.Function.Coprimalize
import Numeral.Natural.Function.FlooredLogarithm
import Numeral.Natural.Function.GreatestCommonDivisor.Extended
import Numeral.Natural.Function.GreatestCommonDivisor.Proofs
import Numeral.Natural.Function.GreatestCommonDivisor
import Numeral.Natural.Function.Proofs
import Numeral.Natural.Function
import Numeral.Natural.Induction
import Numeral.Natural.Inductions
import Numeral.Natural.LinearSearch
-- import Numeral.Natural.LinearSearchDecidable
import Numeral.Natural.Oper.Comparisons.Proofs
import Numeral.Natural.Oper.Comparisons
import Numeral.Natural.Oper.DivMod.Proofs
import Numeral.Natural.Oper.Divisibility
import Numeral.Natural.Oper.FlooredDivision.Proofs.DivisibilityWithRemainder
import Numeral.Natural.Oper.FlooredDivision.Proofs.Inverse
import Numeral.Natural.Oper.FlooredDivision.Proofs
import Numeral.Natural.Oper.FlooredDivision
import Numeral.Natural.Oper.Modulo.Proofs.Algorithm
import Numeral.Natural.Oper.Modulo.Proofs.DivisibilityWithRemainder
import Numeral.Natural.Oper.Modulo.Proofs.Elim
import Numeral.Natural.Oper.Modulo.Proofs
import Numeral.Natural.Oper.Modulo
-- import Numeral.Natural.Oper.Proofs.Elemantary
-- import Numeral.Natural.Oper.Proofs.Iteration
import Numeral.Natural.Oper.Proofs.Multiplication
import Numeral.Natural.Oper.Proofs.Order
import Numeral.Natural.Oper.Proofs.Rewrite
-- import Numeral.Natural.Oper.Proofs.Structure
import Numeral.Natural.Oper.Proofs
import Numeral.Natural.Oper.Summation.Proofs
import Numeral.Natural.Oper.Summation.Range.Proofs
import Numeral.Natural.Oper.Summation.Range
import Numeral.Natural.Oper.Summation
import Numeral.Natural.Oper
import Numeral.Natural.Prime.Proofs.Product
import Numeral.Natural.Prime.Proofs.Representation
import Numeral.Natural.Prime.Proofs
import Numeral.Natural.Prime
import Numeral.Natural.Proofs
import Numeral.Natural.Relation.Divisibility.Proofs.Modulo
import Numeral.Natural.Relation.Divisibility.Proofs.Product
import Numeral.Natural.Relation.Divisibility.Proofs
import Numeral.Natural.Relation.Divisibility
import Numeral.Natural.Relation.DivisibilityWithRemainder.Proofs
import Numeral.Natural.Relation.DivisibilityWithRemainder
import Numeral.Natural.Relation.ModuloCongruence
import Numeral.Natural.Relation.Order.Category
import Numeral.Natural.Relation.Order.Classical
import Numeral.Natural.Relation.Order.Decidable
import Numeral.Natural.Relation.Order.Existence.Proofs
import Numeral.Natural.Relation.Order.Existence
import Numeral.Natural.Relation.Order.Proofs
import Numeral.Natural.Relation.Order
import Numeral.Natural.Relation.Proofs
import Numeral.Natural.Relation.Properties
import Numeral.Natural.Relation
import Numeral.Natural.Sequence.Proofs
import Numeral.Natural.Sequence
import Numeral.Natural.TotalOper
import Numeral.Natural.UnclosedOper
import Numeral.Natural
import Numeral.Ordinal
import Numeral.PositiveInteger.Oper.Proofs
import Numeral.PositiveInteger.Oper
import Numeral.PositiveInteger
-- import Numeral.Rational.AlterAdd
-- import Numeral.Rational.SternBrocot
import Numeral.Sign.Oper.Proofs
import Numeral.Sign.Oper
import Numeral.Sign.Oper0
import Numeral.Sign.Proofs
import Numeral.Sign
import Operator.Equals
import ReductionSystem
import Relator.Category
import Relator.Congruence.Proofs
import Relator.Congruence
import Relator.Converse
import Relator.Equals.Category
import Relator.Equals.Proofs.Equiv
import Relator.Equals.Proofs.Equivalence
import Relator.Equals.Proofs
import Relator.Equals
import Relator.Ordering.Proofs
import Relator.Ordering
import Relator.ReflexiveTransitiveClosure
import Relator.Sets
import Sets.BoolSet
-- import Sets.ExtensionalPredicateSet.SetLike
import Sets.ExtensionalPredicateSet
import Sets.ImageSet.Oper
-- import Sets.ImageSet.SetLike
import Sets.ImageSet
import Sets.IterativeSet.Oper.Proofs
import Sets.IterativeSet.Oper
import Sets.IterativeSet.Relator.Proofs
import Sets.IterativeSet.Relator
import Sets.IterativeSet
import Sets.IterativeUSet
import Sets.PredicateSet.Listable
import Sets.PredicateSet
import Sized.Data.List
import Stream.Iterable
import Stream
import String
-- import Structure.Categorical.Multi
import Structure.Categorical.Names
import Structure.Categorical.Proofs
import Structure.Categorical.Properties
import Structure.Category.Action
import Structure.Category.Categories
import Structure.Category.Category
import Structure.Category.CoMonad
import Structure.Category.Dual
-- import Structure.Category.Equiv
import Structure.Category.Functor.Category
import Structure.Category.Functor.Contravariant
import Structure.Category.Functor.Equiv
import Structure.Category.Functor.Functors.Proofs
import Structure.Category.Functor.Functors
import Structure.Category.Functor.Proofs
import Structure.Category.Functor
import Structure.Category.Monad.Category
import Structure.Category.Monad.ExtensionSystem
import Structure.Category.Monad
import Structure.Category.Monoid
-- import Structure.Category.Monoidal
import Structure.Category.Morphism.IdTransport
import Structure.Category.Morphism.Transport
import Structure.Category.NaturalTransformation.Equiv
import Structure.Category.NaturalTransformation.NaturalTransformations
import Structure.Category.NaturalTransformation
import Structure.Category.Proofs
import Structure.Category
import Structure.Container.IndexedIterable
import Structure.Container.Iterable
-- import Structure.Container.SetLike.Proofs
-- import Structure.Container.SetLike
import Structure.Function.Domain.Proofs
import Structure.Function.Domain
import Structure.Function.Linear
-- import Structure.Function.Metric
import Structure.Function.Multi
import Structure.Function.Names
import Structure.Function.Ordering
import Structure.Function.Proofs
import Structure.Function
import Structure.Groupoid.Functor
import Structure.Groupoid.Groupoids
import Structure.Groupoid
import Structure.Logic.Constructive.BoundedPredicate
import Structure.Logic.Constructive.Predicate
import Structure.Logic.Constructive.Proofs
import Structure.Logic.Constructive.Propositional
import Structure.Logic
-- import Structure.Numeral.Integer.Proofs
import Structure.Numeral.Integer
import Structure.Numeral.Natural
import Structure.Operator.Algebra
import Structure.Operator.Field.VectorSpace
import Structure.Operator.Field
import Structure.Operator.Functions
import Structure.Operator.Group.Proofs
import Structure.Operator.Group
import Structure.Operator.IntegralDomain
-- import Structure.Operator.Iteration
import Structure.Operator.Lattice
import Structure.Operator.Monoid.Category
import Structure.Operator.Monoid.Homomorphism
import Structure.Operator.Monoid.Invertible.Proofs
import Structure.Operator.Monoid.Invertible
import Structure.Operator.Monoid.Monoids.Coset
import Structure.Operator.Monoid.Monoids.Function
import Structure.Operator.Monoid.Proofs
import Structure.Operator.Monoid.Submonoid
import Structure.Operator.Monoid
import Structure.Operator.Names
import Structure.Operator.Proofs.Util
import Structure.Operator.Proofs
import Structure.Operator.Properties
import Structure.Operator.Ring.Characteristic
import Structure.Operator.Ring.Homomorphism
import Structure.Operator.Ring.Proofs
import Structure.Operator.Ring.Rings
import Structure.Operator.Ring
import Structure.Operator.SetAlgebra
import Structure.Operator.Vector.Eigen
-- import Structure.Operator.Vector.Equiv
import Structure.Operator.Vector.FiniteDimensional.LinearMaps.ChangeOfBasis
-- import Structure.Operator.Vector.FiniteDimensional.Proofs
import Structure.Operator.Vector.FiniteDimensional
import Structure.Operator.Vector.InfiniteDimensional
-- import Structure.Operator.Vector.LinearCombination.Proofs
import Structure.Operator.Vector.LinearCombination
-- import Structure.Operator.Vector.LinearMap.Category
-- import Structure.Operator.Vector.LinearMap.Equiv
import Structure.Operator.Vector.LinearMap
import Structure.Operator.Vector.LinearMaps
import Structure.Operator.Vector.Proofs
-- import Structure.Operator.Vector.Subspace.Proofs
-- import Structure.Operator.Vector.Subspace
-- import Structure.Operator.Vector.Subspaces.DirectSum
-- import Structure.Operator.Vector.Subspaces.Image
-- import Structure.Operator.Vector.Subspaces.Kernel
-- import Structure.Operator.Vector.Subspaces.Span
import Structure.Operator.Vector
import Structure.Operator
import Structure.OrderedField.AbsoluteValue
import Structure.OrderedField
import Structure.Real.Abs
-- import Structure.Real.Continuity
-- import Structure.Real.Derivative
-- import Structure.Real.Limit
import Structure.Real
import Structure.Relator.Apartness.Proofs
import Structure.Relator.Apartness
import Structure.Relator.Equivalence.Proofs
import Structure.Relator.Equivalence
import Structure.Relator.Function.Multi
import Structure.Relator.Function.Proofs
import Structure.Relator.Function
import Structure.Relator.Names
import Structure.Relator.Ordering.Lattice
import Structure.Relator.Ordering.Proofs
import Structure.Relator.Ordering
import Structure.Relator.Proofs
import Structure.Relator.Properties.Proofs
import Structure.Relator.Properties
import Structure.Relator
import Structure.Semicategory
import Structure.Setoid.Category.HomFunctor
import Structure.Setoid.Category
import Structure.Setoid.Names
import Structure.Setoid.Proofs
import Structure.Setoid.Size.Proofs
import Structure.Setoid.Size
import Structure.Setoid.Uniqueness.Proofs
import Structure.Setoid.Uniqueness
import Structure.Setoid
import Structure.Sets.Names
import Structure.Sets.Operator
import Structure.Sets.Quantifiers.Proofs
import Structure.Sets.Quantifiers
import Structure.Sets.Relator
import Structure.Sets.Relators
import Structure.Sets.ZFC.Classical
import Structure.Sets.ZFC.Inductive
import Structure.Sets.ZFC.Oper
import Structure.Sets.ZFC
import Structure.Sets
import Structure.Signature
-- import Structure.Topology.Proofs
-- import Structure.Topology.Properties
import Structure.Topology
import Structure.Type.Identity.Proofs.Eliminator
-- import Structure.Type.Identity.Proofs.Multi
import Structure.Type.Identity.Proofs
import Structure.Type.Identity
import Structure.Type.Quotient
import Syntax.Do
import Syntax.Function
import Syntax.Idiom
import Syntax.Implication.Dependent
import Syntax.Implication
import Syntax.List
import Syntax.Number
import Syntax.Transitivity
import Syntax.Type
import TestProp
import Type.Category.ExtensionalFunctionsCategory.HomFunctor
import Type.Category.ExtensionalFunctionsCategory
-- import Type.Category.IntensionalFunctionsCategory.HomFunctor
import Type.Category.IntensionalFunctionsCategory.LvlUpFunctor
import Type.Category.IntensionalFunctionsCategory
import Type.Category
import Type.Cubical.Equiv
import Type.Cubical.HTrunc₁
import Type.Cubical.InductiveInterval
import Type.Cubical.InductivePath
import Type.Cubical.Logic
import Type.Cubical.Path.Category
import Type.Cubical.Path.Equality
import Type.Cubical.Path.Proofs
import Type.Cubical.Path
import Type.Cubical.Quotient
import Type.Cubical.SubtypeSet
import Type.Cubical.Univalence
import Type.Cubical
import Type.Dependent.Functions
import Type.Dependent
import Type.Equiv
import Type.Identity.Heterogenous
import Type.Identity.Proofs
import Type.Identity
import Type.Isomorphism
import Type.Proofs
import Type.Properties.Decidable.Proofs
import Type.Properties.Decidable
import Type.Properties.Empty.Proofs
import Type.Properties.Empty
-- import Type.Properties.Homotopy.Proofs
import Type.Properties.Homotopy
import Type.Properties.Inhabited
import Type.Properties.MereProposition
import Type.Properties.Singleton.Proofs
import Type.Properties.Singleton
import Type.Singleton.Proofs
import Type.Singleton
import Type.Size.Countable
import Type.Size.Finite
import Type.Size.Proofs
import Type.Size
import Type.WellOrdering
import Type


module Example where

import Level
open import Signature
open import Function
open import Data.Empty
open import Data.Unit
open import Data.Nat
open import Data.Fin
open import Data.Product as Prod renaming (Σ to ⨿)
open import Data.Sum as Sum
open import Relation.Nullary
open import Relation.Unary hiding (_⇒_)
open import Relation.Binary.PropositionalEquality hiding ([_])
open ≡-Reasoning

postulate
  ext : Extensionality Level.zero Level.zero

------
-- Examples
-----

module NatProg where
  Σ : Sig
  ∥ Σ ∥ = Fin 3
  ar Σ zero                         = Fin 0 -- 0
  ar Σ (suc zero)                   = Fin 1 -- succ
  ar Σ (suc (suc _))                = Fin 1 -- nat

  open import Terms Σ
  V = ℕ
  Z S N : ∥ Σ ∥
  Z     = # 0
  S     = # 1
  N     = # 2

  z : T V
  z = μ (ι (Z , (λ ())))

  s nat : T V → T V
  s   t = μ (ι (S , (λ _ → t)))
  nat t = μ (ι (N , (λ _ → t)))

  z∞ : T∞ V
  z∞ = χ z

  s∞ nat∞ : ∀{X} → T∞ X → T∞ X
  s∞   t = μ∞ (ι∞ (S , (λ _ → t)))
  nat∞ t = μ∞ (ι∞ (N , (λ _ → t)))

  inf : T∞ ⊥
  inf = corec (λ x → inj₁ (S , (λ _ → tt))) tt

  inf-nat : T∞ ⊥
  inf-nat = nat∞ inf

  open import Program Σ V

  -- | Program consisting of
  -- ⇒ nat(0)
  -- nat(n) ⇒ nat(s n)
  P : Program
  P = ((0 , (λ ())) , ( , clauses))
    where
      clauses : Fin 2 → Clause
      clauses zero             = (0 , (λ ())) ⊢ nat z
      clauses (suc _)          = (1 , b)      ⊢ nat (s n)
        where
          n = η 0

          b : Fin 1 → T V
          b _ = nat n

  open import Herbrand Σ V P

  lem : ¬ (∃ λ σ → (inf ~ app∞ σ (χ (geth-ν P (# 0)))))
  lem (σ , p) with out~ p
  lem (σ , p) | () , _

  bad-ν : inf-nat ∈ Herbrand-ν
  bw-closed bad-ν = inj₁ p
    where
      p : (i : dom-ν P) {σ : V → T∞ ⊥} →
          inf-nat ~ (app∞ σ (χ (geth-ν P i))) →
          (j : dom (getb-ν P i)) →
          app∞ σ (χ (get (getb-ν P i) j)) ∈ Herbrand-ν

{-
      p i {σ} p j with out inf-nat | out (σ 0) | out~ p
      p i p j | inj₁ (zero , α) | v | r = {!!}
      p i p j | inj₁ (suc zero , α) | v | r = {!!}
      p i p j | inj₁ (suc (suc _) , α) | v | r = {!!}
      p i p j | inj₂ () | v | r
-}
      p i {σ} p j with out (σ 0) | out~ p
      p zero p () | u | refl , r
      p (suc i) p zero | inj₁ (zero , _) | refl , r = {!!}
      p (suc i) p zero | inj₁ (suc zero , _) | refl , r = {!!}
      p (suc i) p zero | inj₁ (suc (suc _) , proj₂) | refl , r = {!!}
      p (suc i) p zero | inj₂ () | refl , r
      p (suc _) p (suc ()) | u | refl , r

    {-
      f : ?
      f i {σ} p j with out~ p
      ... | u = ?
-}
  bad : inf-nat ∈ Herbrand-μ
  bad = coind-μ bad-ν

{-

module BitList where
  Σ : Sig
  ∥ Σ ∥ = Fin 6
  ar Σ zero                            = Fin 0 -- 0
  ar Σ (suc zero)                      = Fin 0 -- 1
  ar Σ (suc (suc zero))                = Fin 1 -- bit(x)
  ar Σ (suc (suc (suc zero)))          = Fin 1 -- blist(x)
  ar Σ (suc (suc (suc (suc zero))))    = Fin 0 -- nil
  ar Σ (suc (suc (suc (suc (suc f))))) = Fin 2 -- cons(x,y)

  open import Terms Σ
  V = ℕ

  Z O Bit BList Nil Cons : ∥ Σ ∥
  Z     = # 0
  O     = # 1
  Bit   = # 2
  BList = # 3
  Nil   = # 4
  Cons  = # 5

  z o nil : T V
  z   = μ (ι (Z , (λ ())))
  o   = μ (ι (O , (λ ())))
  nil = μ (ι (Nil , (λ ())))

  bit blist : T V → T V
  bit   t = μ (ι (Bit , (λ _ → t)))
  blist t = μ (ι (BList , (λ _ → t)))

  bin-branch : {X : Set} → X → X → Fin 2 → X
  bin-branch x y zero    = x
  bin-branch x y (suc _) = y

  cons-br-distr : ∀{X Y} (t s : X) (f : X → Y) →
                  f ∘ bin-branch t s ≡ bin-branch (f t) (f s)
  cons-br-distr t s f = ext p
    where
      p : (i : Fin 2) → f (bin-branch t s i) ≡ bin-branch (f t) (f s) i
      p zero    = refl
      p (suc _) = refl

  cons : T V → T V → T V
  cons t s = μ (ι (Cons , bin-branch t s))

  bit0 bit1 : T V
  bit0 = bit z
  bit1 = bit o

  open import Program Σ V

  -- | Program consisting of
  -- ⇒ bit(0)
  -- ⇒ bit(1)
  -- ⇒ blist(nil)
  -- bit(x), blist(y) ⇒ blist(cons(x,y))
  P : Program
  P = , clauses
    where
      clauses : Fin 4 → Clause
      clauses zero                = (0 , (λ ())) ⊢ bit0
      clauses (suc zero)          = (0 , (λ ())) ⊢ bit1
      clauses (suc (suc zero))    = (0 , (λ ())) ⊢ nil
      clauses (suc (suc (suc c))) = (2 , b)      ⊢ blist (cons (η 0) (η 1))
        where
          b : Fin 2 → T V
          b zero = bit (η 0)
          b (suc i) = blist (η 1)

  open import Rewrite Σ V P

  X S bitX : T V
  X = η 0
  S = blist (cons X (cons X nil))
  bitX = bit X

  bitX-val : Val bitX
  bitX-val zero                ()      x
  bitX-val (suc zero)          ()      x
  bitX-val (suc (suc zero))    ()      x
  bitX-val (suc (suc (suc _))) zero    ()
  bitX-val (suc (suc (suc _))) (suc _) ()

  step1 : S ⟿ bitX
  step1 = rew-step (# 3) (# 0) {σ} σ-match
    where
      σ : Subst V V
      σ zero = X
      σ (suc zero) = cons X nil
      σ (suc (suc n)) = η (suc (suc n))

      σ-match : matches (geth P (# 3)) S σ
      σ-match =
        begin
          app σ (blist (cons X (η 1)))
        ≡⟨ refl ⟩
          μ (T₁ σ (blist (cons X (η 1))))
        ≡⟨ refl ⟩
          μ (T₁ σ (μ (ι (BList , (λ _ → (cons X (η 1)))))))
        ≡⟨ refl ⟩
          μ (μ (ι (BList , (λ _ → T₁ σ (cons X (η 1))))))
        ≡⟨ refl ⟩
          μ (μ (ι (BList , (λ _ → T₁ σ (μ (ι (Cons , bin-branch X (η 1))))))))
        ≡⟨ refl ⟩
          μ (μ (ι (BList , (λ _ → μ (ι (Cons , T₁ σ ∘ (bin-branch X (η 1))))))))
        ≡⟨ cong (λ u → μ (μ (ι (BList , (λ _ → μ (ι (Cons , u)))))))
                (cons-br-distr X (η 1) (T₁ σ)) ⟩
          μ (μ (ι (BList , (λ _ →
               μ (ι (Cons , (bin-branch (T₁ σ X) (T₁ σ (η 1)))))))))
        ≡⟨ refl ⟩
          μ (μ (ι (BList , (λ _ →
               μ (ι (Cons , (bin-branch (η (σ 0)) (η (σ 1)))))))))
        ≡⟨ cong (λ u → μ (μ (ι (BList , (λ _ → μ (ι (Cons , u)))))))
                (sym (cons-br-distr (σ 0) (σ 1) η)) ⟩
          μ (μ (ι (BList , (λ _ →
               μ (ι (Cons , (η ∘ (bin-branch (σ 0) (σ 1)))))))))
        ≡⟨ refl ⟩
          blist (cons (σ 0) (σ 1))
        ≡⟨ refl ⟩
          blist (cons X (cons X nil))
        ≡⟨ refl ⟩
          S
        ∎

  term1 : S ↓ bitX
  term1 = step bitX bitX (val bitX-val) step1

  -- Problem: The substitution needs to match _all_ leaves!!!
-}


------------------------------------------------------------------------
-- A stream equality universe
------------------------------------------------------------------------

module Stream.Equality where

open import Codata.Musical.Notation
open import Stream hiding (_⋎_)
open import Stream.Programs
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Data.Vec using (Vec; []; _∷_)

infixr 5 _≺_
infix  3 _≃_ _≅_ _≊_ _∎
infixr 2 _≊⟨_⟩_ _≡⟨_⟩_

mutual

  _≊_ : ∀ {A} (xs ys : Prog A) → Set1
  xs ≊ ys = ⟦ xs ⟧ ≅ ⟦ ys ⟧

  data _≅_ {A} : (xs ys : Stream A) → Set1 where
    _≺_          : ∀ {x y xs ys}
                   (x≡ : x ≡ y) (xs≈ : ∞ (♭ xs ≅ ♭ ys)) →
                   x ≺ xs ≅ y ≺ ys
    _≊⟨_⟩_       : ∀ xs {ys zs}
                   (xs≈ys : ⟦ xs ⟧ ≅ ys) (ys≈zs : ys ≅ zs) → ⟦ xs ⟧ ≅ zs
    _≡⟨_⟩_       : ∀ xs {ys zs}
                   (xs≡ys : ⟦ xs ⟧ ≡ ys) (ys≈zs : ys ≅ zs) → ⟦ xs ⟧ ≅ zs
    ≅-sym        : ∀ {xs ys} (xs≈ys : xs ≅ ys) → ys ≅ xs
    ·-cong       : ∀ {B}
                   (f : B → A) xs ys (xs≈ys : xs ≊ ys) →
                   f · xs ≊ f · ys
    ⟨_⟩-cong     : ∀ {B C} (_∙_ : B → C → A)
                   xs xs′ (xs≈xs′ : xs ≊ xs′)
                   ys ys′ (ys≈ys′ : ys ≊ ys′) →
                   xs ⟨ _∙_ ⟩ ys ≊ xs′ ⟨ _∙_ ⟩ ys′
    ⋎-cong       : ∀ xs xs′ (xs≈xs′ : xs ≊ xs′)
                          ys ys′ (ys≈ys′ : ys ≊ ys′) →
                   xs ⋎ ys ≊ xs′ ⋎ ys′
    ≺≺-cong      : ∀ {n}
                   (xs xs′ : Vec A n) (xs≡xs′ : xs ≡ xs′)
                   ys ys′ (ys≈ys′ : ys ≊ ys′) →
                   xs ≺≺ ys ≊ xs′ ≺≺ ys′

data _≃_ {A} : (xs ys : Stream A) → Set1 where
  _≺_ : ∀ {x y xs ys}
        (x≡ : x ≡ y) (xs≈ : ♭ xs ≅ ♭ ys) → x ≺ xs ≃ y ≺ ys

≅⇒≃ : ∀ {A} {xs ys : Stream A} → xs ≅ ys → xs ≃ ys
≅⇒≃ (x≡ ≺ xs≈)                 = x≡ ≺ ♭ xs≈
≅⇒≃ (xs ≊⟨ xs≈ys ⟩ ys≈zs)      with whnf xs | ≅⇒≃ xs≈ys | ≅⇒≃ ys≈zs
≅⇒≃ (xs ≊⟨ xs≈ys ⟩ ys≈zs)      | x ≺ xs′ | x≡y ≺ xs≈ys′ | y≡z ≺ ys≈zs′ =
                                 trans x≡y y≡z ≺ (xs′ ≊⟨ xs≈ys′ ⟩ ys≈zs′)
≅⇒≃ (xs ≡⟨ refl ⟩ ys≈zs)       = ≅⇒≃ ys≈zs
≅⇒≃ (≅-sym xs≈ys)              with ≅⇒≃ xs≈ys
≅⇒≃ (≅-sym xs≈ys)              | x≡y ≺ xs≈ys′ = sym x≡y ≺ ≅-sym xs≈ys′
≅⇒≃ (·-cong f xs ys xs≈ys)     with whnf xs | whnf ys | ≅⇒≃ xs≈ys
≅⇒≃ (·-cong f xs ys xs≈ys)     | x ≺ xs′ | y ≺ ys′ | x≡y ≺ xs≈ys′ =
                                 cong f x≡y ≺ ·-cong f xs′ ys′ xs≈ys′
≅⇒≃ (⟨ ∙ ⟩-cong xs xs′ xs≈xs′
                ys ys′ ys≈ys′) with whnf xs | whnf xs′ | ≅⇒≃ xs≈xs′
                                  | whnf ys | whnf ys′ | ≅⇒≃ ys≈ys′
≅⇒≃ (⟨ ∙ ⟩-cong xs xs′ xs≈xs′
                ys ys′ ys≈ys′) | _ ≺ txs | _ ≺ txs′ | x≡y  ≺ txs≈txs′
                               | _ ≺ tys | _ ≺ tys′ | x≡y′ ≺ tys≈tys′ =
                                 cong₂ ∙ x≡y x≡y′ ≺
                                 ⟨ ∙ ⟩-cong txs txs′ txs≈txs′
                                            tys tys′ tys≈tys′
≅⇒≃ (⋎-cong xs xs′ xs≈xs′
            ys ys′ ys≈ys′)     with whnf xs | whnf xs′ | ≅⇒≃ xs≈xs′
≅⇒≃ (⋎-cong xs xs′ xs≈xs′
            ys ys′ ys≈ys′)     | _ ≺ txs | _ ≺ txs′ | x≡y ≺ txs≈txs′ =
                                 x≡y ≺ ⋎-cong ys  ys′  ys≈ys′
                                              txs txs′ txs≈txs′
≅⇒≃ (≺≺-cong [] [] refl
             ys ys′ ys≈ys′)    = ≅⇒≃ ys≈ys′
≅⇒≃ (≺≺-cong
      (x ∷ xs) .(_ ∷ _) refl
      ys ys′ ys≈ys′)           = refl ≺ ≺≺-cong xs xs refl ys ys′ ys≈ys′

mutual

  ≃⇒≈ : ∀ {A} {xs ys : Stream A} → xs ≃ ys → xs ≈ ys
  ≃⇒≈ (refl ≺ xs≈) = refl ≺ ♯ ≅⇒≈ xs≈

  ≅⇒≈ : ∀ {A} {xs ys : Stream A} → xs ≅ ys → xs ≈ ys
  ≅⇒≈ xs≈ = ≃⇒≈ (≅⇒≃ xs≈)

≊⇒≈ : ∀ {A} {xs ys : Prog A} → xs ≊ ys → ⟦ xs ⟧ ≈ ⟦ ys ⟧
≊⇒≈ = ≅⇒≈

≈⇒≅ : ∀ {A} {xs ys : Stream A} → xs ≈ ys → xs ≅ ys
≈⇒≅ (refl ≺ xs≈) = refl ≺ ♯ ≈⇒≅ (♭ xs≈)

_∎ : ∀ {A} (xs : Prog A) → xs ≊ xs
xs ∎ = ≈⇒≅ (Setoid.refl (Stream.setoid _))

≊-η : ∀ {A} (xs : Prog A) → xs ≊ headP xs ≺ ♯ tailP xs
≊-η xs with whnf xs
≊-η xs | x ≺ xs′ = refl ≺ ♯ (xs′ ∎)


{- Byzantine Fault Tolerant Consensus Verification in Agda, version 0.9.

   Copyright (c) 2020, 2021 Oracle and/or its affiliates.
   Licensed under the Universal Permissive License v 1.0 as shown at https://opensource.oracle.com/licenses/upl
-}

module Dijkstra.All where

open import Dijkstra.Syntax public
open import Dijkstra.RWS public
open import Dijkstra.RWS.Syntax public
open import Dijkstra.EitherD public
open import Dijkstra.EitherD.Syntax public
open import Dijkstra.EitherLike public


-- Andreas, 2019-06-25, issue #3855 reported by nad
-- Constraint solver needs to respect erasure.

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

-- rejected : (@0 A : Set) → A ≡ A
-- rejected A = refl A

should-also-be-rejected : (@0 A : Set) → A ≡ A
should-also-be-rejected A = refl _


{-

An induction principle for paths in a pushout, described in
Kraus and von Raumer, "Path Spaces of Higher Inductive Types in Homotopy Type Theory"
https://arxiv.org/abs/1901.06022

-}

{-# OPTIONS --cubical --safe #-}
module Cubical.HITs.Pushout.KrausVonRaumer where

open import Cubical.Foundations.Everything
open import Cubical.Data.Sigma
open import Cubical.HITs.Pushout.Base

private
  interpolate : ∀ {ℓ} {A : Type ℓ} {x y z : A} (q : y ≡ z)
    → PathP (λ i → x ≡ q i → x ≡ z) (_∙ q) (idfun _)
  interpolate q i p j =
    hcomp
      (λ k → λ
        { (j = i0) → p i0
        ; (j = i1) → q (i ∨ k)
        ; (i = i1) → p j
        })
      (p j)

  interpolateCompPath : ∀ {ℓ} {A : Type ℓ} {x y : A} (p : x ≡ y) {z : A} (q : y ≡ z)
   → (λ i → interpolate q i (λ j → compPath-filler p q i j)) ≡ refl
  interpolateCompPath p =
    J (λ z q → (λ i → interpolate q i (λ j → compPath-filler p q i j)) ≡ refl)
      (homotopySymInv (λ p i j → compPath-filler p refl (~ i) j) p)

module ElimL {ℓ ℓ' ℓ'' ℓ'''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
  {f : A → B} {g : A → C} {b₀ : B}
  (P : ∀ b → Path (Pushout f g) (inl b₀) (inl b) → Type ℓ''')
  (Q : ∀ c → Path (Pushout f g) (inl b₀) (inr c) → Type ℓ''')
  (r : P b₀ refl)
  (e : (a : A) (q : inl b₀ ≡ inl (f a)) → P (f a) q ≃ Q (g a) (q ∙ push a))
  where

  Codes : (d : Pushout f g) (q : inl b₀ ≡ d) → Type ℓ'''
  Codes (inl b) q = P b q
  Codes (inr c) q = Q c q
  Codes (push a i) q =
    Glue
      (Q (g a) (interpolate (push a) i q))
      (λ
        { (i = i0) → _ , e a q
        ; (i = i1) → _ , idEquiv (Q (g a) q)
        })

  elimL : ∀ b q → P b q
  elimL _ = J Codes r

  elimR : ∀ c q → Q c q
  elimR _ = J Codes r

  refl-β : elimL b₀ refl ≡ r
  refl-β = transportRefl _

  push-β : (a : A) (q : inl b₀ ≡ inl (f a))
    → elimR (g a) (q ∙ push a) ≡ e a q .fst (elimL (f a) q)
  push-β a q =
    J-∙ Codes r q (push a)
    ∙ fromPathP
      (subst
       (λ α → PathP (λ i → Q (g a) (α i)) (e a q .fst (elimL (f a) q)) (e a q .fst (elimL (f a) q)))
       (interpolateCompPath q (push a) ⁻¹)
       refl)

module ElimR {ℓ ℓ' ℓ'' ℓ'''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
  {f : A → B} {g : A → C} {c₀ : C}
  (P : ∀ b → Path (Pushout f g) (inr c₀) (inl b) → Type ℓ''')
  (Q : ∀ c → Path (Pushout f g) (inr c₀) (inr c) → Type ℓ''')
  (r : Q c₀ refl)
  (e : (a : A) (q : inr c₀ ≡ inl (f a)) → P (f a) q ≃ Q (g a) (q ∙ push a))
  where

  Codes : (d : Pushout f g) (q : inr c₀ ≡ d) → Type ℓ'''
  Codes (inl b) q = P b q
  Codes (inr c) q = Q c q
  Codes (push a i) q =
    Glue
      (Q (g a) (interpolate (push a) i q))
      (λ
        { (i = i0) → _ , e a q
        ; (i = i1) → _ , idEquiv (Q (g a) q)
        })

  elimL : ∀ b q → P b q
  elimL _ = J Codes r

  elimR : ∀ c q → Q c q
  elimR _ = J Codes r

  refl-β : elimR c₀ refl ≡ r
  refl-β = transportRefl _

  push-β : (a : A) (q : inr c₀ ≡ inl (f a))
    → elimR (g a) (q ∙ push a) ≡ e a q .fst (elimL (f a) q)
  push-β a q =
    J-∙ Codes r q (push a)
    ∙ fromPathP
      (subst
       (λ α → PathP (λ i → Q (g a) (α i)) (e a q .fst (elimL (f a) q)) (e a q .fst (elimL (f a) q)))
       (interpolateCompPath q (push a) ⁻¹)
       refl)

-- Example application: pushouts preserve embeddings

isEmbeddingInr : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
  {f : A → B} (g : A → C)
  → isEmbedding f → isEmbedding (inr {f = f} {g = g})
isEmbeddingInr {f = f} g fEmb c₀ c₁ =
  isoToIsEquiv (iso _ (fst ∘ bwd c₁) (snd ∘ bwd c₁) bwdCong)
  where
  Q : ∀ c → inr c₀ ≡ inr c → Type _
  Q _ q = fiber (cong inr) q

  P : ∀ b → inr c₀ ≡ inl b → Type _
  P b p = Σ[ u ∈ fiber f b ] Q _ (p ∙ cong inl (u .snd ⁻¹) ∙ push (u .fst))

  module Bwd = ElimR P Q
    (refl , refl)
    (λ a p →
      subst
        (P (f a) p  ≃_)
        (cong (λ w → fiber (cong inr) (p ∙ w)) (lUnit (push a) ⁻¹))
        (Σ-contractFst (inhProp→isContr (a , refl) (isEmbedding→hasPropFibers fEmb (f a)))))

  bwd : ∀ c → (t : inr c₀ ≡ inr c) → fiber (cong inr) t
  bwd = Bwd.elimR

  bwdCong : ∀ {c} → (r : c₀ ≡ c) → bwd c (cong inr r) .fst ≡ r
  bwdCong = J (λ c r → bwd c (cong inr r) .fst ≡ r) (cong fst Bwd.refl-β)


{-# OPTIONS --cubical --no-import-sorts --safe #-}
module Cubical.Algebra.RingSolver.CommRingEvalHom where

open import Cubical.Foundations.Prelude

open import Cubical.Data.Nat using (ℕ)
open import Cubical.Data.FinData
open import Cubical.Data.Vec
open import Cubical.Data.Bool.Base

open import Cubical.Algebra.RingSolver.RawAlgebra
open import Cubical.Algebra.RingSolver.CommRingHornerForms
open import Cubical.Algebra.CommRing
open import Cubical.Algebra.Ring

private
  variable
    ℓ : Level

module HomomorphismProperties (R : CommRing {ℓ}) where
  private
    νR = CommRing→RawℤAlgebra R
  open CommRingStr (snd R)
  open Theory (CommRing→Ring R)
  open IteratedHornerOperations νR

  EvalHom+0 : (n : ℕ) (P : IteratedHornerForms νR n) (xs : Vec ⟨ νR ⟩ n)
      → eval n (0ₕ +ₕ P) xs ≡ eval n P xs
  EvalHom+0 ℕ.zero (const x) [] = cong (scalar R) (+Ridℤ x)
  EvalHom+0 (ℕ.suc n) P xs = refl

  Eval0H : (n : ℕ) (xs : Vec ⟨ νR ⟩ n)
         → eval {A = νR} n 0ₕ xs ≡ 0r
  Eval0H .ℕ.zero [] = refl
  Eval0H .(ℕ.suc _) (x ∷ xs) = refl

  combineCasesEval :
    {n : ℕ}  (P : IteratedHornerForms νR (ℕ.suc n)) (Q : IteratedHornerForms νR n)
    (x : (fst R)) (xs : Vec ⟨ νR ⟩ n)
    → eval (ℕ.suc n) (P ·X+ Q) (x ∷ xs) ≡ (eval (ℕ.suc n) P (x ∷ xs)) · x + eval n Q xs
  combineCasesEval {n = n} 0H Q x xs =
    eval n Q xs               ≡⟨ sym (+Lid _) ⟩
    0r + eval n Q xs          ≡[ i ]⟨ 0LeftAnnihilates x (~ i) + eval n Q xs ⟩
    0r · x + eval n Q xs ∎
  combineCasesEval {n = n} (P ·X+ P₁) Q x xs = refl

  Eval1ₕ : (n : ℕ) (xs : Vec ⟨ νR ⟩ n)
         → eval {A = νR} n 1ₕ xs ≡ 1r
  Eval1ₕ .ℕ.zero [] = refl
  Eval1ₕ (ℕ.suc n) (x ∷ xs) =
    eval (ℕ.suc n) 1ₕ (x ∷ xs)                             ≡⟨ refl ⟩
    eval (ℕ.suc n) (0H ·X+ 1ₕ) (x ∷ xs)                    ≡⟨ combineCasesEval 0H 1ₕ x xs ⟩
    eval {A = νR} (ℕ.suc n) 0H (x ∷ xs) · x + eval n 1ₕ xs ≡⟨ cong (λ u → u · x + eval n 1ₕ xs)
                                                                   (Eval0H _ (x ∷ xs)) ⟩
    0r · x + eval n 1ₕ xs                                   ≡⟨ cong (λ u → 0r · x + u)
                                                                    (Eval1ₕ _ xs) ⟩
    0r · x + 1r                                            ≡⟨ cong (λ u → u + 1r)
                                                                   (0LeftAnnihilates _) ⟩
    0r + 1r                                                ≡⟨ +Lid _ ⟩
    1r ∎

  -EvalDist :
    (n : ℕ) (P : IteratedHornerForms νR n) (xs : Vec ⟨ νR ⟩ n)
    → eval n (-ₕ P) xs ≡ - eval n P xs
  -EvalDist .ℕ.zero (const x) []   = -DistScalar R x
  -EvalDist          n       0H  xs =
    eval n (-ₕ 0H) xs  ≡⟨ Eval0H n xs ⟩
    0r                        ≡⟨ sym 0Selfinverse ⟩
    - 0r                      ≡⟨ cong -_ (sym (Eval0H n xs)) ⟩
    - eval n 0H xs     ∎
  -EvalDist .(ℕ.suc _) (P ·X+ Q) (x ∷ xs) =
      eval (ℕ.suc _) (-ₕ (P ·X+ Q)) (x ∷ xs)
    ≡⟨ refl ⟩
      eval (ℕ.suc _) ((-ₕ P) ·X+ (-ₕ Q)) (x ∷ xs)
    ≡⟨ combineCasesEval (-ₕ P) (-ₕ Q) x xs ⟩
      (eval (ℕ.suc _) (-ₕ P) (x ∷ xs)) · x + eval _ (-ₕ Q) xs
    ≡⟨ cong (λ u → u · x + eval _ (-ₕ Q) xs) (-EvalDist _ P _) ⟩
      (- eval (ℕ.suc _) P (x ∷ xs)) · x + eval _ (-ₕ Q) xs
    ≡⟨ cong (λ u → (- eval (ℕ.suc _) P (x ∷ xs)) · x + u) (-EvalDist _ Q _) ⟩
      (- eval (ℕ.suc _) P (x ∷ xs)) · x + - eval _ Q xs
    ≡[ i ]⟨ -DistL· (eval (ℕ.suc _) P (x ∷ xs)) x i +  - eval _ Q xs ⟩
      - ((eval (ℕ.suc _) P (x ∷ xs)) · x) + (- eval _ Q xs)
    ≡⟨ -Dist _ _ ⟩
      - ((eval (ℕ.suc _) P (x ∷ xs)) · x + eval _ Q xs)
    ≡[ i ]⟨ - combineCasesEval P Q x xs (~ i) ⟩
      - eval (ℕ.suc _) (P ·X+ Q) (x ∷ xs) ∎

  combineCases+ : (n : ℕ) (P Q : IteratedHornerForms νR (ℕ.suc n))
                  (r s : IteratedHornerForms νR n)
                  (xs : Vec ⟨ νR ⟩ (ℕ.suc n))
                  → eval (ℕ.suc n) ((P ·X+ r) +ₕ (Q ·X+ s)) xs
                  ≡ eval (ℕ.suc n) ((P +ₕ Q) ·X+ (r +ₕ s)) xs
  combineCases+ ℕ.zero P Q r s xs with (P +ₕ Q) | (r +ₕ s)
  ... | (_ ·X+ _) | const (pos (ℕ.suc _)) = refl
  ... | (_ ·X+ _) | const (negsuc _) = refl
  ... | (_ ·X+ _) | const (pos ℕ.zero)  = refl
  ... | 0H  | const (pos (ℕ.suc _)) = refl
  ... | 0H  | const (negsuc _) = refl
  combineCases+ ℕ.zero P Q r s (x ∷ []) | 0H  | const (pos ℕ.zero) = refl
  combineCases+ (ℕ.suc n) P Q r s (x ∷ xs) with (P +ₕ Q) | (r +ₕ s)
  ... | (_ ·X+ _) | (_ ·X+ _) = refl
  ... | (_ ·X+ _) | 0H  = refl
  ... | 0H        | (_ ·X+ _) = refl
  ... | 0H        | 0H  = sym (Eval0H (ℕ.suc n) xs)

  +Homeval :
    (n : ℕ) (P Q : IteratedHornerForms νR n) (xs : Vec ⟨ νR ⟩ n)
    → eval n (P +ₕ Q) xs ≡ (eval n P xs) + (eval n Q xs)
  +Homeval .ℕ.zero (const x) (const y) [] = +HomScalar R x y
  +Homeval n 0H Q xs =
    eval n (0H +ₕ Q) xs            ≡⟨ refl ⟩
    eval n Q xs                    ≡⟨ sym (+Lid _) ⟩
    0r + eval n Q xs               ≡⟨ cong (λ u → u + eval n Q xs) (sym (Eval0H n xs)) ⟩
    eval n 0H xs + eval n Q xs ∎
  +Homeval .(ℕ.suc _) (P ·X+ Q) 0H xs =
    eval (ℕ.suc _) ((P ·X+ Q) +ₕ 0H) xs                    ≡⟨ refl ⟩
    eval (ℕ.suc _) (P ·X+ Q) xs                            ≡⟨ sym (+Rid _) ⟩
    eval (ℕ.suc _) (P ·X+ Q) xs + 0r
   ≡⟨ cong (λ u → eval (ℕ.suc _) (P ·X+ Q) xs + u) (sym (Eval0H _ xs)) ⟩
    eval (ℕ.suc _) (P ·X+ Q) xs + eval (ℕ.suc _) 0H xs ∎
  +Homeval .(ℕ.suc _) (P ·X+ Q) (S ·X+ T) (x ∷ xs) =
    eval (ℕ.suc _) ((P ·X+ Q) +ₕ (S ·X+ T)) (x ∷ xs)
   ≡⟨ combineCases+ _ P S Q T (x ∷ xs) ⟩
    eval (ℕ.suc _) ((P +ₕ S) ·X+ (Q +ₕ T)) (x ∷ xs)
   ≡⟨ combineCasesEval (P +ₕ S) (Q +ₕ T) x xs ⟩
    (eval (ℕ.suc _) (P +ₕ S) (x ∷ xs)) · x + eval _ (Q +ₕ T) xs
   ≡⟨ cong (λ u → (eval (ℕ.suc _) (P +ₕ S) (x ∷ xs)) · x + u) (+Homeval _ Q T xs) ⟩
    (eval (ℕ.suc _) (P +ₕ S) (x ∷ xs)) · x + (eval _ Q xs + eval _ T xs)
   ≡⟨ cong (λ u → u · x + (eval _ Q xs + eval _ T xs)) (+Homeval (ℕ.suc _) P S (x ∷ xs)) ⟩
    (eval (ℕ.suc _) P (x ∷ xs) + eval (ℕ.suc _) S (x ∷ xs)) · x
    + (eval _ Q xs + eval _ T xs)
   ≡⟨ cong (λ u → u + (eval _ Q xs + eval _ T xs)) (·Ldist+ _ _ _) ⟩
    (eval (ℕ.suc _) P (x ∷ xs)) · x + (eval (ℕ.suc _) S (x ∷ xs)) · x
    + (eval _ Q xs + eval _ T xs)
   ≡⟨ +ShufflePairs _ _ _ _ ⟩
    ((eval (ℕ.suc _) P (x ∷ xs)) · x + eval _ Q xs)
    + ((eval (ℕ.suc _) S (x ∷ xs)) · x + eval _ T xs)
   ≡[ i ]⟨ combineCasesEval P Q x xs (~ i) + combineCasesEval S T x xs (~ i) ⟩
    eval (ℕ.suc _) (P ·X+ Q) (x ∷ xs)
    + eval (ℕ.suc _) (S ·X+ T) (x ∷ xs) ∎

  ⋆Homeval : (n : ℕ)
             (r : IteratedHornerForms νR n)
             (P : IteratedHornerForms νR (ℕ.suc n)) (x : ⟨ νR ⟩) (xs : Vec ⟨ νR ⟩ n)
           → eval (ℕ.suc n) (r ⋆ P) (x ∷ xs) ≡ eval n r xs · eval (ℕ.suc n) P (x ∷ xs)

  ⋆0LeftAnnihilates :
    (n : ℕ) (P : IteratedHornerForms νR (ℕ.suc n)) (xs : Vec ⟨ νR ⟩ (ℕ.suc n))
    → eval (ℕ.suc n) (0ₕ ⋆ P) xs ≡ 0r
  ⋆0LeftAnnihilates n 0H xs = Eval0H (ℕ.suc n) xs
  ⋆0LeftAnnihilates ℕ.zero (P ·X+ Q) (x ∷ xs) = refl
  ⋆0LeftAnnihilates (ℕ.suc n) (P ·X+ Q) (x ∷ xs) = refl

  ·0LeftAnnihilates :
    (n : ℕ) (P : IteratedHornerForms νR n) (xs : Vec ⟨ νR ⟩ n)
    → eval n (0ₕ ·ₕ P) xs ≡ 0r
  ·0LeftAnnihilates .ℕ.zero (const x) xs =
    eval ℕ.zero (const _) xs ≡⟨ Eval0H _ xs ⟩ 0r ∎
  ·0LeftAnnihilates .(ℕ.suc _) 0H xs = Eval0H _ xs
  ·0LeftAnnihilates .(ℕ.suc _) (P ·X+ P₁) xs = Eval0H _ xs

  ·Homeval : (n : ℕ) (P Q : IteratedHornerForms νR n) (xs : Vec ⟨ νR ⟩ n)
    → eval n (P ·ₕ Q) xs ≡ (eval n P xs) · (eval n Q xs)

  combineCases⋆ : (n : ℕ) (xs : Vec ⟨ νR ⟩ (ℕ.suc n))
                → (r : IteratedHornerForms νR n)
                → (P : IteratedHornerForms νR (ℕ.suc n))
                → (Q : IteratedHornerForms νR n)
                → eval (ℕ.suc n) (r ⋆ (P ·X+ Q)) xs ≡ eval (ℕ.suc n) ((r ⋆ P) ·X+ (r ·ₕ Q)) xs
  combineCases⋆ .ℕ.zero (x ∷ []) (const (pos ℕ.zero)) P Q =
      eval _ (const (pos ℕ.zero) ⋆ (P ·X+ Q))  (x ∷ [])                          ≡⟨ refl ⟩
      eval _ 0ₕ  (x ∷ [])                                                         ≡⟨ refl ⟩
      0r             ≡⟨ sym (+Rid _) ⟩
      0r + 0r        ≡[ i ]⟨ 0LeftAnnihilates x (~ i) + 0r ⟩
      0r · x + 0r    ≡[ i ]⟨ ⋆0LeftAnnihilates _ P (x ∷ []) (~ i) · x + ·0LeftAnnihilates _ Q [] (~ i) ⟩
      eval _ (const (pos ℕ.zero) ⋆ P) (x ∷ []) · x + eval _ (const (pos ℕ.zero) ·ₕ Q) []
    ≡⟨ sym (combineCasesEval (const (pos ℕ.zero) ⋆ P) (const (pos ℕ.zero) ·ₕ Q) x []) ⟩
      eval _ ((const (pos ℕ.zero) ⋆ P) ·X+ (const (pos ℕ.zero) ·ₕ Q))  (x ∷ []) ∎
  combineCases⋆ .ℕ.zero (x ∷ []) (const (pos (ℕ.suc n))) P Q = refl
  combineCases⋆ .ℕ.zero (x ∷ []) (const (negsuc n)) P Q = refl
  combineCases⋆ .(ℕ.suc _) (x ∷ xs) 0H P Q =
      eval _ (0H ⋆ (P ·X+ Q))  (x ∷ xs)    ≡⟨ refl ⟩
      eval _ 0ₕ  (x ∷ [])                  ≡⟨ refl ⟩
      0r             ≡⟨ sym (+Rid _) ⟩
      0r + 0r        ≡[ i ]⟨ 0LeftAnnihilates x (~ i) + 0r ⟩
      0r · x + 0r    ≡[ i ]⟨ ⋆0LeftAnnihilates _ P (x ∷ xs) (~ i) · x + ·0LeftAnnihilates _ Q xs (~ i) ⟩
      eval _ (0H ⋆ P) (x ∷ xs) · x + eval _ (0H ·ₕ Q) xs
    ≡⟨ sym (combineCasesEval (0H ⋆ P) (0H ·ₕ Q) x xs) ⟩
      eval _ ((0H ⋆ P) ·X+ (0H ·ₕ Q))  (x ∷ xs) ∎
  combineCases⋆ .(ℕ.suc _) (x ∷ xs) (r ·X+ r₁) P Q = refl

  ⋆Homeval n r 0H x xs =
    eval (ℕ.suc n) (r ⋆ 0H) (x ∷ xs)         ≡⟨ refl ⟩
    0r                                       ≡⟨ sym (0RightAnnihilates _) ⟩
    eval n r xs · 0r                         ≡⟨ refl ⟩
    eval n r xs · eval {A = νR} (ℕ.suc n) 0H (x ∷ xs) ∎
  ⋆Homeval n r (P ·X+ Q) x xs =
      eval (ℕ.suc n) (r ⋆ (P ·X+ Q)) (x ∷ xs)                    ≡⟨ combineCases⋆ n (x ∷ xs) r P Q ⟩
      eval (ℕ.suc n) ((r ⋆ P) ·X+ (r ·ₕ Q)) (x ∷ xs)
    ≡⟨ combineCasesEval (r ⋆ P) (r ·ₕ Q) x xs ⟩
      (eval (ℕ.suc n) (r ⋆ P) (x ∷ xs)) · x + eval n (r ·ₕ Q) xs
    ≡⟨ cong (λ u → u · x + eval n (r ·ₕ Q) xs) (⋆Homeval n r P x xs) ⟩
      (eval n r xs · eval (ℕ.suc n) P (x ∷ xs)) · x + eval n (r ·ₕ Q) xs
    ≡⟨ cong (λ u → (eval n r xs · eval (ℕ.suc n) P (x ∷ xs)) · x + u) (·Homeval n r Q xs) ⟩
      (eval n r xs · eval (ℕ.suc n) P (x ∷ xs)) · x + eval n r xs · eval n Q xs
    ≡⟨ cong (λ u → u  + eval n r xs · eval n Q xs) (sym (·Assoc _ _ _)) ⟩
      eval n r xs · (eval (ℕ.suc n) P (x ∷ xs) · x) + eval n r xs · eval n Q xs
    ≡⟨ sym (·Rdist+ _ _ _) ⟩
      eval n r xs · ((eval (ℕ.suc n) P (x ∷ xs) · x) + eval n Q xs)
    ≡[ i ]⟨ eval n r xs · combineCasesEval P Q x xs (~ i) ⟩
      eval n r xs · eval (ℕ.suc n) (P ·X+ Q) (x ∷ xs) ∎

  combineCases :
    (n : ℕ) (Q : IteratedHornerForms νR n) (P S : IteratedHornerForms νR (ℕ.suc n))
    (xs : Vec ⟨ νR ⟩ (ℕ.suc n))
    → eval (ℕ.suc n) ((P ·X+ Q) ·ₕ S) xs ≡ eval (ℕ.suc n) (((P ·ₕ S) ·X+ 0ₕ) +ₕ (Q ⋆ S)) xs
  combineCases n Q P S (x ∷ xs) with (P ·ₕ S)
  ... | 0H =
    eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)                ≡⟨ sym (+Lid _) ⟩
    0r + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)           ≡⟨ cong (λ u → u + eval _ (Q ⋆ S) (x ∷ xs)) lemma ⟩
    eval (ℕ.suc n) (0H ·X+ 0ₕ) (x ∷ xs)
    + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)              ≡⟨ sym (+Homeval (ℕ.suc n)
                                                      (0H ·X+ 0ₕ) (Q ⋆ S) (x ∷ xs)) ⟩
    eval (ℕ.suc n) ((0H ·X+ 0ₕ) +ₕ (Q ⋆ S)) (x ∷ xs) ∎
    where lemma : 0r ≡ eval (ℕ.suc n) (0H ·X+ 0ₕ) (x ∷ xs)
          lemma = 0r
                ≡⟨ sym (+Rid _) ⟩
                  0r + 0r
                ≡⟨ cong (λ u → u + 0r) (sym (0LeftAnnihilates _)) ⟩
                  0r · x + 0r
                ≡⟨ cong (λ u → 0r · x + u) (sym (Eval0H _ xs)) ⟩
                  0r · x + eval n 0ₕ xs
                ≡⟨ cong (λ u → u · x + eval n 0ₕ xs) (sym (Eval0H _ (x ∷ xs))) ⟩
                  eval {A = νR} (ℕ.suc n) 0H (x ∷ xs) · x + eval n 0ₕ xs
                ≡[ i ]⟨ combineCasesEval 0H 0ₕ x xs (~ i) ⟩
                  eval (ℕ.suc n) (0H ·X+ 0ₕ) (x ∷ xs) ∎
  ... | (_ ·X+ _) = refl

  ·Homeval .ℕ.zero (const x) (const y) [] = ·HomScalar R x y
  ·Homeval (ℕ.suc n) 0H Q xs =
    eval (ℕ.suc n) (0H ·ₕ Q) xs        ≡⟨ Eval0H _ xs ⟩
    0r                                 ≡⟨ sym (0LeftAnnihilates _) ⟩
    0r · eval (ℕ.suc n) Q xs          ≡⟨ cong (λ u → u · eval _ Q xs) (sym (Eval0H _ xs)) ⟩
    eval (ℕ.suc n) 0H xs · eval (ℕ.suc n) Q xs ∎
  ·Homeval (ℕ.suc n) (P ·X+ Q) S (x ∷ xs) =
      eval (ℕ.suc n) ((P ·X+ Q) ·ₕ S) (x ∷ xs)
    ≡⟨ combineCases n Q P S (x ∷ xs) ⟩
      eval (ℕ.suc n) (((P ·ₕ S) ·X+ 0ₕ) +ₕ (Q ⋆ S)) (x ∷ xs)
    ≡⟨ +Homeval (ℕ.suc n) ((P ·ₕ S) ·X+ 0ₕ) (Q ⋆ S) (x ∷ xs) ⟩
      eval (ℕ.suc n) ((P ·ₕ S) ·X+ 0ₕ) (x ∷ xs) + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)
    ≡⟨ cong (λ u → u + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)) (combineCasesEval (P ·ₕ S) 0ₕ x xs) ⟩
      (eval (ℕ.suc n) (P ·ₕ S) (x ∷ xs) · x + eval n 0ₕ xs)
      + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)
    ≡⟨ cong (λ u → u + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs))
          ((eval (ℕ.suc n) (P ·ₕ S) (x ∷ xs) · x + eval n 0ₕ xs)
         ≡⟨ cong (λ u → eval (ℕ.suc n) (P ·ₕ S) (x ∷ xs) · x + u) (Eval0H _ xs) ⟩
           (eval (ℕ.suc n) (P ·ₕ S) (x ∷ xs) · x + 0r)
         ≡⟨ +Rid _ ⟩
           (eval (ℕ.suc n) (P ·ₕ S) (x ∷ xs) · x)
         ≡⟨ cong (λ u → u · x) (·Homeval (ℕ.suc n) P S (x ∷ xs)) ⟩
           ((eval (ℕ.suc n) P (x ∷ xs) · eval (ℕ.suc n) S (x ∷ xs)) · x)
         ≡⟨ sym (·Assoc _ _ _) ⟩
           (eval (ℕ.suc n) P (x ∷ xs) · (eval (ℕ.suc n) S (x ∷ xs) · x))
         ≡⟨ cong (λ u → eval (ℕ.suc n) P (x ∷ xs) · u) (·-comm _ _) ⟩
           (eval (ℕ.suc n) P (x ∷ xs) · (x · eval (ℕ.suc n) S (x ∷ xs)))
         ≡⟨ ·Assoc _ _ _ ⟩
           (eval (ℕ.suc n) P (x ∷ xs) · x) · eval (ℕ.suc n) S (x ∷ xs)
          ∎) ⟩
      (eval (ℕ.suc n) P (x ∷ xs) · x) · eval (ℕ.suc n) S (x ∷ xs)
      + eval (ℕ.suc n) (Q ⋆ S) (x ∷ xs)
    ≡⟨ cong (λ u → (eval (ℕ.suc n) P (x ∷ xs) · x) · eval (ℕ.suc n) S (x ∷ xs) + u)
            (⋆Homeval n Q S x xs) ⟩
      (eval (ℕ.suc n) P (x ∷ xs) · x) · eval (ℕ.suc n) S (x ∷ xs)
      + eval n Q xs · eval (ℕ.suc n) S (x ∷ xs)
    ≡⟨ sym (·Ldist+ _ _ _) ⟩
      ((eval (ℕ.suc n) P (x ∷ xs) · x) + eval n Q xs) · eval (ℕ.suc n) S (x ∷ xs)
    ≡⟨ cong (λ u → u · eval (ℕ.suc n) S (x ∷ xs)) (sym (combineCasesEval P Q x xs)) ⟩
      eval (ℕ.suc n) (P ·X+ Q) (x ∷ xs) · eval (ℕ.suc n) S (x ∷ xs) ∎


-- Andreas, 2014-01-07 Issue reported by Dmitriy Traytel

{-# OPTIONS --copatterns #-}

module _ where

open import Common.Size
open import Common.Prelude hiding (map)

record Stream (A : Set) : Set where
  coinductive
  field
    head : A
    tail : Stream A
open Stream

-- This type should be empty.
data D : (i : Size) → Set where
  cons : ∀ i → Stream (D i) → D (↑ i)

-- BAD: But we can construct an inhabitant.
inh : Stream (D ∞)
head inh = cons ∞ inh  -- Should be rejected by termination checker.
tail inh = inh

map :  ∀{A B} → (A → B) → Stream A → Stream B
head (map f s) = f (head s)
tail (map f s) = map f (tail s)

loop : ∀ i → D i → ⊥
loop .(↑ i) (cons i s) = head (map (loop i) s)

absurd : ⊥
absurd = loop ∞ (cons ∞ inh)


{-# OPTIONS --universe-polymorphism #-}
open import Categories.Category

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

open Category C
open Equiv

open import Function using (flip)
open import Level
open import Function using (flip)
open import Categories.Support.PropositionalEquality

open import Categories.Square
open GlueSquares C

-- Borrowed from Dan Doel's definition of products
record Product (A B : Obj) : Set (o ⊔ ℓ ⊔ e) where

  infix 10 ⟨_,_⟩

  field
    A×B : Obj
    π₁ : A×B ⇒ A
    π₂ : A×B ⇒ B
    ⟨_,_⟩ : ∀ {C} → (C ⇒ A) → (C ⇒ B) → (C ⇒ A×B)

    .commute₁ : ∀ {C} {f : C ⇒ A} {g : C ⇒ B} → π₁ ∘ ⟨ f , g ⟩ ≡ f
    .commute₂ : ∀ {C} {f : C ⇒ A} {g : C ⇒ B} → π₂ ∘ ⟨ f , g ⟩ ≡ g
    .universal : ∀ {C} {f : C ⇒ A} {g : C ⇒ B} {i : C ⇒ A×B}
               → π₁ ∘ i ≡ f → π₂ ∘ i ≡ g → ⟨ f , g ⟩ ≡ i

  .g-η : ∀ {C} {f : C ⇒ A×B} → ⟨ π₁ ∘ f , π₂ ∘ f ⟩ ≡ f
  g-η = universal refl refl

  .η : ⟨ π₁ , π₂ ⟩ ≡ id
  η = universal identityʳ identityʳ

  .⟨⟩-cong₂ : ∀ {C} → {f f′ : C ⇒ A} {g g′ : C ⇒ B} → f ≡ f′ → g ≡ g′ → ⟨ f , g ⟩ ≡ ⟨ f′ , g′ ⟩
  ⟨⟩-cong₂ f≡f′ g≡g′ =
    universal (trans commute₁ (sym f≡f′)) (trans commute₂ (sym g≡g′))

  .⟨⟩∘ : ∀ {C D} {f : C ⇒ A} {g : C ⇒ B} {q : D ⇒ C} → ⟨ f , g ⟩ ∘ q ≡ ⟨ f ∘ q , g ∘ q ⟩
  ⟨⟩∘ = sym (universal (pullˡ commute₁) (pullˡ commute₂))

import Categories.Morphisms
open Categories.Morphisms C

private
  module Lemmas {A B : Obj} where
    open Product {A} {B} renaming (⟨_,_⟩ to _⟨_,_⟩)

    repack : (p₁ p₂ : Product A B) → A×B p₁ ⇒ A×B p₂
    repack p₁ p₂ = p₂ ⟨ π₁ p₁ , π₂ p₁ ⟩

    .repack∘ : (p₁ p₂ p₃ : Product A B) → repack p₂ p₃ ∘ repack p₁ p₂ ≡ repack p₁ p₃
    repack∘ p₁ p₂ p₃ = sym (universal p₃
      (glueTrianglesʳ (commute₁ p₃) (commute₁ p₂))
      (glueTrianglesʳ (commute₂ p₃) (commute₂ p₂)))

    .repack≡id : (p : Product A B) → repack p p ≡ id
    repack≡id p = η p

    .repack-cancel : (p₁ p₂ : Product A B) → repack p₁ p₂ ∘ repack p₂ p₁ ≡ id
    repack-cancel p₁ p₂ = trans (repack∘ p₂ p₁ p₂) (repack≡id p₂)

up-to-iso : ∀ {A B} → (p₁ p₂ : Product A B) → Product.A×B p₁ ≅ Product.A×B p₂
up-to-iso p₁ p₂ = record
  { f = repack p₁ p₂
  ; g = repack p₂ p₁
  ; iso = record
    { isoˡ = repack-cancel p₂ p₁
    ; isoʳ = repack-cancel p₁ p₂
    }
  }
  where
  open Lemmas

transport-by-iso : ∀ {A B} → (p : Product A B) → ∀ {X} → Product.A×B p ≅ X → Product A B
transport-by-iso p {X} p≅X = record
  { A×B = X
  ; π₁ = p.π₁ ∘ g
  ; π₂ = p.π₂ ∘ g
  ; ⟨_,_⟩ = λ h₁ h₂ → f ∘ p ⟨ h₁ , h₂ ⟩
  ; commute₁ = trans (cancelInner isoˡ) p.commute₁
  ; commute₂ = trans (cancelInner isoˡ) p.commute₂
  ; universal = λ {_ l r i} pfˡ pfʳ → let open HomReasoning in
      begin
        f ∘ p ⟨ l , r ⟩
      ↑⟨ ∘-resp-≡ʳ (p.⟨⟩-cong₂ pfˡ pfʳ) ⟩
        f ∘ p ⟨ (p.π₁ ∘ g) ∘ i , (p.π₂ ∘ g) ∘ i ⟩
      ↓⟨ ∘-resp-≡ʳ (p.universal (sym assoc) (sym assoc)) ⟩
        f ∘ (g ∘ i)
      ↓⟨ cancelLeft isoʳ ⟩
        i
      ∎
  }
  where
  module p = Product p
  open Product using () renaming (⟨_,_⟩ to _⟨_,_⟩)
  open _≅_ p≅X

Reversible : ∀ {A B} → (p : Product A B) → Product B A
Reversible p = record
  { A×B = p.A×B
  ; π₁ = p.π₂
  ; π₂ = p.π₁
  ; ⟨_,_⟩ = flip p.⟨_,_⟩
  ; commute₁ = p.commute₂
  ; commute₂ = p.commute₁
  ; universal = flip p.universal
  }
  where module p = Product p

Commutative : ∀ {A B} (p₁ : Product A B) (p₂ : Product B A) → Product.A×B p₁ ≅ Product.A×B p₂
Commutative p₁ p₂ = up-to-iso p₁ (Reversible p₂)

Associable : ∀ {X Y Z} (p₁ : Product X Y) (p₂ : Product Y Z) (p₃ : Product X (Product.A×B p₂)) → Product (Product.A×B p₁) Z
Associable p₁ p₂ p₃ = record
  { A×B = A×B p₃
  ; π₁ = p₁ ⟨ π₁ p₃ , π₁ p₂ ∘ π₂ p₃ ⟩
  ; π₂ = π₂ p₂ ∘ π₂ p₃
  ; ⟨_,_⟩ = λ f g → p₃ ⟨ π₁ p₁ ∘ f , p₂ ⟨ π₂ p₁ ∘ f , g ⟩ ⟩
  ; commute₁ = λ {_ f g} → let open HomReasoning in begin
      p₁ ⟨ π₁ p₃ , π₁ p₂ ∘ π₂ p₃ ⟩ ∘ p₃ ⟨ π₁ p₁ ∘ f , p₂ ⟨ π₂ p₁ ∘ f , g ⟩ ⟩
    ↓⟨ ⟨⟩∘ p₁ ⟩
      p₁ ⟨ π₁ p₃ ∘ p₃ ⟨ π₁ p₁ ∘ f , _ ⟩ , (π₁ p₂ ∘ π₂ p₃) ∘ p₃ ⟨ _ , p₂ ⟨ π₂ p₁ ∘ f , g ⟩ ⟩ ⟩
    ↓⟨ ⟨⟩-cong₂ p₁ (commute₁ p₃) (glueTrianglesˡ (commute₁ p₂) (commute₂ p₃)) ⟩
      p₁ ⟨ π₁ p₁ ∘ f , π₂ p₁ ∘ f ⟩
    ↓⟨ g-η p₁ ⟩
      f
    ∎
  ; commute₂ = λ {_ f g} → glueTrianglesˡ (commute₂ p₂) (commute₂ p₃)
  ; universal = λ {D l r i} pfˡ pfʳ → let open HomReasoning in begin
      p₃ ⟨ π₁ p₁ ∘ l , p₂ ⟨ π₂ p₁ ∘ l , r ⟩ ⟩
    ↑⟨ ⟨⟩-cong₂ p₃ (∘-resp-≡ʳ pfˡ) (⟨⟩-cong₂ p₂ (∘-resp-≡ʳ pfˡ) pfʳ) ⟩
      p₃ ⟨ π₁ p₁ ∘ (p₁ ⟨ π₁ p₃ , _ ⟩ ∘ i) , p₂ ⟨ π₂ p₁ ∘ (p₁ ⟨ _ , π₁ p₂ ∘ π₂ p₃ ⟩ ∘ i) , (π₂ p₂ ∘ π₂ p₃) ∘ i ⟩ ⟩
    ↓⟨ ⟨⟩-cong₂ p₃ (pullˡ (commute₁ p₁)) (⟨⟩-cong₂ p₂ (pullˡ (commute₂ p₁)) refl) ⟩
      p₃ ⟨ π₁ p₃ ∘ i , p₂ ⟨ (π₁ p₂ ∘ π₂ p₃) ∘ i , (π₂ p₂ ∘ π₂ p₃) ∘ i ⟩ ⟩
    ↓⟨ ⟨⟩-cong₂ p₃ refl (universal p₂ (sym assoc) (sym assoc)) ⟩
      p₃ ⟨ π₁ p₃ ∘ i , π₂ p₃ ∘ i ⟩
    ↓⟨ g-η p₃ ⟩
      i
    ∎
  }
  where
  open Product renaming (⟨_,_⟩ to _⟨_,_⟩)

Associative : ∀ {X Y Z} (p₁ : Product X Y) (p₂ : Product Y Z) (p₃ : Product X (Product.A×B p₂)) (p₄ : Product (Product.A×B p₁) Z) → (Product.A×B p₃) ≅ (Product.A×B p₄)
Associative p₁ p₂ p₃ p₄ = up-to-iso (Associable p₁ p₂ p₃) p₄

open Lemmas public

Mobile : ∀ {A₁ B₁ A₂ B₂} (p : Product A₁ B₁) → A₁ ≅ A₂ → B₁ ≅ B₂ → Product A₂ B₂
Mobile p A₁≅A₂ B₁≅B₂ = record
  { A×B = p.A×B
  ; π₁ = f A₁≅A₂ ∘ p.π₁
  ; π₂ = f B₁≅B₂ ∘ p.π₂
  ; ⟨_,_⟩ = λ h k → p ⟨ g A₁≅A₂ ∘ h , g B₁≅B₂ ∘ k ⟩
  ; commute₁ = let open HomReasoning in begin
      (f A₁≅A₂ ∘ p.π₁) ∘ p ⟨ g A₁≅A₂ ∘ _ , g B₁≅B₂ ∘ _ ⟩
    ↓⟨ pullʳ p.commute₁ ⟩
      f A₁≅A₂ ∘ (g A₁≅A₂ ∘ _)
    ↓⟨ cancelLeft (isoʳ A₁≅A₂) ⟩
      _
    ∎
  ; commute₂ = let open HomReasoning in begin
      (f B₁≅B₂ ∘ p.π₂) ∘ p ⟨ g A₁≅A₂ ∘ _ , g B₁≅B₂ ∘ _ ⟩
    ↓⟨ pullʳ p.commute₂ ⟩
      f B₁≅B₂ ∘ (g B₁≅B₂ ∘ _)
    ↓⟨ cancelLeft (isoʳ B₁≅B₂) ⟩
      _
    ∎
  ; universal = λ pfˡ pfʳ → p.universal
                              (switch-fgˡ A₁≅A₂ (trans (sym assoc) pfˡ))
                              (switch-fgˡ B₁≅B₂ (trans (sym assoc) pfʳ))
  }
  where
  module p = Product p
  open Product renaming (⟨_,_⟩ to _⟨_,_⟩)
  open _≅_


{-# OPTIONS --guardedness-preserving-type-constructors #-}

module TypeConstructorsWhichPreserveGuardedness2 where

record ⊤ : Set where

data _⊎_ (A B : Set) : Set where
  inj₁ : A → A ⊎ B
  inj₂ : B → A ⊎ B

-- This should not be allowed.

ℕ : Set
ℕ = ⊤ ⊎ ℕ


{-# OPTIONS --rewriting --confluence-check --double-check #-}

data _==_ {A : Set} : (x y : A) → Set where
  refl : {a : A} → a == a
{-# BUILTIN REWRITE _==_ #-}

postulate
  copy : ∀ {X : Set} → X → X
  A : Set
  a : A
  uip : (p : a == a) → p == refl

record S : Set where
  field
    x : A
    x-β : x == a
open S

module T (s : S) where
  dummy = x-β (copy s)
  {-# REWRITE dummy #-}

  y-β-is-refl : x-β (copy s) == refl
  y-β-is-refl = uip _ -- WAS: Double check complains about solution to meta.


-- Andreas, AIM XXIII, 2016-04-26 flight EDI-GOT home

-- {-# OPTIONS -v impossible:10 #-}

-- Parameter arguments of overloaded projection applications
-- should not be skipped!

record R A : Set where
  field f : A
open R

record S A : Set where
  field f : A
open S

module _ (A B : Set) (a : A) where

  r : R A
  f r = a

  test1 = f {A = A} r
  test2 = f {A} r

  test = f {A = B} r


open import Agda.Builtin.Bool
open import Agda.Builtin.Nat
open import Agda.Builtin.Equality

record D (A : Set) : Set where
  constructor mkD
  field d : A
open D {{...}}

module test where

  instance

    _ : D Bool
    _ = mkD true

    a : D Nat
    a = mkD 0

  _ : d ≡ true
  _ = refl

  _ : d ≡ zero
  _ = refl

-- no instance in scope
-- _ : d ≡ true
-- _ = ?

_ : d ≡ zero
_ = refl


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

module Number.Bundles2 where

open import Agda.Primitive renaming (_⊔_ to ℓ-max; lsuc to ℓ-suc; lzero to ℓ-zero)
open import Cubical.Foundations.Everything renaming (_⁻¹ to _⁻¹ᵖ; assoc to ∙-assoc)
-- open import Cubical.Foundations.Logic
-- open import Cubical.Structures.Ring
-- open import Cubical.Structures.Group
-- open import Cubical.Structures.AbGroup

open import Cubical.Relation.Nullary.Base -- ¬_
open import Cubical.Relation.Binary.Base
open import Cubical.Data.Sum.Base renaming (_⊎_ to infixr 4 _⊎_)
open import Cubical.Data.Sigma.Base renaming (_×_ to infixr 4 _×_)
open import Cubical.Data.Empty renaming (elim to ⊥-elim; ⊥ to ⊥⊥) -- `⊥` and `elim`
open import Cubical.Foundations.Logic renaming (¬_ to ¬ᵖ_; inl to inlᵖ; inr to inrᵖ)
open import Function.Base using (it; _∋_)

open import Cubical.HITs.PropositionalTruncation --.Properties

open import Utils using (!_; !!_)
open import MoreLogic.Reasoning
open import MoreLogic.Definitions
open import MoreLogic.Properties
open import MorePropAlgebra.Definitions hiding (_≤''_)
open import MorePropAlgebra.Consequences
open import Number.Structures2

{-
| name | struct              | apart | abs | order | cauchy | sqrt₀⁺  | exp | final name                                                             |
|------|---------------------|-------|-----|-------|--------|---------|-----|------------------------------------------------------------------------|
| ℕ    | CommSemiring        |  (✓)  | (✓) | lin.  |        | (on x²) |     | LinearlyOrderedCommSemiring                                            |
| ℤ    | CommRing            |  (✓)  | (✓) | lin.  |        | (on x²) |     | LinearlyOrderedCommRing                                                |
| ℚ    | Field               |  (✓)  | (✓) | lin.  |        | (on x²) | (✓) | LinearlyOrderedField                                                   |
| ℝ    | Field               |  (✓)  | (✓) | part. |   ✓    |    ✓    | (✓) | CompletePartiallyOrderedFieldWithSqrt                                  |
| ℂ    | euclidean 2-Product |  (✓)  | (✓) |       |  (✓)   |         |  ?  | EuclideanTwoProductOfCompletePartiallyOrderedFieldWithSqrt             |
| R    | Ring                |   ✓   |  ✓  |       |        |         |  ?  | ApartnessRingWithAbsIntoCompletePartiallyOrderedFieldWithSqrt          |
| G    | Group               |   ✓   |  ✓  |       |        |         |  ?  | ApartnessGroupWithAbsIntoCompletePartiallyOrderedFieldWithSqrt         |
| K    | Field               |   ✓   |  ✓  |       |   ✓    |         |  ?  | CompleteApartnessFieldWithAbsIntoCompletePartiallyOrderedFieldWithSqrt |
-}

record LinearlyOrderedCommSemiring {ℓ ℓ'} : Type (ℓ-suc (ℓ-max ℓ ℓ')) where
  constructor linearlyorderedcommsemiring
  field
    Carrier : Type ℓ
    0f 1f   : Carrier
    _+_     : Carrier → Carrier → Carrier
    _·_     : Carrier → Carrier → Carrier
    min max : Carrier → Carrier → Carrier
    _<_     : hPropRel Carrier Carrier ℓ'
    is-LinearlyOrderedCommSemiring : [ isLinearlyOrderedCommSemiring 0f 1f _+_ _·_ _<_ min max ] -- defines `_≤_` and `_#_`

  infixl 7 _·_
  infixl 5 _+_
  infixl 4 _<_

  open IsLinearlyOrderedCommSemiring is-LinearlyOrderedCommSemiring public

record LinearlyOrderedCommRing {ℓ ℓ'} : Type (ℓ-suc (ℓ-max ℓ ℓ')) where
  constructor linearlyorderedcommring
  field
    Carrier : Type ℓ
    0f 1f   : Carrier
    _+_     : Carrier → Carrier → Carrier
    -_      : Carrier → Carrier
    _·_     : Carrier → Carrier → Carrier
    min max : Carrier → Carrier → Carrier
    _<_     : hPropRel Carrier Carrier ℓ'
    is-LinearlyOrderedCommRing : [ isLinearlyOrderedCommRing 0f 1f _+_ _·_ -_ _<_ min max ] -- defines `_≤_` and `_#_`

  infixl 7 _·_
  infix  6 -_
  infixl 5 _+_
  infixl 4 _<_

  open IsLinearlyOrderedCommRing is-LinearlyOrderedCommRing public

record LinearlyOrderedField {ℓ ℓ'} : Type (ℓ-suc (ℓ-max ℓ ℓ')) where
  constructor linearlyorderedfield
  field
    Carrier : Type ℓ
    0f 1f   : Carrier
    _+_     : Carrier → Carrier → Carrier
    -_      : Carrier → Carrier
    _·_     : Carrier → Carrier → Carrier
    min max : Carrier → Carrier → Carrier
    _<_     : hPropRel Carrier Carrier ℓ'
    is-LinearlyOrderedField : [ isLinearlyOrderedField 0f 1f _+_ _·_ -_ _<_ min max ] -- defines `_≤_` and `_#_`

  infixl 7 _·_
  infix  6 -_
  infixl 5 _+_
  infixl 4 _<_

  open IsLinearlyOrderedField is-LinearlyOrderedField public

-- NOTE: this smells like "CPO" https://en.wikipedia.org/wiki/Complete_partial_order
record CompletePartiallyOrderedFieldWithSqrt {ℓ ℓ' : Level} : Type (ℓ-suc (ℓ-max ℓ ℓ')) where
  field
    Carrier : Type ℓ
    is-set   : isSet Carrier
    0f      : Carrier
    1f      : Carrier
    _<_     : hPropRel Carrier Carrier ℓ'
    min     : Carrier → Carrier → Carrier
    max     : Carrier → Carrier → Carrier
    _+_     : Carrier → Carrier → Carrier
    _·_     : Carrier → Carrier → Carrier
    -_      : Carrier → Carrier
    <-irrefl  : [ isIrrefl   _<_ ]
    <-trans   : [ isTrans    _<_ ]
    <-cotrans : [ isCotrans  _<_ ]

  -- NOTE: these intermediate definitions are restricted and behave like let-definitions
  --       e.g. they show up in goal contexts and they do not allow for `where` blocks

  _-_ : Carrier → Carrier → Carrier
  a - b = a + (- b)

  <-asym : [ isAsym  _<_ ]
  <-asym = irrefl+trans⇒asym _<_ <-irrefl <-trans

  _#_ : hPropRel Carrier Carrier ℓ'
  x # y = [ <-asym x y ] (x < y) ⊎ᵖ (y < x)

  field
    #-tight : [ isTightˢ''' _#_ is-set ]

  _≤_ : hPropRel Carrier Carrier ℓ'
  x ≤ y = ¬ᵖ(y < x)

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

  ≤-refl : [ isRefl _≤_ ]
  ≤-refl = <-irrefl

  ≤-trans : [ isTrans  _≤_ ]
  ≤-trans = <-cotrans⇒≤-trans _<_ <-cotrans

  -- if x > y then x > y ≥ x, wich contradicts 4. Hence ¬(x > y). Similarly, ¬(y > x), so ¬(x ≠ y) and therefore by axiom R2(3), x = y.
  -- NOTE: this makes use of #-tight to proof ≤-antisym
  --       but we are alrady using ≤-antisym to proof #-tight
  --       so I guess that we have to assume one of them?
  --       Bridges lists tightness a property of _<_, so he seems to assume #-tight
  --       Booij assumes `≤-isLattice : IsLattice _≤_ min max` which gives ≤-refl, ≤-antisym and ≤-trans and proofs #-tight from it
  -- ≤-antisym : (∀ x y → [ ¬ᵖ (x # y) ] → x ≡ y) → [ isAntisymˢ is-set _≤_ ]
  ≤-antisym : [ isAntisymˢ _≤_ is-set ]
  ≤-antisym = fst (isTightˢ'''⇔isAntisymˢ _<_ is-set <-asym) #-tight

  -- NOTE: we have `R3-8 = ∀[ x ] ∀[ y ] (¬(x ≤ y) ⇔ ¬ ¬(y < x))`
  --       so I guess that we do not have `dne-over-< : ¬ ¬(y < x) ⇔ (y < x)`
  --       and that would be my plan to prove `≤-cotrans` with `<-asym`
  -- ≤-cotrans : [ isCotrans  _≤_ ]
  -- ≤-cotrans x y x≤y z = [ (x ≤ z) ⊔ (z ≤ y) ] ∋  {! (≤-antisym x y x≤y)  !}

  abs : Carrier → Carrier
  abs x = max x (- x)

  field
    -- `R3.12` in [Bridges 1999]
    -- bridges-R2-2  : ∀ x y → [ y < x ] → ∀ z → [ (z < x) ⊔ (y < z) ]
    sqrt : (x : Carrier) → {{ ! [ 0f ≤ x ] }} → Carrier
    0≤sqrt : ∀ x → {{ p : ! [ 0f ≤ x ] }} → [ 0f ≤ sqrt x {{p}} ]
    0≤x² : ∀ x → [ 0f ≤ (x · x) ]

  instance _ = λ {x} → !! 0≤x² x

  field
    -- NOTE: all "interface" instance arguments (i.e. those that appear in the goal) need to be passed in as arguments
    -- sqrt-of-²  : ∀ x → {{ p₁ : ! [ 0f ≤ x ] }} → {{ p₂ : ! [ 0f ≤ x · x ] }} → sqrt (x · x) {{p₂}} ≡ x
    -- sqrt-unique-existence : ∀ x → {{ p : ! [ 0f ≤ x ] }} → Σ[ y ∈ Carrier ] y · y ≡ x
    -- sqrt-uniqueness : ∀ x y z → {{ p : ! [ 0f ≤ x ] }} → y · y ≡ x → z · z ≡ x → y ≡ z
    ·-uniqueness : ∀ x y → {{ p₁ : ! [ 0f ≤ x ] }} → {{ p₂ : ! [ 0f ≤ y ] }} → x · x ≡ y · y → x ≡ y
    sqrt-existence   : ∀ x   → {{ p  : ! [ 0f ≤ x ] }} → sqrt x {{p}} · sqrt x {{p}} ≡ x
    sqrt-preserves-· : ∀ x y → {{ p₁ : ! [ 0f ≤ x ] }} → {{ p₁ : ! [ 0f ≤ y ] }} → {{ p₁ : ! [ 0f ≤ x · y ] }} → sqrt (x · y) ≡ sqrt x · sqrt y
    sqrt0≡0 : {{ p : ! [ 0f ≤ 0f ] }} → sqrt 0f {{p}} ≡ 0f
    sqrt1≡1 : {{ p : ! [ 0f ≤ 1f ] }} → sqrt 1f {{p}} ≡ 1f
    -- √x √x = x ⇒ √xx = x
    -- √x √x √x √x = x x
    -- √(√x √x √x √x) = √(x x)

  -- ²-of-sqrt' : ∀ x → {{ p : ! [ 0f ≤ x ] }} → sqrt x {{p}} · sqrt x {{p}} ≡ x
  -- ²-of-sqrt' x {{p}} = let y = sqrt x; instance q = !! 0≤sqrt x in transport (
  --   sqrt (y · y) ≡ y ≡⟨ {!   !} ⟩
  --   sqrt (y · y) · sqrt (y · y) ≡ y · sqrt (y · y) ≡⟨ {!   !} ⟩
  --   sqrt (y · y) · sqrt (y · y) ≡ y · y ≡⟨ {! λ x → x  !} ⟩
  --   sqrt x · sqrt x ≡ x ∎) (sqrt-of-² y)
  --    {!   !} ⇒⟨ {!   !} ⟩
  --    {!   !} ◼) {! (sqrt-of-² y ) !}
  -- sqrt (x · x) ≡ x
  -- sqrt (x · x) · sqrt (x · x) ≡ x · sqrt (x · x)
  -- sqrt (x · x) · sqrt (x · x) ≡ x · x
  -- x = sqrt y
  -- sqrt y · sqrt y ≡ y

  sqrt-test : (x y z : Carrier) → [ 0f ≤ x ] → [ 0f ≤ y ] → Carrier
  sqrt-test x y z 0≤x 0≤y = let instance _ = !! 0≤x
                                instance _ = !! 0≤y
                            in (sqrt x) + (sqrt y) + (sqrt (z · z))

  field
    _⁻¹ : (x : Carrier) → {{p : [ x # 0f ]}} → Carrier

  _/_ : (x y : Carrier) → {{p : [ y # 0f ]}} → Carrier
  (x / y) {{p}} = x · (y ⁻¹) {{p}}

  infix  9 _⁻¹
  infixl 7 _·_
  infixl 7 _/_
  infix  6 -_
  infix  5 _-_
  infixl 5 _+_
  infixl 4 _#_
  infixl 4 _≤_
  infixl 4 _<_

open import MorePropAlgebra.Bridges1999

-- mkBridges : ∀{ℓ ℓ'} → CompletePartiallyOrderedFieldWithSqrt {ℓ} {ℓ'} → BooijResults {ℓ} {ℓ'}
-- mkBridges CPOFS = record { CompletePartiallyOrderedFieldWithSqrt CPOFS }

-----------8<--------------------------------------------8<------------------------------------------8<------------------

{- currently, we have that IsAbs works on "rigs" (rings where `-_` is not necessary)
   but in our applications, we do want to take the square root immediately on modules
   therefore, `abs` is defined here as always mapping into `CompletePartiallyOrderedFieldWithSqrt` although more general `abs`es would be possible
-}

module _ -- mathematical structures with `abs` into the real numbers
  {ℝℓ ℝℓ' : Level}
  (ℝbundle : CompletePartiallyOrderedFieldWithSqrt {ℝℓ} {ℝℓ'})
  where
  module ℝ = CompletePartiallyOrderedFieldWithSqrt ℝbundle
  open ℝ using () renaming (Carrier to ℝ; is-set to is-setʳ; _≤_ to _≤ʳ_; 0f to 0ʳ; 1f to 1ʳ; _+_ to _+ʳ_; _·_ to _·ʳ_; -_ to -ʳ_; _-_ to _-ʳ_)

  -- this makes the complex numbers ℂ
  module EuclideanTwoProductOfCompletePartiallyOrderedFieldWithSqrt where
    Carrier : Type ℝℓ
    Carrier = ℝ × ℝ

    re im : Carrier → ℝ
    re = fst
    im = snd

    0f : Carrier
    0f = 0ʳ , 0ʳ

    1f : Carrier
    1f = 1ʳ , 0ʳ

    _+_ : Carrier → Carrier → Carrier
    (ar , ai) + (br , bi) = (ar +ʳ br) , (ai +ʳ bi)

    _·_ : Carrier → Carrier → Carrier
    (ar , ai) · (br , bi) = (ar ·ʳ br -ʳ ai ·ʳ bi) , (ar ·ʳ bi +ʳ br ·ʳ ai)

    -_ : Carrier → Carrier
    - (ar , ai) = (-ʳ ar , -ʳ ai)

    is-set : isSet Carrier
    is-set = isSetΣ ℝ.is-set (λ _ → ℝ.is-set)

  -- this makes the `R` in `RModule`
  record ApartnessRingWithAbsIntoCompletePartiallyOrderedFieldWithSqrt {ℓ ℓ' : Level} : Type (ℓ-suc (ℓ-max (ℓ-max ℓ ℓ') (ℓ-max ℝℓ ℝℓ'))) where
    field
      Carrier : Type ℓ
      0f      : Carrier
      1f      : Carrier
      _+_     : Carrier → Carrier → Carrier
      _·_     : Carrier → Carrier → Carrier
      -_      : Carrier → Carrier
      _#_     : hPropRel Carrier Carrier ℓ'
      abs     : Carrier → ℝ

  -- this makes the `G` in `GModule`
  record ApartnessGroupWithAbsIntoCompletePartiallyOrderedFieldWithSqrt {ℓ ℓ' : Level} : Type (ℓ-suc (ℓ-max (ℓ-max ℓ ℓ') (ℓ-max ℝℓ ℝℓ'))) where
    field
      Carrier : Type ℓ
      1f      : Carrier
      _·_     : Carrier → Carrier → Carrier
      _⁻¹     : Carrier → Carrier
      _#_     : hPropRel Carrier Carrier ℓ'
      abs     : Carrier → ℝ

  -- this makes the `K` in `KModule`
  record CompleteApartnessFieldWithAbsIntoCompletePartiallyOrderedFieldWithSqrt {ℓ ℓ' : Level} : Type (ℓ-suc (ℓ-max (ℓ-max ℓ ℓ') (ℓ-max ℝℓ ℝℓ'))) where
    field
      Carrier : Type ℓ
      0f      : Carrier
      1f      : Carrier
      _+_     : Carrier → Carrier → Carrier
      _·_     : Carrier → Carrier → Carrier
      -_      : Carrier → Carrier
      _#_     : hPropRel Carrier Carrier ℓ'
      _⁻¹     : (x : Carrier) → {{p : [ x # 0f ]}} → Carrier
      abs     : Carrier → ℝ
      is-set  : isSet Carrier
      is-abs  : [ isAbs is-set 0f _+_ _·_ is-setʳ 0ʳ _+ʳ_ _·ʳ_ _≤ʳ_ abs ]

    -- TODO: complete this


{-# OPTIONS --rewriting #-}
module CF.Contexts.Rewriting where

open import Data.List
open import Data.List.Properties

open import Agda.Builtin.Equality.Rewrite
open import Relation.Binary.PropositionalEquality
open import CF.Types

++-assoc-← : ∀ (xs ys zs : List Ty) → xs ++ (ys ++ zs) ≡ (xs ++ ys) ++ zs
++-assoc-← = λ x y z → sym (++-assoc x y z)

++-identityʳ-← : ∀ (xs : List Ty) → xs ++ [] ≡ xs
++-identityʳ-← xs = ++-identityʳ xs

{-# REWRITE ++-assoc-← #-}
{-# REWRITE ++-identityʳ-← #-}


{-# OPTIONS --rewriting #-}
module Issue4048 where

data _==_ {i} {A : Set i} : (x y : A) → Set i where
  refl : {a : A} → a == a
{-# BUILTIN REWRITE _==_ #-}

postulate
  Π : (A : Set) (B : A → Set) → Set
  lam : {A : Set} {B : A → Set} (b : (a : A) → B a) → Π A B
  app : {A : Set} {B : A → Set} (f : Π A B) (a : A) → B a
  Π-β : {A : Set} {B : A → Set} (b : (a : A) → B a) (a : A) → app (lam b) a == b a
  {-# REWRITE Π-β #-}

postulate
  ⊤ : Set
  tt : ⊤
  ⊤-elim : ∀ {i} (A : ⊤ → Set i) (d : A tt) (x : ⊤) → A x
  ⊤-β : ∀ {i} (A : ⊤ → Set i) (d : A tt) → ⊤-elim A d tt == d
  {-# REWRITE ⊤-β #-}

tt' : ⊤
tt' = tt

module _
  (C : (p : ⊤) → Set)
  (z : C tt)
  where

  F : (n p x : ⊤) → C p
  F n p = app (⊤-elim (λ n → (p : ⊤) → Π ⊤ (λ _ → C p))
                       (⊤-elim _ (lam (⊤-elim _ z)))
                       n p)

  F-red : F tt tt tt == z
  F-red = refl

  -- Bug?
  F-red' : F tt tt' tt == z
  F-red' = refl  -- Not accepted, even though tt' is tt by definition.


-- Andreas, 2015-06-29 fixed handling of projections in positivity checker

-- {-# OPTIONS -v tc.polarity:20 -v tc.proj.like:10 -v tc.pos:10  --show-implicit #-}
-- {-# OPTIONS -v tc.pos.occ:70  #-}

open import Common.Prelude
open import Common.Product

dup : (b : Bool) (X : Set) → Set × Set
dup true  X = (X → X) , X
dup false X = (X → X) , X

postulate b : Bool

data D : Set where
  c : proj₁ (dup b D) → D

-- ERROR WAS:
-- D is not strictly positive, because it occurs
-- in the second argument to dup
-- in the type of the constructor c
-- in the definition of D.

-- EXPECTED ERROR:
-- D is not strictly positive, because it occurs
-- in the second argument to dup
-- in the first argument to proj₁
-- in the type of the constructor c
-- in the definition of D.


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

open import Algebra.Structures.Bundles.Field
open import Algebra.Linear.Structures.Bundles

module Algebra.Linear.Space.Product
  {k ℓ} (K : Field k ℓ)
  {a₁ ℓ₁} (V₁-space : VectorSpace K a₁ ℓ₁)
  {a₂ ℓ₂} (V₂-space : VectorSpace K a₂ ℓ₂)
  where

open import Relation.Binary
open import Level using (_⊔_)
open import Data.Nat using (ℕ; zero; suc) renaming (_+_ to _+ℕ_)
open import Algebra.Linear.Structures.VectorSpace
import Algebra.FunctionProperties as FP

open VectorSpaceField K

open VectorSpace V₁-space
  using ()
  renaming
  ( Carrier       to V₁
  ; _≈_           to _≈₁_
  ; isEquivalence to ≈₁-isEquiv
  ; refl          to ≈₁-refl
  ; sym           to ≈₁-sym
  ; trans         to ≈₁-trans
  ; _+_           to _+₁_
  ; _∙_           to _∙₁_
  ; -_            to -₁_
  ; 0#            to 0₁
  ; +-identityˡ    to +₁-identityˡ
  ; +-identityʳ    to +₁-identityʳ
  ; +-identity    to +₁-identity
  ; +-cong        to +₁-cong
  ; +-assoc       to +₁-assoc
  ; +-comm        to +₁-comm
  ; *ᵏ-∙-compat   to *ᵏ-∙₁-compat
  ; ∙-+-distrib   to ∙₁-+₁-distrib
  ; ∙-+ᵏ-distrib  to ∙₁-+ᵏ-distrib
  ; ∙-cong        to ∙₁-cong
  ; ∙-identity    to ∙₁-identity
  ; ∙-absorbˡ      to ∙₁-absorbˡ
  ; ∙-absorbʳ      to ∙₁-absorbʳ
  ; -‿cong        to -₁‿cong
  ; -‿inverseˡ    to -₁‿inverseˡ
  ; -‿inverseʳ    to -₁‿inverseʳ
  )

open VectorSpace V₂-space
  using ()
  renaming
  ( Carrier       to V₂
  ; _≈_           to _≈₂_
  ; isEquivalence to ≈₂-isEquiv
  ; refl          to ≈₂-refl
  ; sym           to ≈₂-sym
  ; trans         to ≈₂-trans
  ; _+_           to _+₂_
  ; _∙_           to _∙₂_
  ; -_            to -₂_
  ; 0#            to 0₂
  ; +-identityˡ    to +₂-identityˡ
  ; +-identityʳ    to +₂-identityʳ
  ; +-identity    to +₂-identity
  ; +-cong        to +₂-cong
  ; +-assoc       to +₂-assoc
  ; +-comm        to +₂-comm
  ; *ᵏ-∙-compat   to *ᵏ-∙₂-compat
  ; ∙-+-distrib   to ∙₂-+₂-distrib
  ; ∙-+ᵏ-distrib  to ∙₂-+ᵏ-distrib
  ; ∙-cong        to ∙₂-cong
  ; ∙-identity    to ∙₂-identity
  ; ∙-absorbˡ      to ∙₂-absorbˡ
  ; ∙-absorbʳ      to ∙₂-absorbʳ
  ; -‿cong        to -₂‿cong
  ; -‿inverseˡ    to -₂‿inverseˡ
  ; -‿inverseʳ    to -₂‿inverseʳ
  )

open import Data.Product
open import Data.Product.Relation.Binary.Pointwise.NonDependent

private
  V : Set (a₁ ⊔ a₂)
  V = V₁ × V₂

_≈_ : Rel V (ℓ₁ ⊔ ℓ₂)
_≈_ = Pointwise _≈₁_ _≈₂_

≈-isEquiv : IsEquivalence _≈_
≈-isEquiv = ×-isEquivalence ≈₁-isEquiv ≈₂-isEquiv

prod-setoid : Setoid (a₁ ⊔ a₂) (ℓ₁ ⊔ ℓ₂)
prod-setoid = record
  { Carrier       = V
  ; _≈_           = _≈_
  ; isEquivalence = ≈-isEquiv
  }

open IsEquivalence ≈-isEquiv renaming
  ( refl  to ≈-refl
  ; sym   to ≈-sym
  ; trans to ≈-trans
  )

open import Algebra.FunctionProperties _≈_
open import Algebra.Structures _≈_

0# : V
0# = (0₁ , 0₂)

-_ : Op₁ V
- (x₁ , x₂) = (-₁ x₁ , -₂ x₂)

infixr 25 _+_
_+_ : Op₂ V
(x₁ , x₂) + (y₁ , y₂) = (x₁ +₁ y₁ , x₂ +₂ y₂)

infixr 30 _∙_
_∙_ : K' -> V -> V
k ∙ (x₁ , x₂) = (k ∙₁ x₁ , k ∙₂ x₂)

+-cong : Congruent₂ _+_
+-cong (r₁ , r₂) (s₁ , s₂) = ( +₁-cong r₁ s₁ , +₂-cong r₂ s₂ )

+-assoc : Associative _+_
+-assoc (x₁ , x₂) (y₁ , y₂) (z₁ , z₂) = ( +₁-assoc x₁ y₁ z₁ , +₂-assoc x₂ y₂ z₂ )

+-identityˡ : LeftIdentity 0# _+_
+-identityˡ (x₁ , x₂) = ( +₁-identityˡ x₁ , +₂-identityˡ x₂ )

+-identityʳ : RightIdentity 0# _+_
+-identityʳ (x₁ , x₂) = ( +₁-identityʳ x₁ , +₂-identityʳ x₂ )

+-identity : Identity 0# _+_
+-identity = +-identityˡ , +-identityʳ

+-comm : Commutative _+_
+-comm (x₁ , x₂) (y₁ , y₂) = ( +₁-comm x₁ y₁ , +₂-comm x₂ y₂ )

*ᵏ-∙-compat : ∀ (a b : K') (u : V) -> ((a *ᵏ b) ∙ u) ≈ (a ∙ (b ∙ u))
*ᵏ-∙-compat a b (x₁ , x₂) = ( *ᵏ-∙₁-compat a b x₁ , *ᵏ-∙₂-compat a b x₂ )

∙-+-distrib : ∀ (a : K') (u v : V) -> (a ∙ (u + v)) ≈ ((a ∙ u) + (a ∙ v))
∙-+-distrib a (x₁ , x₂) (y₁ , y₂) = ( ∙₁-+₁-distrib a x₁ y₁ , ∙₂-+₂-distrib a x₂ y₂ )

∙-+ᵏ-distrib : ∀ (a b : K') (u : V) -> ((a +ᵏ b) ∙ u) ≈ ((a ∙ u) + (b ∙ u))
∙-+ᵏ-distrib a b  (x₁ , x₂) = ( ∙₁-+ᵏ-distrib a b x₁ , ∙₂-+ᵏ-distrib a b x₂ )

∙-cong : ∀ {a b : K'} {u v : V} -> a ≈ᵏ b -> u ≈ v -> (a ∙ u) ≈ (b ∙ v)
∙-cong rₓ (r₁ , r₂) = ( ∙₁-cong rₓ r₁ , ∙₂-cong rₓ r₂ )

∙-identity : ∀ (x : V) → (1ᵏ ∙ x) ≈ x
∙-identity (x₁ , x₂) = ( ∙₁-identity x₁ , ∙₂-identity x₂ )

∙-absorbˡ : ∀ (x : V) → (0ᵏ ∙ x) ≈ 0#
∙-absorbˡ (x₁ , x₂) = ( ∙₁-absorbˡ x₁ , ∙₂-absorbˡ x₂ )

-‿inverseˡ : LeftInverse 0# -_ _+_
-‿inverseˡ (x₁ , x₂) = ( -₁‿inverseˡ x₁ , -₂‿inverseˡ x₂ )

-‿inverseʳ : RightInverse 0# -_ _+_
-‿inverseʳ (x₁ , x₂) = ( -₁‿inverseʳ x₁ , -₂‿inverseʳ x₂ )

-‿inverse : Inverse 0# -_ _+_
-‿inverse = -‿inverseˡ , -‿inverseʳ

-‿cong : Congruent₁ -_
-‿cong  (x₁ , x₂) = ( -₁‿cong x₁ , -₂‿cong x₂ )

isMagma : IsMagma _+_
isMagma = record
  { isEquivalence = ≈-isEquiv
  ; ∙-cong        = +-cong
  }

isSemigroup : IsSemigroup _+_
isSemigroup = record
  { isMagma = isMagma
  ; assoc   = +-assoc
  }

isMonoid : IsMonoid _+_ 0#
isMonoid = record
  { isSemigroup = isSemigroup
  ; identity    = +-identity
  }

isGroup : IsGroup _+_ 0# -_
isGroup = record
  { isMonoid = isMonoid
  ; inverse  = -‿inverse
  ; ⁻¹-cong   = -‿cong
  }

isAbelianGroup : IsAbelianGroup _+_ 0# -_
isAbelianGroup = record
  { isGroup = isGroup
  ; comm    = +-comm
  }

isVectorSpace : IsVectorSpace K _≈_ _+_ _∙_ -_ 0#
isVectorSpace = record
  { isAbelianGroup = isAbelianGroup
  ; *ᵏ-∙-compat      = *ᵏ-∙-compat
  ; ∙-+-distrib      = ∙-+-distrib
  ; ∙-+ᵏ-distrib     = ∙-+ᵏ-distrib
  ; ∙-cong           = ∙-cong
  ; ∙-identity       = ∙-identity
  ; ∙-absorbˡ         = ∙-absorbˡ
  }

vectorSpace : VectorSpace K (a₁ ⊔ a₂)  (ℓ₁ ⊔ ℓ₂)
vectorSpace = record { isVectorSpace = isVectorSpace }


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

module Dodo.Binary.Immediate where

-- Stdlib imports
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; _≢_; refl; subst) renaming (sym to ≡-sym)
open import Level using (Level; _⊔_)
open import Function using (_∘_; flip)
open import Data.Empty using (⊥-elim)
open import Data.Product using (_×_; _,_; proj₁; proj₂; ∃-syntax)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Relation.Nullary using (¬_)
open import Relation.Unary using (Pred)
open import Relation.Binary using (Rel; REL)
open import Relation.Binary using (IsStrictTotalOrder; Irreflexive; Trichotomous)
open import Relation.Binary using (Transitive)
open import Relation.Binary using (Tri; tri<; tri≈; tri>)
open import Relation.Binary.Construct.Closure.Transitive using (TransClosure; [_]; _∷_; _∷ʳ_; _++_)
-- Local imports
open import Dodo.Unary.Equality
open import Dodo.Unary.Unique
open import Dodo.Binary.Equality
open import Dodo.Binary.Transitive
open import Dodo.Binary.Functional
open import Dodo.Binary.Filter
open import Dodo.Binary.Domain

-- # Definitions #

-- | The immediate relation over the given (order) relation
immediate : ∀ {a ℓ : Level} {A : Set a}
  → Rel A ℓ
    -------------
  → Rel A (a ⊔ ℓ)
immediate r x y = r x y × ¬ (∃[ z ] r x z × TransClosure r z y)
-- A more conventional definitions is:
-- immediate r x y = r x y × (¬ ∃ λ{z → r x z × r z y})
-- which is identical to this one when r is Transitive

Immediate : ∀ {a ℓ : Level} {A : Set a}
  → Rel A ℓ
  → Set (a ⊔ ℓ)
-- For some reason, x and y have to be /explicit/. Otherwise, Agda complains about some
-- of Immediate's uses. Unsure why.
Immediate {A = A} r = ∀ (x y : A) → r x y → ¬ (∃[ z ] r x z × TransClosure r z y)

-- # Operations #

imm-flip : ∀ {a ℓ : Level} {A : Set a}
  → {R : Rel A ℓ} {x y : A}
  → immediate R x y
  → immediate (flip R) y x
imm-flip {R = R} {x} {y} (Rxy , ¬∃z) = (Rxy , lemma)
  where
  ⁺-invert : {a ℓ : Level} {A : Set a} {R : Rel A ℓ} {x y : A}
    → {z : A} → R x z → TransClosure R z y
    → ∃[ q ] (TransClosure R x q × R q y)
  ⁺-invert {z = z} Rxz [ Rzy ] = (z , [ Rxz ] , Rzy)
  ⁺-invert {z = z} Rxz ( Rzq ∷ R⁺qy ) with ⁺-invert Rzq R⁺qy
  ... | v , R⁺zv , Rvy = (v , Rxz ∷ R⁺zv , Rvy)

  lemma : ¬ (∃[ z ] (flip R y z × TransClosure (flip R) z x))
  lemma (z , flipRyz , flipR⁺zx) =
    let (q , R⁺yq , Rqx) = ⁺-invert flipRyz flipR⁺zx
    in ¬∃z (q , Rqx , ⁺-flip R⁺yq)

-- # Properties #

module _ {a ℓ : Level} {A : Set a} {R : Rel A ℓ} where

  imm-imm : Immediate (immediate R)
  imm-imm _ _ (Rxy , ¬∃z) (z , (Rxz , ¬∃w) , [immR]⁺xy) = ¬∃z (z , Rxz , ⁺-map _ proj₁ [immR]⁺xy)

  imm-⊆₂ : immediate R ⊆₂ R
  imm-⊆₂ = ⊆: λ{_ _ → proj₁}

module _ {a ℓ₁ ℓ₂ : Level} {A : Set a} {_≈_ : Rel A ℓ₁} {_<_ : Rel A ℓ₂} where

  imm-uniqueˡ : Trichotomous _≈_ _<_ → {z : A} → Unique₁ _≈_ λ{τ → immediate _<_ τ z}
  imm-uniqueˡ triR {z} {x} {y} (Rxz , ¬∃y) (Ryz , ¬∃x) with triR x y
  ... | tri<  Rxy x≉y ¬Ryx = ⊥-elim (¬∃y (y , Rxy , [ Ryz ]))
  ... | tri≈ ¬Rxy x≈y ¬Ryx = x≈y
  ... | tri> ¬Rxy x≉y  Ryx = ⊥-elim (¬∃x (x , Ryx , [ Rxz ]))

  imm-uniqueʳ : Trichotomous _≈_ _<_ → {x : A} → Unique₁ _≈_ (immediate _<_ x)
  imm-uniqueʳ triR {x} {y} {z} (Rxy , ¬∃z) (Rxz , ¬∃y) with triR y z
  ... | tri<  Ryz y≈z ¬Rzy = ⊥-elim (¬∃y (y , Rxy , [ Ryz ]))
  ... | tri≈ ¬Ryz y≈z ¬Rzy = y≈z
  ... | tri> ¬Ryz y≈z  Rzy = ⊥-elim (¬∃z (z , Rxz , [ Rzy ]))

module _ {a ℓ₁ ℓ₂ : Level} {A : Set a} {≈ : Rel A ℓ₁} {< : Rel A ℓ₂} where

  -- immediate < x y → immediate < x z → y ≈ z
  imm-func : IsStrictTotalOrder ≈ < → Functional ≈ (immediate <)
  imm-func sto x y₁ y₂ (x<y₁ , ¬∃z[x<z×z<y₁]) (x<y₂ , ¬∃z[x<z×z<y₂])
      with IsStrictTotalOrder.compare sto y₁ y₂
  ... | tri< y₁<y₂ _     _     = ⊥-elim (¬∃z[x<z×z<y₂] (y₁ , x<y₁ , [ y₁<y₂ ]))
  ... | tri≈ _     y₁≈y₂ _     = y₁≈y₂
  ... | tri> _     _     y₂<y₁ = ⊥-elim (¬∃z[x<z×z<y₁] (y₂ , x<y₂ , [ y₂<y₁ ]))

module _ {a ℓ₁ ℓ₂ : Level} {A : Set a} {P : Pred A ℓ₁} {R : Rel A ℓ₂} where

  imm-filter-⊆₂ : filter-rel P (immediate R) ⊆₂ immediate (filter-rel P R)
  imm-filter-⊆₂ = ⊆: lemma
    where
    lemma : filter-rel P (immediate R) ⊆₂' immediate (filter-rel P R)
    lemma (with-pred x Px) (with-pred y Py) (Rxy , ¬∃z) = Rxy , ¬∃z'
      where
      ¬∃z' : ¬ (∃[ z ] (filter-rel P R (with-pred x Px) z × TransClosure (filter-rel P R) z (with-pred y Py)))
      ¬∃z' (with-pred z Pz , Rxz , fR⁺zy) = ¬∃z (z , Rxz , ⁺-strip-filter fR⁺zy)

module _ {a ℓ : Level} {A : Set a} {R : Rel A ℓ} where

  immediate⁺ : Immediate R → R ⇔₂ immediate (TransClosure R)
  immediate⁺ immR = ⇔: ⊆-proof ⊇-proof
    where
    ⊆-proof : R ⊆₂' immediate (TransClosure R)
    ⊆-proof x y xRy = ([ xRy ] , lemma x y xRy)
      where
      lemma : (x y : A) → R x y → ¬ (∃[ z ] TransClosure R x z × TransClosure (TransClosure R) z y)
      lemma x y xRy (z , [ xRz ] , zR⁺y) =
        immR x y xRy (z , xRz , ⇔₂-apply-⊇₂ ⁺-idem zR⁺y)
      lemma x y xRy (z , _∷_ {_} {w} xRw wR⁺z , zR⁺y) =
        immR x y xRy (w , xRw , ⇔₂-apply-⊇₂ ⁺-idem (wR⁺z ∷ zR⁺y))

    ⊇-proof : immediate (TransClosure R) ⊆₂' R
    ⊇-proof x y ([ x∼y ] , ¬∃z) = x∼y
    ⊇-proof x y (_∷_ {_} {w} x∼w wR⁺y , ¬∃z) = ⊥-elim (¬∃z (w , [ x∼w ] , [ wR⁺y ]))

  trans-imm⁺-⊆ : Transitive R → TransClosure (immediate R) ⊆₂ R
  trans-imm⁺-⊆ transR = ⊆: lemma
    where
    lemma : TransClosure (immediate R) ⊆₂' R
    lemma x y [ R[xy] ] = proj₁ R[xy]
    lemma x y (_∷_ {_} {z} R[xz] R⁺[zy]) = transR (proj₁ R[xz]) (lemma z y R⁺[zy])

  imm-udr-⊆₁ : udr (immediate R) ⊆₁ udr R
  imm-udr-⊆₁ = ⊆: lemma
    where
    lemma : udr (immediate R) ⊆₁' udr R
    lemma _ (inj₁ (y , Rxy , ¬∃z)) = inj₁ (y , Rxy)
    lemma _ (inj₂ (x , Rxy , ¬∃z)) = inj₂ (x , Rxy)


-- Jesper, 2016-11-04
-- Absurd patterns should *not* be counted as a UnusedArg.

open import Common.Equality

data ⊥ : Set where

data Bool : Set where
  true false : Bool

abort : (A : Set) → ⊥ → A
abort A ()

test : (x y : ⊥) → abort Bool x ≡ abort Bool y
test x y = refl


{-# OPTIONS --cubical --allow-unsolved-metas #-}

open import Agda.Primitive.Cubical
open import Agda.Builtin.Cubical.Path

module _ where

data D {ℓ} (A : Set ℓ) : Set ℓ where
  c : PathP _ _ _