\begin{code}
{-# OPTIONS --cubical --safe #-}
module Cardinality.Finite.SplitEnumerable.Search where
open import Prelude
open import Cardinality.Finite.SplitEnumerable
open import Cardinality.Finite.SplitEnumerable.Inductive
open import Cardinality.Finite.ManifestEnumerable using (ℰ⇒Omniscient; ℰ!⇒ℰ)
open import Data.Product.NAry
open import Relation.Nullary.Decidable.Properties
open import Data.Fin
open import Relation.Nullary.Omniscience
open import Cardinality.Finite.SplitEnumerable.Isomorphism
open import HITs.PropositionalTruncation
open import HITs.PropositionalTruncation.Properties
private variable p : Level
ℰ!⇒Omniscient : ℰ! A → Omniscient p A
ℰ!⇒Omniscient = ℰ⇒Omniscient ∘ ℰ!⇒ℰ
ℰ!⇒Exhaustible : ℰ! A → Exhaustible p A
ℰ!⇒Exhaustible = Omniscient→Exhaustible ∘ ℰ!⇒Omniscient
ℰ!⟨fib⟩ : (f : A → B) → (y : B) → ℰ! A → ℰ! B → ℰ! ∥ fiber f y ∥
ℰ!⟨fib⟩ f y xs ys with ℰ!⇒Omniscient xs λ x → ℰ!⇒Discrete (𝕃⇔ℒ⟨ℰ!⟩ .fun ys) (f x) y
ℰ!⟨fib⟩ f y xs ys | yes p = ∣ p ∣ ∷ [] , λ _ → f0 , squash _ _
ℰ!⟨fib⟩ f y xs ys | no ¬p = [] , ⊥-elim ∘ refute-trunc ¬p
tup-inst′ : ∀ n {ls} {Xs : Types (suc n) ls} → ⦅ map-types ℰ! Xs ⦆⁺ → ℰ! ⦅ Xs ⦆⁺
tup-inst′ zero x = x
tup-inst′ (suc n) (x , xs) = x |×| tup-inst′ n xs
tup-inst : ∀ n {ls} {Xs : Types n ls} → ⦅ map-types ℰ! Xs ⦆ → ℰ! ⦅ Xs ⦆
tup-inst zero xs = _ ∷ [] , λ _ → f0 , refl
tup-inst (suc n) xs = tup-inst′ n xs
Dec⇔ : (B ⇔ A) → Dec A → Dec B
Dec⇔ A⇔B = ⟦yes A⇔B .inv ,no A⇔B .fun ⟧
module _ {a p} {A : Type a} {P : A → Type p} where
\end{code}
%<*forall-ask>
\begin{code}
∀? : ℰ! A →
(∀ x → Dec (P x)) →
Dec (∀ x → P x)
∀? ℰ!⟨A⟩ = ℰ!⇒Exhaustible ℰ!⟨A⟩
\end{code}
%</forall-ask>
%<*exists-ask>
\begin{code}
∃? : ℰ! A →
(∀ x → Dec (P x)) →
Dec (∃[ x ] P x)
∃? ℰ!⟨A⟩ = ℰ!⇒Omniscient ℰ!⟨A⟩
\end{code}
%</exists-ask>
\begin{code}
module PreInst {a p} {A : Type a} {P : A → Type p} where
\end{code}
%<*forall-zap>
\begin{code}
∀↯ : (ℰ!⟨A⟩ : ℰ! A) →
(P? : ∀ x → Dec (P x)) →
⦃ _ : True (∀? ℰ!⟨A⟩ P?) ⦄ →
∀ x → P x
∀↯ _ _ ⦃ t ⦄ = toWitness t
\end{code}
%</forall-zap>
%<*exists-zap>
\begin{code}
∃↯ : (ℰ!⟨A⟩ : ℰ! A) →
(P? : ∀ x → Dec (P x)) →
⦃ _ : True (∃? ℰ!⟨A⟩ P?) ⦄ →
∃[ x ] P x
∃↯ _ _ ⦃ t ⦄ = toWitness t
\end{code}
%</exists-zap>
\begin{code}
module WithInst {a p} {A : Type a} {P : A → Type p} where
\end{code}
%<*forall-zap-inst>
\begin{code}
∀↯ : ⦃ ℰ!⟨A⟩ : ℰ! A ⦄ →
(P? : ∀ x → Dec (P x)) →
⦃ _ : True (∀? ℰ!⟨A⟩ P?) ⦄ →
∀ x → P x
∀↯ _ ⦃ t ⦄ = toWitness t
\end{code}
%</forall-zap-inst>
%<*exists-zap-inst>
\begin{code}
∃↯ : ⦃ ℰ!⟨A⟩ : ℰ! A ⦄ →
(P? : ∀ x → Dec (P x)) →
⦃ _ : True (∃? ℰ!⟨A⟩ P?) ⦄ →
∃[ x ] P x
∃↯ _ ⦃ t ⦄ = toWitness t
\end{code}
%</exists-zap-inst>
\begin{code}
module _ (n : ℕ)
{ls ℓ}
{Xs : Types n ls}
{P : ⦅ Xs ⦆ → Type ℓ}
where
∀?ⁿ : ⦅ map-types ℰ! Xs ⦆[ inst ]→
xs ⦂⦅ Xs ⦆Π[ expl ]→
Dec (P xs) [ expl ]→
Dec (xs ⦂⦅ Xs ⦆Π[ expl ]→ P xs)
∀?ⁿ = [ n ^ inst $] .inv λ fs
→ Dec⇔ Π[ n ^ expl $]
∘ Omniscient→Exhaustible (ℰ!⇒Omniscient (tup-inst n fs))
∘ Π[ n ^ expl $] .fun
\end{code}
%<*exists-q-n>
\begin{code}
∃?ⁿ : ⦅ map-types ℰ! Xs ⦆[ inst ]→
xs ⦂⦅ Xs ⦆Π[ expl ]→
Dec (P xs) [ expl ]→
Dec (Σ ⦅ Xs ⦆ P)
∃?ⁿ = [ n ^ inst $] .inv λ fs
→ ℰ!⇒Omniscient (tup-inst n fs)
∘ Π[ n ^ expl $] .fun
\end{code}
%</exists-q-n>
\begin{code}
∀↯ⁿ : insts ⦂⦅ map-types ℰ! Xs ⦆Π[ inst ]→
( (P? : xs ⦂⦅ Xs ⦆Π[ expl ]→ Dec (P xs))
→ ⦃ _ : True (Omniscient→Exhaustible (ℰ!⇒Omniscient (tup-inst n insts)) (Π[ n ^ expl $] .fun P?)) ⦄
→ xs ⦂⦅ Xs ⦆Π[ expl ]→ P xs)
∀↯ⁿ = Π[ n ^ inst $] .inv λ fs P? ⦃ p ⦄ → Π[ n ^ expl $] .inv (toWitness p)
\end{code}
%<*exists-zap-n>
\begin{code}
∃↯ⁿ :
insts ⦂⦅ map-types ℰ! Xs ⦆Π[ inst ]→
((P? : xs ⦂⦅ Xs ⦆Π[ expl ]→ Dec (P xs))
→ ⦃ _ : True
(ℰ!⇒Omniscient
(tup-inst n insts)
(Π[ n ^ expl $] .fun P?)) ⦄
→ Σ ⦅ Xs ⦆ P)
∃↯ⁿ =
Π[ n ^ inst $] .inv
λ fs P? ⦃ p ⦄ → toWitness p
\end{code}
%</exists-zap-n>