Lists, added All and Any
This commit is contained in:
parent
7a369f9f8d
commit
652da6c516
5 changed files with 167 additions and 20 deletions
|
@ -52,7 +52,6 @@ https://github.com/agda/agda/blob/master/src/data/emacs-mode/agda-input.el#L194
|
|||
C-c C-c x split on variable x
|
||||
C-c C-space fill in hole
|
||||
|
||||
|
||||
Also see [here](
|
||||
http://agda.readthedocs.io/en/latest/tools/emacs-mode.html
|
||||
).
|
||||
|
|
|
@ -27,7 +27,7 @@ record _≃_ (A B : Set) : Set where
|
|||
fro : B → A
|
||||
invˡ : ∀ (x : A) → fro (to x) ≡ x
|
||||
invʳ : ∀ (y : B) → to (fro y) ≡ y
|
||||
open _≃_
|
||||
open _≃_
|
||||
\end{code}
|
||||
Let's unpack the definition. An isomorphism between sets `A` and `B` consists
|
||||
of four things:
|
||||
|
|
160
src/Lists.lagda
160
src/Lists.lagda
|
@ -13,8 +13,12 @@ introducing polymorphic types and functions.
|
|||
import Relation.Binary.PropositionalEquality as Eq
|
||||
open Eq using (_≡_; refl; sym; trans; cong)
|
||||
open Eq.≡-Reasoning
|
||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_)
|
||||
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _≤_; s≤s; z≤n)
|
||||
open import Data.Nat.Properties using (+-assoc; +-identityˡ; +-identityʳ; *-assoc; *-identityˡ; *-identityʳ)
|
||||
open import Relation.Nullary using (¬_)
|
||||
open import Data.Product using (_×_) renaming (_,_ to ⟨_,_⟩)
|
||||
open import Isomorphism using (_≃_)
|
||||
open import Function using (_∘′_)
|
||||
\end{code}
|
||||
|
||||
## Lists
|
||||
|
@ -601,7 +605,12 @@ Use fold to define a function to find the product of a list of numbers.
|
|||
|
||||
Show that fold and append are related as follows.
|
||||
|
||||
\begin{code}
|
||||
postulate
|
||||
foldr-++ : ∀ {A B : Set} (_⊗_ : A → B → B) (e : B) (xs ys : List A) →
|
||||
foldr _⊗_ e (xs ++ ys) ≡ foldr _⊗_ (foldr _⊗_ e ys) xs
|
||||
\end{code}
|
||||
|
||||
|
||||
*Exercise* (`map-is-foldr`) <!-- `mapIsFold` in Data.List.Properties -->
|
||||
|
||||
|
@ -660,9 +669,9 @@ list, are all examples of monoids.
|
|||
If `_⊕_` and `e` form a monoid, then we can re-express fold on the
|
||||
same operator and an arbitrary value.
|
||||
\begin{code}
|
||||
fold-monoid : ∀ {A : Set} (_⊗_ : A → A → A) (e : A) → Monoid _⊗_ e →
|
||||
∀ (y : A) (xs : List A) → foldr _⊗_ e xs ⊗ y ≡ foldr _⊗_ y xs
|
||||
fold-monoid _⊗_ e ⊗-monoid y [] =
|
||||
foldr-monoid : ∀ {A : Set} (_⊗_ : A → A → A) (e : A) → Monoid _⊗_ e →
|
||||
∀ (xs : List A) (y : A) → foldr _⊗_ e xs ⊗ y ≡ foldr _⊗_ y xs
|
||||
foldr-monoid _⊗_ e ⊗-monoid [] y =
|
||||
begin
|
||||
foldr _⊗_ e [] ⊗ y
|
||||
≡⟨⟩
|
||||
|
@ -672,35 +681,158 @@ fold-monoid _⊗_ e ⊗-monoid y [] =
|
|||
≡⟨⟩
|
||||
foldr _⊗_ y []
|
||||
∎
|
||||
fold-monoid _⊗_ e ⊗-monoid y (x ∷ xs) =
|
||||
foldr-monoid _⊗_ e ⊗-monoid (x ∷ xs) y =
|
||||
begin
|
||||
foldr _⊗_ e (x ∷ xs) ⊗ y
|
||||
≡⟨⟩
|
||||
(x ⊗ foldr _⊗_ e xs) ⊗ y
|
||||
≡⟨ assoc ⊗-monoid x (foldr _⊗_ e xs) y ⟩
|
||||
x ⊗ (foldr _⊗_ e xs ⊗ y)
|
||||
≡⟨ cong (x ⊗_) (fold-monoid _⊗_ e ⊗-monoid y xs) ⟩
|
||||
≡⟨ cong (x ⊗_) (foldr-monoid _⊗_ e ⊗-monoid xs y) ⟩
|
||||
x ⊗ (foldr _⊗_ y xs)
|
||||
≡⟨⟩
|
||||
foldr _⊗_ y (x ∷ xs)
|
||||
∎
|
||||
\end{code}
|
||||
|
||||
As a consequence of `foldr-++` and `fold-monoid`, it is easy to show
|
||||
As a consequence, using a previous exercise, we have the following.
|
||||
\begin{code}
|
||||
foldr-monoid-++ : ∀ {A : Set} (_⊗_ : A → A → A) (e : A) → Monoid _⊗_ e →
|
||||
(xs ys : List A) → foldr _⊗_ e (xs ++ ys) ≡ foldr _⊗_ e xs ⊗ foldr _⊗_ e ys
|
||||
foldr-monoid-++ _⊗_ e monoid-⊗ xs ys =
|
||||
begin
|
||||
foldr _⊗_ e (xs ++ ys)
|
||||
≡⟨ foldr-++ _⊗_ e xs ys ⟩
|
||||
foldr _⊗_ (foldr _⊗_ e ys) xs
|
||||
≡⟨ sym (foldr-monoid _⊗_ e monoid-⊗ xs (foldr _⊗_ e ys)) ⟩
|
||||
foldr _⊗_ e xs ⊗ foldr _⊗_ e ys
|
||||
∎
|
||||
\end{code}
|
||||
|
||||
## All and Any
|
||||
|
||||
foldr _⊗_ e (xs ++ ys) ≡ foldr _⊗_ e xs ⊗ foldr _⊗_ e ys
|
||||
We can also define predicates over lists. Two of the most important are `All` and `Any`.
|
||||
|
||||
Predicate `All P` holds if predicate `P` is satisfied by every element of a list.
|
||||
\begin{code}
|
||||
data All {A : Set} (P : A → Set) : List A → Set where
|
||||
[] : All P []
|
||||
_∷_ : {x : A} {xs : List A} → P x → All P xs → All P (x ∷ xs)
|
||||
\end{code}
|
||||
The type has two constructors, reusing the names of the same constructors for lists.
|
||||
The first asserts that `All P` always holds of the empty list.
|
||||
The second asserts that if `P` holds of the head of a list, and if `All P`
|
||||
holds of the tail of the list, then `All P` holds for the entire list.
|
||||
Agda uses type information to distinguish whether the constructor is building
|
||||
a list, or evidence that `All P` holds.
|
||||
|
||||
## Element
|
||||
For example, `All (_≤ 2)` holds of a list where every element is less
|
||||
than or equal to two. Recall that `z≤n` proves `zero ≤ n` for any
|
||||
`n`, and that if `m≤n` proves `m ≤ n` then `s≤s m≤n` proves `suc m ≤
|
||||
suc n`, for any `m` and `n`.
|
||||
\begin{code}
|
||||
ex₁₀ : All (_≤ 2) ([ 0 , 1 , 2 ])
|
||||
ex₁₀ = z≤n ∷ (s≤s z≤n) ∷ (s≤s (s≤s z≤n)) ∷ []
|
||||
\end{code}
|
||||
Here `_∷_` and `[]` are the constructors of `All P` rather than of `List A`.
|
||||
The three items are proofs of `0 ≤ 2`, `1 ≤ 2`, and `2 ≤ 2`, respectively.
|
||||
|
||||
Predicate `Any P` holds if predicate `P` is satisfied by some element of a list.
|
||||
\begin{code}
|
||||
data Any {A : Set} (P : A → Set) : List A → Set where
|
||||
here : {x : A} {xs : List A} → P x → Any P (x ∷ xs)
|
||||
there : {x : A} {xs : List A} → Any P xs → Any P (x ∷ xs)
|
||||
\end{code}
|
||||
The first constructor provides evidence that the head of the list satisfies `P`,
|
||||
while the second provides evidence that the tail of the list satisfies `Any P`.
|
||||
For example, we can define list membership as follows.
|
||||
\begin{code}
|
||||
infix 4 _∈_
|
||||
|
||||
_∈_ : ∀ {A : Set} (x : A) (xs : List A) → Set
|
||||
x ∈ xs = Any (x ≡_) xs
|
||||
|
||||
_∉_ : ∀ {A : Set} (x : A) (xs : List A) → Set
|
||||
x ∉ xs = ¬ (x ∈ xs)
|
||||
\end{code}
|
||||
For example, we have `0 ∈ ([ 0 , 1 , 0 ])`. Indeed, we can demonstrate
|
||||
this fact in two different ways, corresponding to the two different
|
||||
occurrences of zero in the list, as the first element and as the third element.
|
||||
\begin{code}
|
||||
ex₁₁ ex₁₂ : 0 ∈ ([ 0 , 1 , 0 ])
|
||||
ex₁₁ = here refl
|
||||
ex₁₂ = there (there (here refl))
|
||||
\end{code}
|
||||
Further, we can demonstrate that two is not in the list, because
|
||||
any possible proof that it is in the list leads to contradiction.
|
||||
\begin{code}
|
||||
ex₁₃ : 2 ∉ ([ 0 , 1 , 0 ])
|
||||
ex₁₃ (here ())
|
||||
ex₁₃ (there (here ()))
|
||||
ex₁₃ (there (there (here ())))
|
||||
ex₁₃ (there (there (there ())))
|
||||
\end{code}
|
||||
The four occurrences of `()` attest to the fact that there is no
|
||||
possible evidence for the facts `2 ≡ 0`, `2 ≡ 1`, `2 ≡ 0`, and
|
||||
`2 ∈ []`, respectively.
|
||||
|
||||
A predicate holds for every element of one list appended to another if and
|
||||
only if it holds for every element of each list. Indeed, an even stronger
|
||||
result is true, as we can show that the two types are isomorphic.
|
||||
\begin{code}
|
||||
All-++ : ∀ {A : Set} {P : A → Set} (xs ys : List A) → All P (xs ++ ys) ≃ (All P xs × All P ys)
|
||||
All-++ xs ys =
|
||||
record
|
||||
{ to = to xs ys
|
||||
; fro = fro xs ys
|
||||
; invˡ = invˡ xs ys
|
||||
; invʳ = invʳ xs ys
|
||||
}
|
||||
|
||||
where
|
||||
|
||||
to : ∀ {A : Set} {P : A → Set} (xs ys : List A) → All P (xs ++ ys) → (All P xs × All P ys)
|
||||
to [] ys AllPys = ⟨ [] , AllPys ⟩
|
||||
to (x ∷ xs) ys (Px ∷ AllPxsys) with to xs ys AllPxsys
|
||||
... | ⟨ AllPxs , AllPys ⟩ = ⟨ Px ∷ AllPxs , AllPys ⟩
|
||||
|
||||
fro : ∀ { A : Set} {P : A → Set} (xs ys : List A) → All P xs × All P ys → All P (xs ++ ys)
|
||||
fro [] ys ⟨ [] , AllPys ⟩ = AllPys
|
||||
fro (x ∷ xs) ys ⟨ Px ∷ AllPxs , AllPys ⟩ = Px ∷ fro xs ys ⟨ AllPxs , AllPys ⟩
|
||||
|
||||
invˡ : ∀ { A : Set} {P : A → Set} (xs ys : List A) → (AllPxsys : All P (xs ++ ys)) →
|
||||
fro xs ys (to xs ys AllPxsys) ≡ AllPxsys
|
||||
invˡ [] ys AllPys = refl
|
||||
invˡ (x ∷ xs) ys (Px ∷ AllPxsys) = cong (Px ∷_) (invˡ xs ys AllPxsys)
|
||||
|
||||
invʳ : ∀ { A : Set} {P : A → Set} (xs ys : List A) → (AllPxsAllPys : All P xs × All P ys) →
|
||||
to xs ys (fro xs ys AllPxsAllPys) ≡ AllPxsAllPys
|
||||
invʳ [] ys ⟨ [] , AllPys ⟩ = refl
|
||||
invʳ (x ∷ xs) ys ⟨ Px ∷ AllPxs , AllPys ⟩ rewrite invʳ xs ys ⟨ AllPxs , AllPys ⟩ = refl
|
||||
\end{code}
|
||||
|
||||
*Exercise* `Any-++`
|
||||
|
||||
Prove a result similar to `All-++`, but with `Any` in place of `All`, and a suitable
|
||||
replacement for `_×_`. As a consequence, demonstrate an isomorphism relating
|
||||
`_∈_` and `_++_`.
|
||||
|
||||
*Exercise* `¬Any≃All¬`
|
||||
|
||||
Show that `Any` and `All` satisfy a version of De Morgan's Law.
|
||||
|
||||
\begin{code}
|
||||
data _∈_ {A : Set} (x : A) : List A → Set where
|
||||
here : {y : A} {ys : List A} → x ≡ y → x ∈ y ∷ ys
|
||||
there : {y : A} {ys : List A} → x ∈ ys → x ∈ y ∷ ys
|
||||
|
||||
infix 4 _∈_
|
||||
postulate
|
||||
¬Any≃All¬ : ∀ {A : Set} (P : A → Set) (xs : List A) → ¬ Any P xs ≃ All (λ x → ¬ P x) xs
|
||||
\end{code}
|
||||
|
||||
Do we also have the following?
|
||||
|
||||
¬ All P xs ≃ Any (λ x → ¬ P x) xs
|
||||
|
||||
If so, prove; if not, explain why.
|
||||
|
||||
|
||||
## Unicode
|
||||
|
||||
∷ U+2237 PROPORTION (\::)
|
||||
|
|
|
@ -833,6 +833,22 @@ excluded-middle-irrefutable : ∀ {A : Set} → ¬ ¬ (A ⊎ ¬ A)
|
|||
excluded-middle-irrefutable k = k (inj₂ (λ a → k (inj₁ a)))
|
||||
\end{code}
|
||||
|
||||
*Exercise* (`¬⊎≃׬`)
|
||||
|
||||
Show that conjunction, disjunction, and negation are related by a
|
||||
version of De Morgan's Law.
|
||||
\begin{code}
|
||||
postulate
|
||||
¬⊎≃׬ : ∀ {A B : Set} → ¬ (A ⊎ B) ≃ (¬ A) × (¬ B)
|
||||
\end{code}
|
||||
This result is an easy consequence of something we've proved previously.
|
||||
|
||||
Do we also have the following?
|
||||
|
||||
¬ (A × B) ≃ (¬ A) ⊎ (¬ B)
|
||||
|
||||
If so, prove; if not, explain why.
|
||||
|
||||
|
||||
## Intuitive and Classical logic
|
||||
|
||||
|
@ -878,7 +894,7 @@ a disjoint sum.
|
|||
(The passage above is taken from "Propositions as Types", Philip Wadler,
|
||||
*Communications of the ACM*, December 2015.)
|
||||
|
||||
**Exercise** Prove the following six formulas are equivalent.
|
||||
**Exercise** Prove the following five formulas are equivalent.
|
||||
|
||||
\begin{code}
|
||||
lone ltwo : Level
|
||||
|
@ -890,9 +906,7 @@ ltwo = lsuc lone
|
|||
excluded-middle = ∀ {A : Set} → A ⊎ ¬ A
|
||||
peirce = ∀ {A B : Set} → (((A → B) → A) → A)
|
||||
implication = ∀ {A B : Set} → (A → B) → ¬ A ⊎ B
|
||||
de-morgan = ∀ {A B : Set} → ¬ (¬ A × ¬ B) → A ⊎ B
|
||||
de-morgan′ = ∀ {A B : Set} → ¬ (¬ A ⊎ ¬ B) → A × B
|
||||
|
||||
de-morgan = ∀ {A B : Set} → ¬ (A × B) → ¬ A ⊎ ¬ B
|
||||
\end{code}
|
||||
|
||||
It turns out that an assertion such as `Set : Set` is paradoxical.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import Data.List.Properties
|
||||
import Data.List.All
|
||||
import Data.Nat.Properties
|
||||
import Data.Nat.Properties.Simple
|
||||
import Relation.Nullary
|
||||
|
||||
|
|
Loading…
Reference in a new issue