------------------------------------------------------------------------ -- The Agda standard library -- -- Properties related to All ------------------------------------------------------------------------ module Data.List.All.Properties where open import Data.Bool open import Data.Bool.Properties open import Data.Empty open import Data.List as List import Data.List.Any as Any; open Any.Membership-≡ open import Data.List.All as All using (All; []; _∷_) open import Data.List.Any using (Any; here; there) open import Data.Product as Prod open import Function open import Function.Equality using (_⟨$⟩_) open import Function.Equivalence using (_⇔_; module Equivalence) open import Function.Inverse using (_↔_) open import Function.Surjection using (_↠_) open import Relation.Binary.PropositionalEquality as P using (_≡_) open import Relation.Nullary open import Relation.Unary using (Decidable) renaming (_⊆_ to _⋐_) -- Functions can be shifted between the predicate and the list. All-map : ∀ {a b p} {A : Set a} {B : Set b} {P : B → Set p} {f : A → B} {xs} → All (P ∘ f) xs → All P (List.map f xs) All-map [] = [] All-map (p ∷ ps) = p ∷ All-map ps map-All : ∀ {a b p} {A : Set a} {B : Set b} {P : B → Set p} {f : A → B} {xs} → All P (List.map f xs) → All (P ∘ f) xs map-All {xs = []} [] = [] map-All {xs = _ ∷ _} (p ∷ ps) = p ∷ map-All ps -- A variant of All.map. gmap : ∀ {a b p q} {A : Set a} {B : Set b} {P : A → Set p} {Q : B → Set q} {f : A → B} → P ⋐ Q ∘ f → All P ⋐ All Q ∘ List.map f gmap g = All-map ∘ All.map g -- All and all are related via T. All-all : ∀ {a} {A : Set a} (p : A → Bool) {xs} → All (T ∘ p) xs → T (all p xs) All-all p [] = _ All-all p (px ∷ pxs) = Equivalence.from T-∧ ⟨$⟩ (px , All-all p pxs) all-All : ∀ {a} {A : Set a} (p : A → Bool) xs → T (all p xs) → All (T ∘ p) xs all-All p [] _ = [] all-All p (x ∷ xs) px∷xs with Equivalence.to (T-∧ {p x}) ⟨$⟩ px∷xs all-All p (x ∷ xs) px∷xs | (px , pxs) = px ∷ all-All p xs pxs -- All is anti-monotone. anti-mono : ∀ {a p} {A : Set a} {P : A → Set p} {xs ys} → xs ⊆ ys → All P ys → All P xs anti-mono xs⊆ys pys = All.tabulate (All.lookup pys ∘ xs⊆ys) -- all is anti-monotone. all-anti-mono : ∀ {a} {A : Set a} (p : A → Bool) {xs ys} → xs ⊆ ys → T (all p ys) → T (all p xs) all-anti-mono p xs⊆ys = All-all p ∘ anti-mono xs⊆ys ∘ all-All p _ -- All P (xs ++ ys) is isomorphic to All P xs and All P ys. private ++⁺ : ∀ {a p} {A : Set a} {P : A → Set p} {xs ys : List A} → All P xs → All P ys → All P (xs ++ ys) ++⁺ [] pys = pys ++⁺ (px ∷ pxs) pys = px ∷ ++⁺ pxs pys ++⁻ : ∀ {a p} {A : Set a} {P : A → Set p} (xs : List A) {ys} → All P (xs ++ ys) → All P xs × All P ys ++⁻ [] p = [] , p ++⁻ (x ∷ xs) (px ∷ pxs) = Prod.map (_∷_ px) id $ ++⁻ _ pxs ++⁺∘++⁻ : ∀ {a p} {A : Set a} {P : A → Set p} xs {ys} (p : All P (xs ++ ys)) → uncurry′ ++⁺ (++⁻ xs p) ≡ p ++⁺∘++⁻ [] p = P.refl ++⁺∘++⁻ (x ∷ xs) (px ∷ pxs) = P.cong (_∷_ px) $ ++⁺∘++⁻ xs pxs ++⁻∘++⁺ : ∀ {a p} {A : Set a} {P : A → Set p} {xs ys} (p : All P xs × All P ys) → ++⁻ xs (uncurry ++⁺ p) ≡ p ++⁻∘++⁺ ([] , pys) = P.refl ++⁻∘++⁺ (px ∷ pxs , pys) rewrite ++⁻∘++⁺ (pxs , pys) = P.refl ++↔ : ∀ {a p} {A : Set a} {P : A → Set p} {xs ys} → (All P xs × All P ys) ↔ All P (xs ++ ys) ++↔ {P = P} {xs = xs} = record { to = P.→-to-⟶ $ uncurry ++⁺ ; from = P.→-to-⟶ $ ++⁻ xs ; inverse-of = record { left-inverse-of = ++⁻∘++⁺ ; right-inverse-of = ++⁺∘++⁻ xs } } -- Three lemmas relating Any, All and negation. ¬Any↠All¬ : ∀ {a p} {A : Set a} {P : A → Set p} {xs} → ¬ Any P xs ↠ All (¬_ ∘ P) xs ¬Any↠All¬ {P = P} = record { to = P.→-to-⟶ (to _) ; surjective = record { from = P.→-to-⟶ from ; right-inverse-of = to∘from } } where to : ∀ xs → ¬ Any P xs → All (¬_ ∘ P) xs to [] ¬p = [] to (x ∷ xs) ¬p = ¬p ∘ here ∷ to xs (¬p ∘ there) from : ∀ {xs} → All (¬_ ∘ P) xs → ¬ Any P xs from [] () from (¬p ∷ _) (here p) = ¬p p from (_ ∷ ¬p) (there p) = from ¬p p to∘from : ∀ {xs} (¬p : All (¬_ ∘ P) xs) → to xs (from ¬p) ≡ ¬p to∘from [] = P.refl to∘from (¬p ∷ ¬ps) = P.cong₂ _∷_ P.refl (to∘from ¬ps) -- If equality of functions were extensional, then the surjection -- could be strengthened to a bijection. from∘to : P.Extensionality _ _ → ∀ xs → (¬p : ¬ Any P xs) → from (to xs ¬p) ≡ ¬p from∘to ext [] ¬p = ext λ () from∘to ext (x ∷ xs) ¬p = ext λ { (here p) → P.refl ; (there p) → P.cong (λ f → f p) $ from∘to ext xs (¬p ∘ there) } Any¬→¬All : ∀ {a p} {A : Set a} {P : A → Set p} {xs} → Any (¬_ ∘ P) xs → ¬ All P xs Any¬→¬All (here ¬p) = ¬p ∘ All.head Any¬→¬All (there ¬p) = Any¬→¬All ¬p ∘ All.tail Any¬⇔¬All : ∀ {a p} {A : Set a} {P : A → Set p} {xs} → Decidable P → Any (¬_ ∘ P) xs ⇔ ¬ All P xs Any¬⇔¬All {P = P} dec = record { to = P.→-to-⟶ Any¬→¬All ; from = P.→-to-⟶ (from _) } where from : ∀ xs → ¬ All P xs → Any (¬_ ∘ P) xs from [] ¬∀ = ⊥-elim (¬∀ []) from (x ∷ xs) ¬∀ with dec x ... | yes p = there (from xs (¬∀ ∘ _∷_ p)) ... | no ¬p = here ¬p -- If equality of functions were extensional, then the logical -- equivalence could be strengthened to a surjection. to∘from : P.Extensionality _ _ → ∀ {xs} (¬∀ : ¬ All P xs) → Any¬→¬All (from xs ¬∀) ≡ ¬∀ to∘from ext ¬∀ = ext (⊥-elim ∘ ¬∀)