Martin Escardo, January 2021.
It is possible to work with lists *defined* from the ingredients of
our Spartan MLTT (see the module Fin.lagda). For the moment we are
Athenian in this respect.
\begin{code}
{-# OPTIONS --safe --without-K --no-exact-split #-}
module MLTT.List where
open import MLTT.Spartan
open import MLTT.Bool
open import Naturals.Properties
open import Naturals.Order hiding (minus)
open import Notation.Order
open import UF.Base
open import UF.Subsingletons
data List {π€} (X : π€ Μ ) : π€ Μ where
 [] : List X
 _β·_ : X β List X β List X
infixr 3 _β·_
{-# BUILTIN LIST List #-}
length : {X : π€ Μ } β List X β β
length []       = 0
length (x β· xs) = succ (length xs)
course-of-values-induction-on-length
 : {X : π€ Μ }
 β (P : List X β π₯ Μ )
 β ((xs : List X) β ((ys : List X) β length ys < length xs β P ys) β P xs)
 β (xs : List X) β P xs
course-of-values-induction-on-length {π€} {π₯} {X} =
 course-of-values-induction-on-value-of-function length
Vector' : π€ Μ β β β π€ Μ
Vector' X n = (Ξ£ xs κ List X , length xs οΌ n)
_β·'_ : {X : π€ Μ } {n : β} β X β Vector' X n β Vector' X (succ n)
x β·' (xs , p) = (x β· xs) , ap succ p
equal-heads : {X : π€ Μ } {x y : X} {s t : List X}
            β x β· s οΌ y β· t
            β x οΌ y
equal-heads refl = refl
equal-tails : {X : π€ Μ } {x y : X} {s t : List X}
            β x β· s οΌ y β· t
            β s οΌ t
equal-tails refl = refl
equal-head-tail : {X : π€ Μ } {x : X} {s t : List X}
                β x β· s οΌ t
                β Ξ£ y κ X , Ξ£ t' κ List X , (t οΌ y β· t')
equal-head-tail {π€} {X} {x} {s} {t} refl = x , s , refl
[_] : {X : π€ Μ } β X β List X
[ x ] = x β· []
[]-is-not-cons : {X : π€ Μ } (x : X) (xs : List X)
               β [] β  x β· xs
[]-is-not-cons x []        ()
[]-is-not-cons x (xβ β· xs) ()
_++_ : {X : π€ Μ } β List X β List X β List X
[]      ++ t = t
(x β· s) ++ t = x β· (s ++ t)
infixr 2 _++_
[]-right-neutral : {X : π€ Μ } (s : List X) β s οΌ s ++ []
[]-right-neutral []      = refl
[]-right-neutral (x β· s) = ap (x β·_) ([]-right-neutral s)
++-assoc : {X : π€ Μ } β associative (_++_ {π€} {X})
++-assoc []      t u = refl
++-assoc (x β· s) t u = ap (x β·_) (++-assoc s t u)
foldr : {X : π€ Μ } {Y : π₯ Μ } β (X β Y β Y) β Y β List X β Y
foldr _Β·_ Ξ΅ []       = Ξ΅
foldr _Β·_ Ξ΅ (x β· xs) = x Β· foldr _Β·_ Ξ΅ xs
map : {X : π€ Μ } {Y : π₯ Μ } β (X β Y) β List X β List Y
map f []       = []
map f (x β· xs) = f x β· map f xs
_<$>_ = map
is-non-empty : {X : π€ Μ } β List X β π€ Μ
is-non-empty []       = π
is-non-empty (x β· xs) = π
pattern cons-is-non-empty = β
list-non-emptiness-is-decidable : {X : π€ Μ }
                                  (xs : List X)
                                β is-decidable (is-non-empty xs)
list-non-emptiness-is-decidable [] = inr π-elim
list-non-emptiness-is-decidable (x β· xs) = inl cons-is-non-empty
map-is-non-empty : {X : π€ Μ } {Y : π₯ Μ } (f : X β Y) (xs : List X)
                 β is-non-empty xs
                 β is-non-empty (map f xs)
map-is-non-empty f (x β· xs) cons-is-non-empty = cons-is-non-empty
[]-is-empty : {X : π€ Μ } β Β¬ is-non-empty ([] {π€} {X})
[]-is-empty = π-elim
is-non-empty-++ : {X : π€ Μ } (xs ys : List X)
                β is-non-empty xs
                β is-non-empty (xs ++ ys)
is-non-empty-++ (x β· xs) ys β = β
empty : {X : π€ Μ } β List X β Bool
empty []       = true
empty (x β· xs) = false
data member {X : π€ Μ } : X β List X β π€ Μ where
 in-head : {x : X}   {xs : List X} β member x (x β· xs)
 in-tail : {x y : X} {xs : List X} β member x xs β member x (y β· xs)
empty-list-has-no-members : {X : π€ Μ }
                            (x : X)
                          β Β¬ member x []
empty-list-has-no-members x ()
lists-with-members-are-non-empty : {X : π€ Μ }
                                   {y : X}
                                   {xs : List X}
                                 β member y xs
                                 β is-non-empty xs
lists-with-members-are-non-empty in-head     = cons-is-non-empty
lists-with-members-are-non-empty (in-tail m) = cons-is-non-empty
member-map : {X : π€ Μ } {Y : π₯ Μ } (f : X β Y) (x : X) (xs : List X)
           β member x xs
           β member (f x) (map f xs)
member-map f x' (_ β· _)  in-head     = in-head
member-map f x' (_ β· xs) (in-tail m) = in-tail (member-map f x' xs m)
private
 filter-helper : {X : π€ Μ } (p : X β π₯ Μ )
               β (x : X)
               β p x + Β¬ p x
               β List X
               β List X
 filter-helper p x (inl _) xs = x β· xs
 filter-helper p x (inr _) xs = xs
filter : {X : π€ Μ } (p : X β π₯ Μ ) β ((x : X) β p x + Β¬ p x) β List X β List X
filter p Ξ΄ []       = []
filter p Ξ΄ (x β· xs) = filter-helper p x (Ξ΄ x) (filter p Ξ΄ xs)
open import MLTT.Plus-Properties
filter-memberβ : {X : π€ Μ }
                 (p : X β π₯ Μ )
                 (Ξ΄ : (x : X) β p x + Β¬ p x)
                 (y : X)
                 (xs : List X)
               β member y (filter p Ξ΄ xs)
               β p y
filter-memberβ {π€} {π₯} {X} p Ξ΄ y (x β· xs) = h x xs (Ξ΄ x)
 where
  h : (x : X)
      (xs : List X)
    β (d : p x + Β¬ p x)
    β member y (filter-helper p x d (filter p Ξ΄ xs))
    β p y
  h x xs        (inl l) in-head     = l
  h x xs        (inl _) (in-tail m) = filter-memberβ p Ξ΄ y xs m
  h x (x' β· xs) (inr _) m           = h x' xs (Ξ΄ x') m
filter-memberβ : {X : π€ Μ }
                 (p : X β π₯ Μ )
                 (Ξ΄ : (x : X) β p x + Β¬ p x)
                 (y : X)
                 (xs : List X)
               β p y
               β member y xs
               β member y (filter p Ξ΄ xs)
filter-memberβ {π€} {π₯} {X} p Ξ΄ y (x β· xs) = h x xs (Ξ΄ x)
 where
  h : (x : X)
      (xs : List X)
    β (d : p x + Β¬ p x)
    β p y
    β member y (x β· xs)
    β member y (filter-helper p x d (filter p Ξ΄ xs))
  h x xs (inl _) py in-head = in-head
  h x (x' β· xs) (inl _) py (in-tail m) = in-tail (h x' xs (Ξ΄ x') py m)
  h x xs (inr r) py in-head = π-elim (r py)
  h x xs (inr _) py (in-tail m) = filter-memberβ p Ξ΄ y xs py m
member' : {X : π€ Μ } β X β List X β π€ Μ
member' y []       = π
member' y (x β· xs) = (x οΌ y) + member' y xs
member'-map : {X : π€ Μ } {Y : π₯ Μ } (f : X β Y) (x : X) (xs : List X)
            β member' x xs
            β member' (f x) (map f xs)
member'-map f x' (x β· xs) (inl p) = inl (ap f p)
member'-map f x' (x β· xs) (inr m) = inr (member'-map f x' xs m)
listed : π€ Μ β π€ Μ
listed X = Ξ£ xs κ List X , ((x : X) β member x xs)
the-list : {X : π€ Μ } β listed X β List X
the-list (xs , m) = xs
member-of-the-list : {X : π€ Μ } (X-is-listed : listed X)
                   β (x : X) β member x (the-list X-is-listed)
member-of-the-list (xs , m) = m
π-is-listed : listed (π {π€})
π-is-listed = (β β· []) , (Ξ» x β in-head)
listedβΊ : π€ Μ β π€ Μ
listedβΊ X = X Γ listed X
distinguished-element : {X : π€ Μ } β listedβΊ X β X
distinguished-element (x , X-listed) = x
listedβΊ-types-are-listed : {X : π€ Μ } β listedβΊ X β listed X
listedβΊ-types-are-listed (x , X-is-listed) = X-is-listed
π-is-listedβΊ : listedβΊ (π {π€})
π-is-listedβΊ = β , π-is-listed
type-from-list : {X : π€ Μ } β List X β π€ Μ
type-from-list {π€} {X} xs = Ξ£ x κ X , member x xs
type-from-list-is-listed : {X : π€ Μ } (xs : List X)
                         β listed (type-from-list xs)
type-from-list-is-listed {π€} {X} [] = [] , g
 where
  g : (Ο : type-from-list []) β member Ο []
  g (x , ())
type-from-list-is-listed {π€} {X} (x β· xs) = g
 where
  h : (x : X) β type-from-list (x β· xs)
  h x = x , in-head
  t : type-from-list xs β type-from-list (x β· xs)
  t (x , m) = x , in-tail m
  Ξ± : List (type-from-list xs) β List (type-from-list (x β· xs))
  Ξ± Οs = h x β· map t Οs
  Ξ² : ((Οs , ΞΌ) : listed (type-from-list xs))
    β (Ο : type-from-list (x β· xs)) β member Ο (Ξ± Οs)
  Ξ² (Οs , ΞΌ) (y , in-head)   = in-head
  Ξ² (Οs , ΞΌ) (y , in-tail m) = in-tail (member-map t (y , m) Οs (ΞΌ (y , m)))
  f : listed (type-from-list xs) β listed (type-from-list (x β· xs))
  f (Οs , ΞΌ) = Ξ± Οs , Ξ² (Οs , ΞΌ)
  g : listed (type-from-list (x β· xs))
  g = f (type-from-list-is-listed xs)
module _ {X : π€ Μ } where
 delete : {n : β}
          {y : X}
          ((xs , _) : Vector' X (succ n))
        β member y xs
        β Vector' X n
 delete {0}      _              in-head     = [] , refl
 delete {0}      _              (in-tail _) = [] , refl
 delete {succ _} ((_ β· xs) , p) in-head     = xs , succ-lc p
 delete {succ n} ((x β· xs) , p) (in-tail m) = x β·' delete {n} (xs , succ-lc p) m
module list-util
        {π€ : Universe}
        {X : π€ Μ }
        {{_ : Eq X}}
       where
 _is-in_ : X β List X β Bool
 x is-in []       = false
 x is-in (y β· ys) = (x == y) || (x is-in ys)
 insert : X β List X β List X
 insert x xs = x β· xs
 _contained-in_ : List X β List X β Bool
 []       contained-in ys = true
 (x β· xs) contained-in ys = (x is-in ys) && (xs contained-in ys)
 contained-lemmaβ : (x z : X) (xs ys : List X)
                  β ys contained-in (x β· xs) οΌ true
                  β ys contained-in (x β· z β· xs) οΌ true
 contained-lemmaβ x z xs []       e = e
 contained-lemmaβ x z xs (y β· ys) e = Ξ³
  where
   IH : ys contained-in (x β· xs) οΌ true β ys contained-in (x β· z β· xs) οΌ true
   IH = contained-lemmaβ x z xs ys
   eβ : (y == x) || (y is-in xs) οΌ true
   eβ = prβ (&&-gives-Γ e)
   eβ : ys contained-in (x β· xs) οΌ true
   eβ = prβ (&&-gives-Γ e)
   a : (y == x) || ((y == z) || (y is-in xs)) οΌ true
   a = Cases (||-gives-+ eβ)
        (Ξ» (e : (y == x) οΌ true)   β ||-left-intro ((y == z) || (y is-in xs)) e)
        (Ξ» (e : y is-in xs οΌ true) β ||-right-intro {y == x} ((y == z) || (y is-in xs)) (||-right-intro (y is-in xs) e))
   b : ys contained-in (x β· z β· xs) οΌ true
   b = IH eβ
   Ξ³ : ((y == x) || ((y == z) || (y is-in xs))) && (ys contained-in (x β· z β· xs)) οΌ true
   Ξ³ = &&-intro a b
 contained-lemmaβ : (x : X) (ys : List X)
                  β ys contained-in (x β· ys) οΌ true
 contained-lemmaβ x []       = refl
 contained-lemmaβ x (y β· ys) = Ξ³
  where
   IH : ys contained-in (x β· ys) οΌ true
   IH = contained-lemmaβ x ys
   a : y == x || (y == y || (y is-in ys)) οΌ true
   a = ||-right-intro {y == x} ((y == y) || (y is-in ys)) (||-left-intro (y is-in ys) (==-refl y))
   b : ys contained-in (x β· y β· ys) οΌ true
   b = contained-lemmaβ x y ys ys IH
   Ξ³ : (y == x || (y == y || (y is-in ys))) && (ys contained-in (x β· y β· ys)) οΌ true
   Ξ³ = &&-intro a b
 some-contained : List (List X) β List X β Bool
 some-contained []         ys = false
 some-contained (xs β· xss) ys = xs contained-in ys || some-contained xss ys
 remove-first : X β List X β List X
 remove-first x []       = []
 remove-first x (y β· ys) = if x == y then ys else (y β· remove-first x ys)
 remove-all : X β List X β List X
 remove-all x []       = []
 remove-all x (y β· ys) = if x == y then remove-all x ys else (y β· remove-all x ys)
 _minus_ : List X β List X β List X
 xs minus []       = xs
 xs minus (y β· ys) = (remove-all y xs) minus ys
\end{code}
Remove first occurrence:
\begin{code}
 remove : X β List X β List X
 remove x []       = []
 remove x (y β· ys) = if x == y then ys else (y β· remove x ys)
 remove-head : (x y : X) (ys : List X)
             β (x == y) οΌ true
             β remove x (y β· ys) οΌ ys
 remove-head x y ys q =
  remove x (y β· ys)                          οΌβ¨ refl β©
  (if x == y then ys else (y β· remove x ys)) οΌβ¨ I β©
  (if true then ys else (y β· remove x ys))   οΌβ¨ refl β©
  ys                                         β
   where
    I = ap (Ξ» - β if - then ys else (y β· remove x ys)) q
 remove-tail : (x y : X) (ys : List X)
             β (x == y) οΌ false
             β remove x (y β· ys) οΌ y β· remove x ys
 remove-tail x y ys q =
  remove x (y β· ys)                        οΌβ¨ refl β©
  if x == y then ys else (y β· remove x ys) οΌβ¨ I β©
  if false then ys else (y β· remove x ys)  οΌβ¨ refl β©
  y β· remove x ys                          β
   where
    I  = ap (Ξ» - β if - then ys else (y β· remove x ys)) q
 remove-length : (x : X) (ys : List X)
               β member x ys
               β (n : β)
               β length ys οΌ succ n
               β length (remove x ys) οΌ n
 remove-length x ys@(z β· zs) m n p = h m n p (x == z) refl
  where
   h : member x ys
     β (n : β)
     β length ys οΌ succ n
     β (b : Bool) β (x == z) οΌ b β length (remove x ys) οΌ n
   h _ n p true q =
    length (remove x (z β· zs)) οΌβ¨ ap length (remove-head x z zs q) β©
    length zs                  οΌβ¨ succ-lc p β©
    n                          β
   h in-head n p false q =
    π-elim (true-is-not-false
             (true    οΌβ¨ (==-refl x)β»ΒΉ β©
             (x == x) οΌβ¨ q β©
             false    β))
   h (in-tail in-head)     0        () false q
   h (in-tail (in-tail m)) 0        () false q
   h (in-tail m)           (succ n) p  false q =
    length (remove x (z β· zs))  οΌβ¨ I β©
    length (z β· remove x zs)    οΌβ¨ refl β©
    succ (length (remove x zs)) οΌβ¨ II β©
    succ n                      β
     where
      I  = ap length (remove-tail x z zs q)
      II = ap succ (remove-length x zs m n (succ-lc p))
 delete' : {n : β}
           (x : X)
           ((xs , _) : Vector' X (succ n))
         β member x xs
         β Vector' X n
 delete' {n} x (xs , p) m = remove x xs , remove-length x xs m n p
\end{code}
Added by Ayberk Tosun on 2023-10-16.
\begin{code}
right-concatenation-preserves-membership : {X : π€ Μ } (x : X) (xs ys : List X)
                                         β member x xs
                                         β member x (xs ++ ys)
right-concatenation-preserves-membership x xs@(xβ² β· _)   ys in-head = in-head
right-concatenation-preserves-membership x xs@(xβ² β· xsβ²) ys (in-tail p) =
 in-tail (right-concatenation-preserves-membership x xsβ² ys p)
left-concatenation-preserves-membership : {X : π€ Μ } (x : X) (xs ys : List X)
                                      β member x xs
                                      β member x (ys ++ xs)
left-concatenation-preserves-membership x xs []       p = p
left-concatenation-preserves-membership x xs (y β· ys) p = β 
 where
  β  : member x (y β· (ys ++ xs))
  β  = in-tail (left-concatenation-preserves-membership x xs ys p)
split-++-membership : {X : π€ Μ } (x : X) (xs ys : List X)
                    β member x (xs ++ ys)
                    β member x xs + member x ys
split-++-membership x []       zs p           = inr p
split-++-membership x (x β· ys) zs in-head     = inl in-head
split-++-membership x (y β· ys) zs (in-tail p) =
 cases β  β‘ (split-++-membership x ys zs p)
 where
  β  : member x ys β member x (y β· ys) + member x zs
  β  p = inl (in-tail p)
  β‘ : member x zs β member x (y β· ys) + member x zs
  β‘ = inr
\end{code}
Added 2nd April 2024 by Martin Escardo and Paulo Oliva. Ingredients
for the list monad.
\begin{code}
map-++ : {X : π€ Μ } {Y : π₯ Μ }
         (f : X β Y)
         (xs ys : List X)
       β map f (xs ++ ys) οΌ map f xs ++ map f ys
map-++ f [] ys       = refl
map-++ f (x β· xs) ys = ap (f x β·_) (map-++ f xs ys)
map-id : {X : π€ Μ }
         (xs : List X)
       β map id xs οΌ xs
map-id [] = refl
map-id (x β· xs) = ap (x β·_) (map-id xs)
map-β : {X : π€ Μ } {Y : π₯ Μ } {Z : π¦ Μ }
        (f : X β Y) (g : Y β Z)
      β map (g β f) βΌ map g β map f
map-β f g []       = refl
map-β f g (x β· xs) = ap (g (f x) β·_) (map-β f g xs)
concat : {X : π€ Μ } β List (List X) β List X
concat []         = []
concat (xs β· xss) = xs ++ concat xss
concat-singletons' : {X : π€ Μ } {Y : π₯ Μ }
                     (g : X β Y)
                     (xs : List X)
                   β concat (map (Ξ» x β [ g x ]) xs) οΌ map g xs
concat-singletons' g []       = refl
concat-singletons' g (x β· xs) = ap (g x β·_) (concat-singletons' g xs)
concat-singletons : {X : π€ Μ }
                    (xs : List X) β concat (map [_] xs) οΌ xs
concat-singletons xs = concat-singletons' id xs β map-id xs
concat-++ : {X : π€ Μ }
            (xss yss : List (List X))
          β concat (xss ++ yss) οΌ concat xss ++ concat yss
concat-++ [] yss = refl
concat-++ (xs β· xss) yss =
 concat (xs β· xss ++ yss)         οΌβ¨ refl β©
 xs ++ concat (xss ++ yss)        οΌβ¨ I β©
 xs ++ (concat xss ++ concat yss) οΌβ¨ II β©
 (xs ++ concat xss) ++ concat yss οΌβ¨ refl β©
 concat (xs β· xss) ++ concat yss  β
  where
   I  = ap (xs ++_) (concat-++ xss yss)
   II = (++-assoc xs (concat xss) (concat yss))β»ΒΉ
\end{code}
The following are the Kleisli extension operations for the list monad
and its associativity law.
\begin{code}
List-ext : {X : π€ Μ } {Y : π₯ Μ }
         β (X β List Y) β (List X β List Y)
List-ext f xs = concat (map f xs)
List-ext-unit : {X : π€ Μ } {Y : π₯ Μ }
                (f : X β List Y) (x : X)
              β f x ++ [] οΌ f x
List-ext-unit f x = ([]-right-neutral (f x))β»ΒΉ
List-ext-assoc
 : {X : π€ Μ } {Y : π₯ Μ } {Z : π¦ Μ }
   (g : Y β List Z) (f : X β List Y)
   (xs : List X)
 β List-ext (Ξ» x β List-ext g (f x)) xs οΌ List-ext g (List-ext f xs)
List-ext-assoc g f []       = refl
List-ext-assoc g f (x β· xs) =
 List-ext (Ξ» - β List-ext g (f -)) (x β· xs)               οΌβ¨ refl β©
 List-ext g (f x) ++ List-ext (Ξ» - β List-ext g (f -)) xs οΌβ¨ I β©
 List-ext g (f x) ++ List-ext g (List-ext f xs)           οΌβ¨ II β©
 concat (map g (f x) ++ map g (List-ext f xs))            οΌβ¨ III β©
 List-ext g (f x ++ List-ext f xs)                        οΌβ¨ refl β©
 List-ext g (List-ext f (x β· xs))                         β
  where
   I   = ap (List-ext g (f x) ++_) (List-ext-assoc g f xs)
   II  = (concat-++ (map g (f x)) (map g (List-ext f xs)))β»ΒΉ
   III = (ap concat (map-++ g (f x) (List-ext f xs)))β»ΒΉ
map' : {X : π€ Μ } {Y : π₯ Μ } β (X β Y) β List X β List Y
map' f = List-ext (Ξ» x β [ f x ])
map-agrees-with-map' : {X : π€ Μ } {Y : π₯ Μ }
                       (f : X β Y)
                     β map f βΌ map' f
map-agrees-with-map' f [] = refl
map-agrees-with-map' f (x β· xs) = ap (f x β·_) (map-agrees-with-map' f xs)
\end{code}
Added by Martin Escardo and Paulo Oliva 12th March 2025.
\begin{code}
member-of-concatβ : {X : π€ Μ } (x : X) (yss : List (List X))
                  β member x (concat yss)
                  β Ξ£ ys κ List X , member ys yss Γ member x ys
member-of-concatβ {π€} {X} x (ys β· yss) m = II I
 where
  I : member x ys + member x (concat yss)
  I = split-++-membership x ys (concat yss) m
  II : type-of I β Ξ£ ys' κ List X , member ys' (ys β· yss) Γ member x ys'
  II (inl l) = ys , in-head , l
  II (inr r) = III IH
   where
    IH : Ξ£ ys' κ List X , member ys' yss Γ member x ys'
    IH = member-of-concatβ x yss r
    III : type-of IH β Ξ£ ys' κ List X , member ys' (ys β· yss) Γ member x ys'
    III (ys' , rβ , rβ) = ys' , in-tail rβ , rβ
member-of-mapβ : {X Y : π€ Μ } (f : X β Y) (y : Y) (xs : List X)
              β member y (map f xs)
              β Ξ£ x κ X , member x xs Γ (f x οΌ y)
member-of-mapβ f y (x β· xs) in-head = x , in-head , refl
member-of-mapβ {π€} {X} f y (x β· xs) (in-tail m) = I IH
 where
  IH : Ξ£ x κ X , member x xs Γ (f x οΌ y)
  IH = member-of-mapβ f y xs m
  I : type-of IH β Ξ£ x' κ X , member x' (x β· xs) Γ (f x' οΌ y)
  I (x , m , e) = x , in-tail m , e
\end{code}
Added 10 April 2025 by Fredrik Nordvall Forsberg.
\begin{code}
data All {X : π€ Μ } (P : X β π₯ Μ ) : List X β π€ β π₯ Μ  where
  [] : All P []
  _β·_ : {x : X} {xs : List X} β P x β All P xs β All P (x β· xs)
All-is-prop : {X : π€ Μ } (P : X β π₯ Μ )
            β is-prop-valued-family P
            β is-prop-valued-family (All P)
All-is-prop P p [] [] [] = refl
All-is-prop P p (x β· l) (a β· as) (a' β· as') =
 apβ _β·_ (p x a a') (All-is-prop P p l as as')
\end{code}
Added by Martin Escardo and Paulo Oliva 14th May 2025.
\begin{code}
member-of-concatβ : {X : π€ Μ } (x : X) (yss : List (List X))
                    (zs : List X)
                  β member zs yss
                  β member x zs
                  β member x (concat yss)
member-of-concatβ x (ys β· yss) .ys in-head mβ =
 right-concatenation-preserves-membership x ys (concat yss) mβ
member-of-concatβ x (ys β· yss) zs (in-tail mβ) mβ =
 left-concatenation-preserves-membership x (concat yss) ys IH
 where
  IH : member x (concat yss)
  IH = member-of-concatβ x yss zs mβ mβ
member-of-mapβ : {X Y : π€ Μ } (f : X β Y) (xs : List X)
                 (x : X)
               β member x xs
               β member (f x) (map f xs)
member-of-mapβ f xs x in-head = in-head
member-of-mapβ f (_ β· xs) x (in-tail m) = in-tail (member-of-mapβ f xs x m)
\end{code}
Added 8-22 October by Martin Escardo and Paulo Oliva.
\begin{code}
conditionally-prepend : {X : π€ Μ } (A : X β π₯ Μ )
                      β (x : X)
                      β A x + Β¬ A x
                      β List (Ξ£ x κ X , A x)
                      β List (Ξ£ x κ X , A x)
conditionally-prepend A x (inl a) ys = (x , a) β· ys
conditionally-prepend A x (inr _) ys = ys
filter' : {X : π€ Μ }
          (A : X β π₯ Μ )
        β ((x : X) β A x + Β¬ A x)
        β List X
        β List (Ξ£ x κ X , A x)
filter' A Ξ΄ []       = []
filter' A Ξ΄ (x β· xs) = conditionally-prepend A x (Ξ΄ x) (filter' A Ξ΄ xs)
filter'-memberβ : {X : π€ Μ }
                  (A : X β π₯ Μ )
                  (Ξ΄ : (x : X) β A x + Β¬ A x)
                  (A-is-prop-valued : (x : X) β is-prop (A x))
                  (y : X)
                  (xs : List X)
                  (a : A y)
                β member y xs
                β member (y , a) (filter' A Ξ΄ xs)
filter'-memberβ {π€} {π₯} {X} A Ξ΄ A-is-prop-valued y (x β· xs) = h x xs (Ξ΄ x)
 where
  h : (x : X)
      (xs : List X)
    β (d : A x + Β¬ A x)
      (a : A y)
    β member y (x β· xs)
    β member (y , a) (conditionally-prepend A x d (filter' A Ξ΄ xs))
  h x xs (inl b) a in-head = II
   where
    I : member (y , a) ((y , a) β· filter' A Ξ΄ xs)
    I = in-head
    II : member (y , a) ((y , b) β· filter' A Ξ΄ xs)
    II = transport
          (Ξ» - β member (y , a) ((y , -) β· filter' A Ξ΄ xs))
          (A-is-prop-valued y a b)
          I
  h x (x' β· xs) (inl b) a (in-tail m) = in-tail (h x' xs (Ξ΄ x') a m)
  h x xs (inr r) a in-head = π-elim (r a)
  h x xs (inr xβ) a (in-tail m) = filter'-memberβ A Ξ΄ A-is-prop-valued y xs a m
detachable-subtype-of-listed-type-is-listed
 : {X : Type}
 β (A : X β Type)
 β ((x : X) β is-decidable (A x))
 β ((x : X) β is-prop (A x))
 β listed X
 β listed (Ξ£ x κ X , A x)
detachable-subtype-of-listed-type-is-listed {X} A Ξ΄ A-is-prop-valued (xs , m)
 = filter' A Ξ΄ xs , Ξ³
 where
  Ξ³ : (Ο : Ξ£ x κ X , A x) β member Ο (filter' A Ξ΄ xs)
  Ξ³ (x , a) = filter'-memberβ A Ξ΄ A-is-prop-valued x xs a (m x)
\end{code}
Added by Martin Escardo and Paulo Oliva 29th October 2025.
Dependent version of `map`.
\begin{code}
dmap : {X : π€ Μ } {Y : X β π₯ Μ } β ((x : X) β Y x) β List X β List (Ξ£ x κ X , Y x)
dmap f []       = []
dmap f (x β· xs) = (x , f x) β· dmap f xs
\end{code}
We now discuss the non-dependent special case of the above.
\begin{code}
module _ {X : π€ Μ } {Y : π₯ Μ } (f : X β Y) where
 prβ-of-dmap : (xs : List X)
             β xs οΌ map prβ (dmap f xs)
 prβ-of-dmap [] = refl
 prβ-of-dmap (x β· xs) = ap (x β·_) (prβ-of-dmap xs)
 map-from-dmap : (xs : List X)
               β map f xs οΌ map prβ (dmap f xs)
 map-from-dmap [] = refl
 map-from-dmap (x β· xs) = ap (f x β·_) (map-from-dmap xs)
\end{code}
In the non-dependent case, we can define dmap from map.
\begin{code}
 dmap-from-map : (xs : List X)
               β dmap f xs οΌ map (Ξ» x β x , f x) xs
 dmap-from-map [] = refl
 dmap-from-map (x β· xs) = ap ((x , f x) β·_) (dmap-from-map xs)
\end{code}