Maybe Monads
The main contribution of this work is in this module: Monads on containers.
While monads on containers aren’t a surprising fact in itself, it is noteworthy to see that they provide us with similar capabilities than monads on types and functions, but in the realm of bidirectional programming.
The first step in defining our maybe monad is to chose the maybe functor for which we are going to carry out the proof. For pedagical purposes, we start with proving that the functor written using data types in idris \defref{prop:maybe-functor-idris} is a monad. Then we will prove that is a monad via the monoid.
Monads are identified by their unit : 1 -> m a and mult : m (m a) -> m a
operation. Here m is Maybe ▷ and 1 is the identity functor on containers
defined as Unit :- Void.
With this knowledge, we build the unit mapping:
unit : (a : Container) -> a =%> Any.Maybe a
unit _ = Just <! (\x, y => y.unwrap)We now need to prove that just is natural, that is, given any other morphism
m : a =%> b, composing unit after m is the same as functorially mapping
m after unit: . Or
graphically, the following diagram commutes:
Programatically it means we need to implement the function:
%unbound_implicits off
MaybeAnyIsNatural : {0 a, b : Container} ->
(m : a =%> b) ->
m |%> unit b <%≡%> unit a |%> mapHom Any.MaybeF a b m
MaybeAnyIsNatural (fwd <! bwd) = MkDepLensEq
(\arg => Refl)
(\arg, wrg => Refl)Thankfully the proofs are quite simple.
Those two functions are enough to define the first part of our monad: the unit natural transformation:
unitNT : Functor.idF Cont =>> Any.MaybeF
unitNT = MkNT
unit
(\_, _, arg => depLensEqToEq (MaybeAnyIsNatural arg))The second part is the multiplication natural transformation, which states that for any monad we have , in our case, this takes the form of a morphism
public export
mult : (x : Container) -> Any.Maybe (Any.Maybe x) =%> Any.Maybe x
mult container = joinMaybe <! anyJoinIt is left to prove that join is natural, we do the same as we did for unit:
JoinIsNatural : {0 a, b : Container} ->
(m : a =%> b) ->
mapHom Any.MaybeF (Any.Maybe a) (Any.Maybe b) (mapHom Any.MaybeF a b m) |%> mult b
<%≡%> mult a |%> mapHom Any.MaybeF a b mWhich is the expected naturality square .
The proof of this square is a bit more involved and is left in appendix.
joinNT : (Any.MaybeF ⨾⨾ Any.MaybeF) =>> Any.MaybeF
joinNT = MkNT
mult
(\a, b, m => depLensEqToEq (joinCommutes a b m))Equipped with those two natural transformation, and the MaybeAny functor, we have proven that our functor is also a monad. We can make sure of that fact by building a value of type Monad \defref{def:monad}
MaybeAnyMonad : Monad Cont Any.MaybeF
MaybeAnyMonad = MkMonad
{ unit = unitNT
, mult = joinNT
, square = \c => depLensEqToEq (monadSquare c)
, identityLeft = \c => depLensEqToEq $ MkDepLensEq (\_ => Refl) (\_, _ => Refl)
, identityRight = \c => depLensEqToEq $ MkDepLensEq
(\case Nothing => Refl
(Just x) => Refl)
(\case Nothing => \x => absurd x
(Just x) => \(Aye y) => Refl)
}
where
monadSquare : (x : Container) ->
(Any.mapMaybe (mult x) |%> mult x)
<%≡%>
(mult (Any.Maybe x) |%> mult x)
monadSquare x = MkDepLensEq
(\case Nothing => Refl
(Just y) => Refl)
(\case Nothing => \y => absurd y
(Just y) => \_ => Refl)Maybe Monad arising from the Maybe Monoid
All this effort can be saved by deriving the monad instance from the monoidal structor of in .
First we build a self-action in from the monoidal structure of .
MaybeMonoidAction : Action Cont Cont SequenceMonoidal
MaybeMonoidAction = monoidalSelfAction SequenceMonoidalThen we turn the action into a lax-action and use that to produce the monad. The monoid object is given by the fact that is a monoid with regards to the monoidal structure in
namespace Any
public export
MaybeMonad : Monad Cont MaybeSeq
MaybeMonad =
MonadFromLaxAction ? ? Cont Cont SequenceMonoidal
(relax MaybeMonoidAction) Cont.MaybeMonoidComposeWe do the same for the All.Maybe monad as the partially
applied functor .
namespace All
MaybeMonad : Monad Cont MaybeAllSeq
MaybeMonad =
MonadFromLaxAction Container Container ContCart Cont
Cart.SequenceMonoidal
ForallLaxAction
Cart.MaybeMonoidCompose