Martin Escardo, Paulo Oliva, December 2024, modified from a 2023 file.

A variation of the J monad transformer. Starting with a monad T and an
algebra α : T R → R, we define a new monad JT X := (X → R) → T X.

\begin{code}

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

open import MLTT.Spartan hiding (J)

module Games.J-transf-variation where

open import UF.FunExt
open import Games.Monad

𝕁-transf : Fun-Ext
          (𝓣 : Monad)
           (R : Type)
           (𝓐 : Algebra 𝓣 R)
          Monad
𝕁-transf fe 𝓣 R 𝓐 = monad JT ηᴶᵀ extᴶᵀ extᴶᵀ-η unitᴶᵀ assocᴶᵀ
 where
  open α-definitions 𝓣 R 𝓐
  open T-definitions 𝓣

  JT : Type  Type
  JT X = (X  R)  T X

  ηᴶᵀ : {X : Type}  X  JT X
  ηᴶᵀ = λ x p  ηᵀ x

  extᴶᵀ : {X Y : Type}  (X  JT Y)  JT X  JT Y
  extᴶᵀ f ε p = extᵀ  x  f x p) (ε  x  α-extᵀ p (f x p)))

  extᴶᵀ-η : {X : Type}  extᴶᵀ (ηᴶᵀ {X})  𝑖𝑑 (JT X)
  extᴶᵀ-η ε = dfunext fe  p 
   extᵀ ηᵀ (ε  x  α-extᵀ p (ηᵀ x))) =⟨ extᵀ-η _ 
   ε  x  α-extᵀ p (ηᵀ x))           =⟨ ap ε (dfunext fe (α-extᵀ-unit p)) 
   ε p                                 )

  unitᴶᵀ : {X Y : Type} (f : X  JT Y) (x : X)  extᴶᵀ f (ηᴶᵀ x)  f x
  unitᴶᵀ f x = dfunext fe  p  unit 𝓣  x  f x p) x)

  assocᴶᵀ : {X Y Z : Type} (g : Y  JT Z) (f : X  JT Y) (ε : JT X)
           extᴶᵀ (extᴶᵀ g  f) ε  extᴶᵀ g (extᴶᵀ f ε)
  assocᴶᵀ {X} {Y} {Z} g f ε = dfunext fe γ
   where
    γ : extᴶᵀ (extᴶᵀ g  f) ε  extᴶᵀ g (extᴶᵀ f ε)
    γ p =
     extᴶᵀ (extᴶᵀ g  f) ε p                         =⟨ refl 
     extᵀ (extᵀ 𝕘  𝕗) (ε (α-extᵀ p  extᵀ 𝕘  𝕗))   =⟨ assoc 𝓣 _ _ _ 
     extᵀ 𝕘 (extᵀ 𝕗 (ε (α-extᵀ p  extᵀ 𝕘  𝕗)))     =⟨ by-α-extᵀ-assoc ⁻¹ 
     extᵀ 𝕘 (extᵀ 𝕗 (ε (α-extᵀ (α-extᵀ p  𝕘)  𝕗))) =⟨ refl 
     extᴶᵀ g (extᴶᵀ f ε) p                           
      where
       𝕘 : Y  T Z
       𝕘 = λ y  g y p
       𝕗 : X  T Y
       𝕗 = λ x  f x (α-extᵀ p  𝕘)
       by-α-extᵀ-assoc = ap  -  extᵀ 𝕘 (extᵀ 𝕗 (ε (-  𝕗))))
                            (dfunext fe (α-extᵀ-assoc fe p 𝕘))

𝕁' : Fun-Ext  Type  Monad
𝕁' fe R = 𝕁-transf fe 𝕀𝕕 R 𝓘
 where
  𝓘 = record {
       structure-map = id ;
       aunit         = λ r  refl ;
       aassoc        = λ r  refl}

module JT-definitions
        (𝓣 : Monad)
        (R : Type)
        (𝓐 : Algebra 𝓣 R)
        (fe : Fun-Ext)
       where

 open import Games.K

 open T-definitions 𝓣
 open K-definitions R

 𝕁𝕋 : Monad
 𝕁𝕋 = 𝕁-transf fe 𝓣 R 𝓐

 JT : Type  Type
 JT = functor 𝕁𝕋

 KT : Type  Type
 KT X = (X  T R)  R

 ηᴶᵀ : {X : Type}  X  JT X
 ηᴶᵀ = η 𝕁𝕋

 extᴶᵀ : {X Y : Type}  (X  JT Y)  JT X  JT Y
 extᴶᵀ = ext 𝕁𝕋

 mapᴶᵀ : {X Y : Type}  (X  Y)  JT X  JT Y
 mapᴶᵀ = map 𝕁𝕋

 _⊗ᴶᵀ_ : {X : Type} {Y : X  Type}
        JT X
        ((x : X)  JT (Y x))
        JT (Σ x  X , Y x)
 _⊗ᴶᵀ_ = _⊗_ 𝕁𝕋


 open α-definitions 𝓣 R 𝓐

 module _ {X : Type}
          {Y : X  Type}
          (ε : JT X)
          (δ : (x : X)  JT (Y x))
          (q : (Σ x  X , Y x)  R)
       where

  private
   f : (x : X)  T (Y x)
   f x = δ x  y  α (extᵀ (ηᵀ  q) (ηᵀ (x , y))))

   g : (x : X)  T (Σ x  X , Y x)
   g x = extᵀ  y  ηᵀ (x , y)) (f x)

   h : T X
   h = ε  x  α (extᵀ (ηᵀ  q) (g x)))

  ⊗ᴶᵀ-explicitly : (ε ⊗ᴶᵀ δ) q  extᵀ g h
  ⊗ᴶᵀ-explicitly = refl

  ν : (x : X)  T (Y x)
  ν x = δ x  y  q (x , y))

  τ : T X
  τ = ε  x  α-extᵀ  y  q (x , y)) (ν x))

  module _ (fe : funext₀) where

  private
   lemma-f : funext₀  f  ν
   lemma-f fe x =
    δ x  y  α (extᵀ (ηᵀ  q) (ηᵀ (x , y)))) =⟨ I 
    δ x  y  α (ηᵀ (q (x , y))))             =⟨ II 
    δ x  y  q (x , y))                      
     where
      I = ap  -  δ x  y  α (- y))) (dfunext fe  y  unitᵀ (ηᵀ  q) (x , y)))
      II = ap (δ x) (dfunext fe  y  α-unitᵀ (q (x , y))))

   lemma-g : funext₀  g   x  extᵀ  y  ηᵀ (x , y)) (ν x))
   lemma-g fe x = ap (extᵀ  y  ηᵀ (x , y))) (lemma-f fe x)

   lemma-h : funext₀  h  τ
   lemma-h fe =
    h                                                             =⟨ refl 
    ε  x  α (extᵀ (ηᵀ  q) (g x)))                             =⟨ I 
    ε  x  α (extᵀ (ηᵀ  q) (extᵀ  y  ηᵀ (x , y)) (ν x))))   =⟨ II 
    ε  x  α (extᵀ (extᵀ (ηᵀ  q)   y  ηᵀ (x , y))) (ν x))) =⟨ refl 
    ε  x  α (extᵀ  y  extᵀ (ηᵀ  q) (ηᵀ (x , y))) (ν x)))   =⟨ III 
    ε  x  α (extᵀ  y  ηᵀ (q (x , y))) (ν x)))               =⟨ refl 
    ε  x  α-extᵀ  y  q (x , y)) (ν x))                      =⟨ refl 
    τ 
     where
      I   = ap  -  ε  x  α (extᵀ (ηᵀ  q) (- x))))
               (dfunext fe (lemma-g fe))
      II  = ap  -  ε  x  α (- x)))
               (dfunext fe  x  (assocᵀ (ηᵀ  q)  y  ηᵀ (x , y)) (ν x))⁻¹))
      III = ap  -  ε  x  α (extᵀ  y  - (x , y)) (ν x))))
               (dfunext fe (unitᵀ (ηᵀ  q)))

  ⊗ᴶᵀ-in-terms-of-⊗ᵀ : funext₀  (ε ⊗ᴶᵀ δ) q  τ ⊗ᵀ ν
  ⊗ᴶᵀ-in-terms-of-⊗ᵀ fe =
   (ε ⊗ᴶᵀ δ) q                                  =⟨ ⊗ᴶᵀ-explicitly 
   extᵀ g h                                     =⟨ I 
   extᵀ g τ                                     =⟨ II 
   extᵀ  x  extᵀ  y  ηᵀ (x , y)) (ν x)) τ =⟨ refl 
   τ ⊗ᵀ ν                                       
    where
     I  = ap (extᵀ g) (lemma-h fe)
     II = ap  -  extᵀ - τ) (dfunext fe (lemma-g fe))

\end{code}