Martin Escardo, Paulo Oliva, 2024

Non-empty list monad.

\begin{code}

{-# OPTIONS --safe --without-K #-}

open import MLTT.Spartan hiding (J)

module Games.NonEmptyList where

open import Games.Monad
open import MLTT.List hiding (map)
open import Notation.CanonicalMap
open import UF.Subsingletons

being-non-empty-is-prop : {X : 𝓤 ̇ } (xs : List X)  is-prop (is-non-empty xs)
being-non-empty-is-prop []       = 𝟘-is-prop
being-non-empty-is-prop (x  xs) = 𝟙-is-prop

List⁺ : Type  Type
List⁺ X = Σ xs  List X , is-non-empty xs

module _ {X : Type} where

 head⁺ : List⁺ X  X
 head⁺ ((x  xs) , cons-is-non-empty) = x

 tail⁺ : List⁺ X  List X
 tail⁺ ((x  xs) , cons-is-non-empty) = xs

 cons⁺ : X  List X  List⁺ X
 cons⁺ x xs = (x  xs) , cons-is-non-empty

 underlying-list⁺ : List⁺ X  List X
 underlying-list⁺ = pr₁

 underlying-list⁺-is-non-empty : (xs : List⁺ X)
                                is-non-empty (underlying-list⁺ xs)
 underlying-list⁺-is-non-empty = pr₂

 instance
  canonical-map-List⁺-to-List : Canonical-Map (List⁺ X) (List X)
  ι {{canonical-map-List⁺-to-List}} = underlying-list⁺

 to-List⁺-= : {xs ys : List⁺ X}  ι xs  ι ys  xs  ys
 to-List⁺-= = to-subtype-= being-non-empty-is-prop

List-ext-lemma⁻ : {X Y : Type} (f : X  List⁺ Y) (xs : List X)
                 is-non-empty xs
                 is-non-empty (List-ext (ι  f) xs)
List-ext-lemma⁻ f (x  xs) cons-is-non-empty =
 is-non-empty-++ (ι (f x)) _ (underlying-list⁺-is-non-empty (f x))

𝕃⁺ : Monad
𝕃⁺ = record {
 functor = List⁺ ;
 η       = λ x  (x  []) , cons-is-non-empty ;
 ext     = λ {X} {Y} (f : X  List⁺ Y) (xs : List⁺ X)
             List-ext (ι  f) (ι xs) ,
              List-ext-lemma⁻ f (ι xs) (underlying-list⁺-is-non-empty xs) ;
 ext-η   = λ {X} (xs : List⁺ X)
             to-List⁺-= (concat-singletons (ι xs)) ;
 unit    = λ {X} {Y} (f : X  List⁺ Y) (x : X)
             to-List⁺-= (List-ext-unit (ι  f) x) ;
 assoc   = λ {X} {Y} {Z} (g : Y  List⁺ Z) (f : X  List⁺ Y) (xs : List⁺ X)
             to-List⁺-= (List-ext-assoc (ι  g) (ι  f) (ι xs))
 }

module List⁺-definitions where

 _⊗ᴸ⁺_ : {X : Type} {Y : X  Type}
       List⁺ X
       ((x : X)  List⁺ (Y x))
       List⁺ (Σ x  X , Y x)
 _⊗ᴸ⁺_ = _⊗_ 𝕃⁺

 ηᴸ⁺ : {X : Type}  X  List⁺ X
 ηᴸ⁺ = η 𝕃⁺

 extᴸ⁺ : {X Y : Type}  (X  List⁺ Y)  List⁺ X  List⁺ Y
 extᴸ⁺ = ext 𝕃⁺

 mapᴸ⁺ : {X Y : Type}  (X  Y)  List⁺ X  List⁺ Y
 mapᴸ⁺ = map 𝕃⁺