module Cubical.Structures.Decidability where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Relation.Nullary.Base
import Cubical.Data.Empty as 

private
  variable
     ℓ' : Level
    A : Type 
    P : Type 

module _ { ℓ'} {P : Type } {A : Dec P  Type ℓ'} where

  decElim : ((p : P)  A (yes p))  ((¬p : ¬ P)  A (no ¬p))
           (p : Dec P)  A p
  decElim y n (yes p) = y p
  decElim y n (no ¬p) = n ¬p

module _ {} {P : Type } (isPropP : isProp P) where

  private
    isPropDec : isProp (Dec P)
    isPropDec (yes p) (yes q) = congS yes (isPropP p q)
    isPropDec (yes p) (no ¬q) = ⊥.rec (¬q p)
    isPropDec (no ¬p) (yes q) = ⊥.rec (¬p q)
    isPropDec (no ¬p) (no ¬q) = congS no (isProp→ ⊥.isProp⊥ ¬p ¬q)

  decRecYes : {A : Type } {y : P -> A} {n : ¬ P -> A} (p : P) (d : Dec P) -> decRec y n d  y p
  decRecYes {A = A} {y = y} {n = n} p = decElim  q -> congS y (isPropP q p)) λ ¬p -> ⊥.rec (¬p p)

  decRecNo : {A : Type } {y : P -> A} {n : ¬ P -> A} (¬p : ¬ P) (d : Dec P) -> decRec y n d  n ¬p
  decRecNo {A = A} {y = y} {n = n} ¬p = decElim  p -> ⊥.rec (¬p p))  ¬q -> congS n (isProp→ ⊥.isProp⊥ ¬q ¬p))