2018-03-12 13:11:31 +00:00
|
|
|
|
{---
|
|
|
|
|
Monads
|
|
|
|
|
|
|
|
|
|
This module presents two formulations of monads:
|
|
|
|
|
|
|
|
|
|
* The standard monoidal presentation
|
|
|
|
|
* Kleisli's presentation
|
|
|
|
|
|
|
|
|
|
The first one defines a monad in terms of an endofunctor and two natural
|
|
|
|
|
transformations. The second defines it in terms of a function on objects and a
|
|
|
|
|
pair of arrows.
|
|
|
|
|
|
|
|
|
|
These two formulations are proven to be equivalent:
|
|
|
|
|
|
|
|
|
|
Monoidal.Monad ≃ Kleisli.Monad
|
|
|
|
|
|
2018-03-12 13:20:49 +00:00
|
|
|
|
The monoidal representation is exposed by default from this module.
|
2018-03-12 13:11:31 +00:00
|
|
|
|
---}
|
|
|
|
|
|
2018-02-24 14:13:25 +00:00
|
|
|
|
{-# OPTIONS --cubical --allow-unsolved-metas #-}
|
2018-02-23 16:33:09 +00:00
|
|
|
|
module Cat.Category.Monad where
|
|
|
|
|
|
2018-02-24 11:52:16 +00:00
|
|
|
|
open import Agda.Primitive
|
|
|
|
|
|
|
|
|
|
open import Data.Product
|
|
|
|
|
|
2018-02-23 16:33:09 +00:00
|
|
|
|
open import Cubical
|
2018-03-07 16:30:09 +00:00
|
|
|
|
open import Cubical.NType.Properties using (lemPropF ; lemSig ; lemSigP)
|
2018-03-06 09:16:42 +00:00
|
|
|
|
open import Cubical.GradLemma using (gradLemma)
|
2018-02-23 16:33:09 +00:00
|
|
|
|
|
2018-03-02 12:31:46 +00:00
|
|
|
|
open import Cat.Category
|
2018-02-24 11:52:16 +00:00
|
|
|
|
open import Cat.Category.Functor as F
|
|
|
|
|
open import Cat.Category.NaturalTransformation
|
2018-03-12 13:20:49 +00:00
|
|
|
|
open import Cat.Category.Monad.Monoidal as Monoidal public
|
|
|
|
|
open import Cat.Category.Monad.Kleisli as Kleisli
|
2018-02-23 16:33:09 +00:00
|
|
|
|
open import Cat.Categories.Fun
|
2018-02-24 11:52:16 +00:00
|
|
|
|
|
2018-02-26 19:23:31 +00:00
|
|
|
|
-- | The monoidal- and kleisli presentation of monads are equivalent.
|
2018-02-24 14:13:25 +00:00
|
|
|
|
module _ {ℓa ℓb : Level} {ℂ : Category ℓa ℓb} where
|
|
|
|
|
private
|
2018-03-05 09:28:16 +00:00
|
|
|
|
module ℂ = Category ℂ
|
|
|
|
|
open ℂ using (Object ; Arrow ; 𝟙 ; _∘_ ; _>>>_)
|
2018-02-24 14:13:25 +00:00
|
|
|
|
module M = Monoidal ℂ
|
2018-03-06 08:55:18 +00:00
|
|
|
|
module K = Kleisli ℂ
|
2018-02-24 14:13:25 +00:00
|
|
|
|
|
|
|
|
|
module _ (m : M.RawMonad) where
|
2018-03-06 08:52:01 +00:00
|
|
|
|
open M.RawMonad m
|
2018-02-24 14:13:25 +00:00
|
|
|
|
|
|
|
|
|
forthRaw : K.RawMonad
|
2018-03-06 09:16:42 +00:00
|
|
|
|
K.RawMonad.omap forthRaw = Romap
|
2018-03-06 08:52:01 +00:00
|
|
|
|
K.RawMonad.pure forthRaw = pureT _
|
|
|
|
|
K.RawMonad.bind forthRaw = bind
|
2018-02-24 14:13:25 +00:00
|
|
|
|
|
|
|
|
|
module _ {raw : M.RawMonad} (m : M.IsMonad raw) where
|
2018-03-01 13:19:46 +00:00
|
|
|
|
private
|
|
|
|
|
module MI = M.IsMonad m
|
2018-02-24 14:13:25 +00:00
|
|
|
|
forthIsMonad : K.IsMonad (forthRaw raw)
|
2018-03-06 08:55:18 +00:00
|
|
|
|
K.IsMonad.isIdentity forthIsMonad = proj₂ MI.isInverse
|
|
|
|
|
K.IsMonad.isNatural forthIsMonad = MI.isNatural
|
|
|
|
|
K.IsMonad.isDistributive forthIsMonad = MI.isDistributive
|
2018-02-24 14:13:25 +00:00
|
|
|
|
|
|
|
|
|
forth : M.Monad → K.Monad
|
2018-03-06 09:16:42 +00:00
|
|
|
|
Kleisli.Monad.raw (forth m) = forthRaw (M.Monad.raw m)
|
2018-02-24 14:13:25 +00:00
|
|
|
|
Kleisli.Monad.isMonad (forth m) = forthIsMonad (M.Monad.isMonad m)
|
|
|
|
|
|
2018-02-25 02:09:25 +00:00
|
|
|
|
module _ (m : K.Monad) where
|
2018-03-06 09:16:42 +00:00
|
|
|
|
open K.Monad m
|
2018-02-25 02:09:25 +00:00
|
|
|
|
|
|
|
|
|
backRaw : M.RawMonad
|
2018-03-06 09:16:42 +00:00
|
|
|
|
M.RawMonad.R backRaw = R
|
|
|
|
|
M.RawMonad.pureNT backRaw = pureNT
|
|
|
|
|
M.RawMonad.joinNT backRaw = joinNT
|
2018-02-25 02:09:25 +00:00
|
|
|
|
|
2018-03-01 13:58:01 +00:00
|
|
|
|
private
|
2018-03-06 09:16:42 +00:00
|
|
|
|
open M.RawMonad backRaw
|
|
|
|
|
module R = Functor (M.RawMonad.R backRaw)
|
2018-03-01 13:58:01 +00:00
|
|
|
|
|
2018-03-01 13:19:46 +00:00
|
|
|
|
backIsMonad : M.IsMonad backRaw
|
2018-03-06 09:16:42 +00:00
|
|
|
|
M.IsMonad.isAssociative backIsMonad {X} = begin
|
2018-03-08 10:03:56 +00:00
|
|
|
|
joinT X ∘ R.fmap (joinT X) ≡⟨⟩
|
2018-03-06 09:16:42 +00:00
|
|
|
|
join ∘ fmap (joinT X) ≡⟨⟩
|
|
|
|
|
join ∘ fmap join ≡⟨ isNaturalForeign ⟩
|
|
|
|
|
join ∘ join ≡⟨⟩
|
2018-03-08 10:03:56 +00:00
|
|
|
|
joinT X ∘ joinT (R.omap X) ∎
|
2018-03-06 09:16:42 +00:00
|
|
|
|
M.IsMonad.isInverse backIsMonad {X} = inv-l , inv-r
|
2018-03-01 13:58:01 +00:00
|
|
|
|
where
|
|
|
|
|
inv-l = begin
|
2018-03-08 10:03:56 +00:00
|
|
|
|
joinT X ∘ pureT (R.omap X) ≡⟨⟩
|
2018-03-06 09:16:42 +00:00
|
|
|
|
join ∘ pure ≡⟨ proj₁ isInverse ⟩
|
|
|
|
|
𝟙 ∎
|
2018-03-01 13:58:01 +00:00
|
|
|
|
inv-r = begin
|
2018-03-08 10:03:56 +00:00
|
|
|
|
joinT X ∘ R.fmap (pureT X) ≡⟨⟩
|
2018-03-06 09:16:42 +00:00
|
|
|
|
join ∘ fmap pure ≡⟨ proj₂ isInverse ⟩
|
|
|
|
|
𝟙 ∎
|
2018-02-25 02:09:25 +00:00
|
|
|
|
|
2018-02-24 18:07:58 +00:00
|
|
|
|
back : K.Monad → M.Monad
|
2018-02-25 02:09:25 +00:00
|
|
|
|
Monoidal.Monad.raw (back m) = backRaw m
|
|
|
|
|
Monoidal.Monad.isMonad (back m) = backIsMonad m
|
|
|
|
|
|
2018-02-25 02:12:23 +00:00
|
|
|
|
module _ (m : K.Monad) where
|
2018-03-06 14:52:22 +00:00
|
|
|
|
private
|
|
|
|
|
open K.Monad m
|
|
|
|
|
bindEq : ∀ {X Y}
|
|
|
|
|
→ K.RawMonad.bind (forthRaw (backRaw m)) {X} {Y}
|
|
|
|
|
≡ K.RawMonad.bind (K.Monad.raw m)
|
|
|
|
|
bindEq {X} {Y} = begin
|
|
|
|
|
K.RawMonad.bind (forthRaw (backRaw m)) ≡⟨⟩
|
|
|
|
|
(λ f → join ∘ fmap f) ≡⟨⟩
|
|
|
|
|
(λ f → bind (f >>> pure) >>> bind 𝟙) ≡⟨ funExt lem ⟩
|
|
|
|
|
(λ f → bind f) ≡⟨⟩
|
|
|
|
|
bind ∎
|
|
|
|
|
where
|
|
|
|
|
lem : (f : Arrow X (omap Y))
|
|
|
|
|
→ bind (f >>> pure) >>> bind 𝟙
|
|
|
|
|
≡ bind f
|
|
|
|
|
lem f = begin
|
|
|
|
|
bind (f >>> pure) >>> bind 𝟙
|
|
|
|
|
≡⟨ isDistributive _ _ ⟩
|
|
|
|
|
bind ((f >>> pure) >>> bind 𝟙)
|
|
|
|
|
≡⟨ cong bind ℂ.isAssociative ⟩
|
|
|
|
|
bind (f >>> (pure >>> bind 𝟙))
|
|
|
|
|
≡⟨ cong (λ φ → bind (f >>> φ)) (isNatural _) ⟩
|
|
|
|
|
bind (f >>> 𝟙)
|
|
|
|
|
≡⟨ cong bind (proj₂ ℂ.isIdentity) ⟩
|
|
|
|
|
bind f ∎
|
2018-03-05 09:28:16 +00:00
|
|
|
|
|
2018-02-25 02:12:23 +00:00
|
|
|
|
forthRawEq : forthRaw (backRaw m) ≡ K.Monad.raw m
|
2018-03-06 09:05:35 +00:00
|
|
|
|
K.RawMonad.omap (forthRawEq _) = omap
|
2018-02-26 18:58:27 +00:00
|
|
|
|
K.RawMonad.pure (forthRawEq _) = pure
|
2018-03-05 09:28:16 +00:00
|
|
|
|
K.RawMonad.bind (forthRawEq i) = bindEq i
|
2018-02-24 18:07:58 +00:00
|
|
|
|
|
|
|
|
|
fortheq : (m : K.Monad) → forth (back m) ≡ m
|
2018-02-25 02:09:25 +00:00
|
|
|
|
fortheq m = K.Monad≡ (forthRawEq m)
|
|
|
|
|
|
2018-02-25 02:12:23 +00:00
|
|
|
|
module _ (m : M.Monad) where
|
2018-03-06 14:52:22 +00:00
|
|
|
|
private
|
|
|
|
|
open M.Monad m
|
|
|
|
|
module KM = K.Monad (forth m)
|
|
|
|
|
module R = Functor R
|
|
|
|
|
omapEq : KM.omap ≡ Romap
|
|
|
|
|
omapEq = refl
|
|
|
|
|
|
|
|
|
|
bindEq : ∀ {X Y} {f : Arrow X (Romap Y)} → KM.bind f ≡ bind f
|
|
|
|
|
bindEq {X} {Y} {f} = begin
|
|
|
|
|
KM.bind f ≡⟨⟩
|
|
|
|
|
joinT Y ∘ Rfmap f ≡⟨⟩
|
|
|
|
|
bind f ∎
|
|
|
|
|
|
|
|
|
|
joinEq : ∀ {X} → KM.join ≡ joinT X
|
|
|
|
|
joinEq {X} = begin
|
|
|
|
|
KM.join ≡⟨⟩
|
|
|
|
|
KM.bind 𝟙 ≡⟨⟩
|
|
|
|
|
bind 𝟙 ≡⟨⟩
|
|
|
|
|
joinT X ∘ Rfmap 𝟙 ≡⟨ cong (λ φ → _ ∘ φ) R.isIdentity ⟩
|
|
|
|
|
joinT X ∘ 𝟙 ≡⟨ proj₁ ℂ.isIdentity ⟩
|
|
|
|
|
joinT X ∎
|
|
|
|
|
|
|
|
|
|
fmapEq : ∀ {A B} → KM.fmap {A} {B} ≡ Rfmap
|
|
|
|
|
fmapEq {A} {B} = funExt (λ f → begin
|
|
|
|
|
KM.fmap f ≡⟨⟩
|
|
|
|
|
KM.bind (f >>> KM.pure) ≡⟨⟩
|
|
|
|
|
bind (f >>> pureT _) ≡⟨⟩
|
|
|
|
|
Rfmap (f >>> pureT B) >>> joinT B ≡⟨⟩
|
|
|
|
|
Rfmap (f >>> pureT B) >>> joinT B ≡⟨ cong (λ φ → φ >>> joinT B) R.isDistributive ⟩
|
|
|
|
|
Rfmap f >>> Rfmap (pureT B) >>> joinT B ≡⟨ ℂ.isAssociative ⟩
|
|
|
|
|
joinT B ∘ Rfmap (pureT B) ∘ Rfmap f ≡⟨ cong (λ φ → φ ∘ Rfmap f) (proj₂ isInverse) ⟩
|
|
|
|
|
𝟙 ∘ Rfmap f ≡⟨ proj₂ ℂ.isIdentity ⟩
|
|
|
|
|
Rfmap f ∎
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
rawEq : Functor.raw KM.R ≡ Functor.raw R
|
2018-03-08 10:03:56 +00:00
|
|
|
|
RawFunctor.omap (rawEq i) = omapEq i
|
|
|
|
|
RawFunctor.fmap (rawEq i) = fmapEq i
|
2018-03-05 16:31:13 +00:00
|
|
|
|
|
2018-03-05 09:28:16 +00:00
|
|
|
|
Req : M.RawMonad.R (backRaw (forth m)) ≡ R
|
2018-03-05 16:10:41 +00:00
|
|
|
|
Req = Functor≡ rawEq
|
2018-03-05 09:28:16 +00:00
|
|
|
|
|
|
|
|
|
open NaturalTransformation ℂ ℂ
|
2018-03-07 14:23:07 +00:00
|
|
|
|
|
|
|
|
|
pureTEq : M.RawMonad.pureT (backRaw (forth m)) ≡ pureT
|
|
|
|
|
pureTEq = funExt (λ X → refl)
|
|
|
|
|
|
|
|
|
|
pureNTEq : (λ i → NaturalTransformation F.identity (Req i))
|
|
|
|
|
[ M.RawMonad.pureNT (backRaw (forth m)) ≡ pureNT ]
|
2018-03-07 16:30:09 +00:00
|
|
|
|
pureNTEq = lemSigP (λ i → propIsNatural F.identity (Req i)) _ _ pureTEq
|
2018-03-07 14:23:07 +00:00
|
|
|
|
|
|
|
|
|
joinTEq : M.RawMonad.joinT (backRaw (forth m)) ≡ joinT
|
|
|
|
|
joinTEq = funExt (λ X → begin
|
|
|
|
|
M.RawMonad.joinT (backRaw (forth m)) X ≡⟨⟩
|
|
|
|
|
KM.join ≡⟨⟩
|
|
|
|
|
joinT X ∘ Rfmap 𝟙 ≡⟨ cong (λ φ → joinT X ∘ φ) R.isIdentity ⟩
|
|
|
|
|
joinT X ∘ 𝟙 ≡⟨ proj₁ ℂ.isIdentity ⟩
|
|
|
|
|
joinT X ∎)
|
|
|
|
|
|
|
|
|
|
joinNTEq : (λ i → NaturalTransformation F[ Req i ∘ Req i ] (Req i))
|
|
|
|
|
[ M.RawMonad.joinNT (backRaw (forth m)) ≡ joinNT ]
|
2018-03-07 16:30:09 +00:00
|
|
|
|
joinNTEq = lemSigP (λ i → propIsNatural F[ Req i ∘ Req i ] (Req i)) _ _ joinTEq
|
2018-03-07 14:23:07 +00:00
|
|
|
|
|
2018-02-25 02:12:23 +00:00
|
|
|
|
backRawEq : backRaw (forth m) ≡ M.Monad.raw m
|
2018-03-06 09:16:42 +00:00
|
|
|
|
M.RawMonad.R (backRawEq i) = Req i
|
2018-03-06 22:18:23 +00:00
|
|
|
|
M.RawMonad.pureNT (backRawEq i) = pureNTEq i
|
2018-03-06 14:55:03 +00:00
|
|
|
|
M.RawMonad.joinNT (backRawEq i) = joinNTEq i
|
2018-02-24 18:07:58 +00:00
|
|
|
|
|
|
|
|
|
backeq : (m : M.Monad) → back (forth m) ≡ m
|
2018-02-25 02:09:25 +00:00
|
|
|
|
backeq m = M.Monad≡ (backRawEq m)
|
2018-02-24 18:07:58 +00:00
|
|
|
|
|
2018-02-24 14:13:25 +00:00
|
|
|
|
eqv : isEquiv M.Monad K.Monad forth
|
2018-02-24 18:07:58 +00:00
|
|
|
|
eqv = gradLemma forth back fortheq backeq
|
2018-02-24 14:13:25 +00:00
|
|
|
|
|
|
|
|
|
Monoidal≃Kleisli : M.Monad ≃ K.Monad
|
|
|
|
|
Monoidal≃Kleisli = forth , eqv
|