# Listen

```
{-# OPTIONS --allow-unsolved-metas #-}
open import Level using (Level)
import Relation.Binary.PropositionalEquality as ≡
open import Relation.Binary.PropositionalEquality using (_≡_)
open import Function.Base using (_∘_)
open import Data.Product hiding (map)
open import Function.Bundles using (_⇔_; mk⇔)

module Lists where
```

Der Parameter an das folgende Modul bewirkt, dass im folgenden `List` in
abhängigkeit von `X` definiert ist.

```
module List-Definition {ℓ : Level} (X : Set ℓ) where
  data List : Set ℓ where
    [] : List                    -- nil
    _∷_ : X → List → List        -- cons

  [_] : X → List
  [ x ] = x ∷ []

module _ {ℓ : Level} {X : Set ℓ} where
  open List-Definition X
  _++_ : List → List → List
  _++_ [] ys = ys
  _++_ (x ∷ xs) ys = x ∷ (_++_ xs ys)

  ++-assoc : ∀ x y z → (x ++ y) ++ z ≡ x ++ (y ++ z)
  ++-assoc [] y z = ≡.refl
  ++-assoc (x-h ∷ x-t) y z = ≡.cong (x-h ∷_) (++-assoc x-t y z)

  x++[]≡x : ∀ {x} → x ++ [] ≡ x
  x++[]≡x {[]} = ≡.refl
  x++[]≡x {x ∷ xs} rewrite (x++[]≡x {xs}) = ≡.refl
  -- x++[]≡x {x ∷ xs} = ≡.cong (x ∷_) x++[]≡x
  -- x++[]≡x {x ∷ xs} = ≡.cong (x ∷_) (x++[]≡x {xs})

  ∷-injectiveʳ : ∀ {x} {y₁ y₂} → x ∷ y₁ ≡ x ∷ y₂ → y₁ ≡ y₂
  ∷-injectiveʳ ≡.refl = ≡.refl

  ++-injectiveʳ : ∀ x {y₁} {y₂} → x ++ y₁ ≡ x ++ y₂ → y₁ ≡ y₂
  ++-injectiveʳ [] eq = eq
  ++-injectiveʳ (x ∷ xs) eq =
    ++-injectiveʳ xs (∷-injectiveʳ eq)

  _∷ʳ_ : List → X → List
  xs ∷ʳ x = xs ++ [ x ]

  -- hier im Modul lässt sich `map` nicht definieren,
  -- da Listen stets über `X` sind


module Map-Definition {ℓ ℓ'} {X : Set ℓ} {Y : Set ℓ'} where
  open List-Definition
  map : (f : X → Y) → List X → List Y
  map f [] = []
  map f (x ∷ xs) = f x ∷ map f xs

  map-++ : (f : X → Y) → ∀ (xs₁ xs₂ : List X)
           → map f (xs₁ ++ xs₂) ≡ (map f xs₁ ++ map f xs₂)
  map-++ f [] zs = ≡.refl
  map-++ f (x ∷ xs) zs = ≡.cong ((f x) ∷_) (map-++ f xs zs)
```

[Ende der Vorlesung am 20. April 2026]

## Reverse

Welche Eigenschaften sollte reverse erfüllen?

* rev ∘ rev ≐ id
* rev [] ≡ []
* rev (xs ++ ys) ≡ rev ys ++ rev xs

Welche Eigenschaft definiert reverse auf eindeutige Weise?

```
module Reverse {ℓ : Level} (X : Set ℓ) where
  open List-Definition {ℓ} X

  rev' : List → List
  rev' [] = []
  rev' (x ∷ xs) = rev' xs ∷ʳ x

  rev-acc : List → List → List
  rev-acc [] acc = acc
  rev-acc (x ∷ xs) acc = rev-acc xs (x ∷ acc)

  rev : List → List
  rev x = rev-acc x []

  rev[] : rev [] ≡ []
  rev[] = ≡.refl

  -- rev preserves ++ in the first argument:
  rev-acc-++₁ : ∀ xs ys zs → rev-acc (xs ++ ys) zs ≡ rev-acc ys (rev-acc xs zs)
  rev-acc-++₁ [] ys zs = ≡.refl
  rev-acc-++₁ (x ∷ xs) ys zs = rev-acc-++₁ xs ys (x ∷ zs)

  -- rev preserves ++ in the second argument:
  rev-acc-++₂ : ∀ xs ys zs → rev-acc xs ys ++ zs ≡ rev-acc xs (ys ++ zs)
  rev-acc-++₂ [] ys zs = ≡.refl
  rev-acc-++₂ (x ∷ xs) ys zs = rev-acc-++₂ xs (x ∷ ys) zs
    where
      open ≡.≡-Reasoning
      longer-solution = 
        begin
        (rev-acc (x ∷ xs) ys ++ zs) ≡⟨⟩
        rev-acc xs (x ∷ ys) ++ zs ≡⟨ rev-acc-++₂ xs (x ∷ ys) zs ⟩
        rev-acc xs (x ∷ (ys ++ zs)) ≡⟨⟩
        rev-acc (x ∷ xs) (ys ++ zs)
        ∎

  rev-++ : ∀ xs ys → rev (xs ++ ys) ≡ rev ys ++ rev xs
  rev-++ xs ys =
    begin
    rev (xs ++ ys) ≡⟨⟩
    rev-acc (xs ++ ys) [] ≡⟨ rev-acc-++₁ xs ys [] ⟩
    rev-acc ys (rev-acc xs []) ≡⟨⟩
    rev-acc ys (rev xs) ≡⟨⟩
    rev-acc ys ([] ++ rev xs) ≡⟨ rev-acc-++₂ ys [] (rev xs)  ⟨
    -- ... ⟨ <- Klammer andersherum = sym
    (rev-acc ys []) ++ (rev xs) ≡⟨⟩
    (rev ys ++ rev xs)
    ∎
    where
      open ≡.≡-Reasoning


```
[Ende der Vorlesung am 23. April 2026]

```
  open import Relation.Binary.PropositionalEquality using (_≗_)
  ++-antitone : (List → List) → Set ℓ
  ++-antitone f = ∀ x y → f (x ++ y) ≡ f y ++ f x

  _preveres-[-] : (List → List) → Set ℓ
  _preveres-[-] f = ∀ x → f [ x ] ≡ [ x ]

  only-rev++ : ∀ f → f preveres-[-] → ++-antitone f → f ≗ rev
  only-rev++ f _ f-++ [] = ++-injectiveʳ (f []) (begin
    (f [] ++ f []) ≡⟨ f-++ [] [] ⟨
    f ([] ++ []) ≡⟨⟩
    f [] ≡⟨ x++[]≡x ⟨ -- <- Notation für sym
    (f [] ++ [])
    ∎)
    where open ≡.≡-Reasoning
  only-rev++ f f-[-] f-++ (x ∷ xs) =
    begin
    f (x ∷ xs) ≡⟨ f-++ _ _ ⟩
    f xs ++ f [ x ]  ≡⟨ ≡.cong₂ _++_ IH (f-[-] x) ⟩
    rev xs ++ rev [ x ]  ≡⟨ rev-++ [ x ] xs ⟨
    rev (x ∷ xs)
    ∎
    where
      open ≡.≡-Reasoning
      IH = (only-rev++ f f-[-] f-++ xs)

  record _UniquelyDefinedBy_ (r : List → List)
                           (P : (List → List) → Set ℓ)
                           : Set ℓ where
    field
      r-P : P r
      only-r : ∀ f → P f → f ≗ r

  record Spec (r : List → List) : Set ℓ where
    field
      prop-1 : r preveres-[-]
      prop-2 : ++-antitone r

  rev-unique-spec : rev UniquelyDefinedBy Spec
  rev-unique-spec = record
    { r-P = record { prop-1 = λ x → ≡.refl ; prop-2 = rev-++ }
    ; only-r = λ f f-Spec → only-rev++ f
             (Spec.prop-1 f-Spec)
             (f-Spec .Spec.prop-2) -- flipped function application
    }
```

## Dependently-Typed Recursive Data-Types

| Datentypen  | Beispiele          | Beispiele mit Dependent Types |
| ----------- | ------------------ | ----------------------------- |
| Funktionen  | `A → B`            | `∀ (x : A) → B x`             |
| Records     | `_×_`              | `Σ`                           |
| Rec. DT     | `List`             | `_∈_` , `_≤_`                 |

Die Element-Beziehung `_∈_` definieren wir wie folgt:

```
module List-Membership {ℓ} (X : Set ℓ) where
  private
    variable ℓ' : Level

  open import Level using (_⊔_)
  open List-Definition {ℓ} X

  data Any (P : X → Set ℓ') : List → Set (ℓ ⊔ ℓ') where
    here : ∀ {x} {xs} → P x → Any P (x ∷ xs)
    there : ∀ {x} {xs} → Any P xs → Any P (x ∷ xs)

  _∈_ : (x : X) → List → Set ℓ
  x ∈ list = Any (x ≡_) list

  open Reverse {ℓ} X

  rev-P-acc : ∀ {P : X → Set ℓ} xs acc → Any P acc → Any P (rev-acc xs acc)
  rev-P-acc [] acc P-acc = P-acc
  rev-P-acc (x ∷ xs) acc P-acc = rev-P-acc xs (x ∷ acc) (there P-acc)

  rev-P : ∀ {P : X → Set ℓ} xs acc → Any P xs → Any P (rev-acc xs acc)
  rev-P [] _ () -- <- absurd pattern; no constructor of 'Any' possible
  rev-P (x ∷ xs) acc (here P-x) = rev-P-acc xs (x ∷ acc) (here P-x)
  rev-P (x ∷ xs) acc (there any-P-xs) = rev-P xs (x ∷ acc) any-P-xs

  rev-∈ : ∀ x xs → (x ∈ xs) → x ∈ rev xs
  rev-∈ x xs = rev-P {x ≡_} xs []
```
Weiteres Beispiel einer rekursiven Datenstruktur mittels Dependent Types:
```
module ℕ-≤ where

  open import Data.Nat.Base using (ℕ; zero; suc)
  data _≤₁_ : ℕ → ℕ → Set where
    z≤n : ∀ n → zero ≤₁ n
    s≤s : ∀ n m → n ≤₁ m → suc n ≤₁ suc m
    -- intuition: left-aligned length comparison:
    --      s s s z
    --      _≤₁_  
    --      s s s s s s s s z
    --            '-- z≤n --'

  data _≤₂_ : ℕ → ℕ → Set where
    n≤n : ∀ n → n ≤₂ n
    ≤-s : ∀ n m → n ≤₂ m → n ≤₂ suc m
    -- intuition: right-aligned length comparison
    --            s s s s z
    --          _≤₂_
    --      s s s s s s s z
    --            '- n≤n -'
```
[Ende der Vorlesung am 27.04.2026]

## Definitionen in der Agda standard library
```
import Data.List using (List; []; _∷_; _++_; reverse)
import Data.List.Properties using (reverse-++; ++-identityʳ)
import Data.List.Membership.Propositional using (_∈_)
import Data.List.Relation.Unary.Any using (Any; here; there)
import Data.Nat using (_≤_; _≤′_)
```

