{-# OPTIONS --safe #-}

module Decidable where

open import Cubical.Relation.Nullary
  using ( Stable )
  public
open import Cubical.Relation.Nullary.Properties
  using  ( Dec→Stable
         ; Discrete→isSet
         ; isPropDec
         )
  public
open import Cubical.Relation.Nullary.Base
  using
    ( Dec
    ; yes
    ; no
    ; Discrete
    )
  public


open import Level
open import Data.Bool
open import Path
open import Inspect
open import Data.Unit

T? :  d  Dec (T d)
T? = bool (no λ x  x) (yes tt)

open import HLevels using (isProp; isPropΠ)

isProp⇒Discrete : isProp A  Discrete A
isProp⇒Discrete p x y = yes (p x y)

isPropDiscrete : isProp (Discrete A)
isPropDiscrete _≟_ = isPropΠ  x  isPropΠ  y  isPropDec (Discrete→isSet _≟_ _ _))) _≟_

open import Data.Empty

infixr 2 dec
dec : (A  B)  (¬ A  B)  Dec A   B
dec t f (yes p) = t p
dec t f (no ¬p) = f ¬p

syntax dec  p  t)  ¬p  f) d = If d Then p  t Else ¬p  f

does : Dec A  Bool
does d = If d Then _  true Else _  false

from-does : (d : Dec A)  T (does d)  A
from-does (yes p) _ = p

map-dec : (A  B)  (¬ A  ¬ B)  Dec A  Dec B
map-dec t f d = If d Then p  yes (t p) Else ¬p  no (f ¬p)

open import Function
open import Data.Sigma

iff-dec : (A  B)  Dec A  Dec B
iff-dec (f , f⁻) = map-dec f λ ¬A B  ¬A (f⁻ B)

record EqAlg (A : Type a) : Type a where
  field
    _≡ᴮ_ : A  A  Bool
    sound :  x y  T (x ≡ᴮ y)  x  y
    complete :  x  T (x ≡ᴮ x)

  from-bool-eq : Discrete A
  from-bool-eq x y =
    map-dec
      (sound x y)
       x≢ᴮy x≡y  x≢ᴮy (subst  z  T (x ≡ᴮ z)) x≡y (complete x)))
      (T? (x ≡ᴮ y))
open EqAlg using (from-bool-eq) public

open import HITs.PropositionalTruncation

dec-trunc : Dec A  Dec  A 
dec-trunc = map-dec ∣_∣ (∥rec∥  ()))
    
dec-untrunc : Dec A   A   A
dec-untrunc (yes p) _ = p
dec-untrunc (no ¬p) p = absurd (∥rec∥  ()) ¬p p)

inj-discrete : (A  B)  Discrete B  Discrete A
inj-discrete (f , inj) eq? x y =
  map-dec inj  fx≢fy x≡y  fx≢fy (cong f x≡y) ) (eq? (f x) (f y))