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

open import Cubical.Foundations.Prelude
open import Cubical.Relation.Nullary
open import Cubical.Data.Sum
open import Cubical.Data.Nat
open import Cubical.Axiom.Omniscience as O hiding (WLPO ; LPO)

open import Misc
open import Z

module LPO where

LPO : { ℓ' : Level} (A : Type )  Type (ℓ-max  (ℓ-suc ℓ'))
LPO {ℓ' = ℓ'} A = (P : A  Type ℓ')  ((n : A)  isProp (P n))  ((n : A)  Dec (P n))  ((n : A)  P n)  Σ A  n  ¬ (P n))

postulate
  -- NOTE: one should be enough since the two are equivalent
  LPOℕ : {ℓ' : Level}  LPO {ℓ' = ℓ'} 
  LPOℤ : {ℓ' : Level}  LPO {ℓ' = ℓ'} 

DecΣ : { ℓ' : Level} {A : Type }  LPO A  (P : A  Type ℓ')  ((n : A)  Dec (P n))  Dec (Σ A P)
DecΣ LPO P D with LPO  n  ¬ (P n))  _  isProp¬ _)  n  Dec¬ (D n))
... | inl ¬p = no λ { (n , p)  ¬p n p }
... | inr (n , ¬¬p) = yes (n , Dec→NNE (D n) ¬¬p)

DecΣℕ : { : Level} (P :   Type )  ((n : )  Dec (P n))  Dec (Σ  P)
DecΣℕ = DecΣ LPOℕ

DecΣℤ : { : Level} (P :   Type )  ((n : )  Dec (P n))  Dec (Σ  P)
DecΣℤ = DecΣ LPOℤ

DecΠℕ : { : Level} (P :   Type )  ((n : )  isProp (P n))  ((n : )  Dec (P n))  Dec ((n : )  P n)
DecΠℕ P PP D with LPOℕ P PP D
... | inl p = yes p
... | inr (n , ¬p) = no λ p  ¬p (p n)

DecΠℤ : { : Level} (P :   Type )  ((n : )  isProp (P n))  ((n : )  Dec (P n))  Dec ((n : )  P n)
DecΠℤ P PP D with LPOℤ P PP D
... | inl p = yes p
... | inr (n , ¬p) = no  p  ¬p (p n))