0

A monad, I've been told, is a monoid of X in the category of endofunctors of X, where X is some category.

Maybe is supposedly then a monoid, which means that it is: an object of a category, some operation Maybe x Maybe -> Maybe, and an identity morphism I -> Maybe. Where are they?

What is X in this case? The category of library functions in Haskell?

Also, I don't understand how Maybe even satisfies the Haskell criteria for being a monad which needs a "return" and a "bind". Where are they?

I'm more interested in the internal logic of the concept than its applications.

I found this thread: What is a monad?

It contains:

do
  user <- getUser 17
  addr <- getAddress user
  getStreetName addr

This do-block invokes the bind-function for the Maybe type (since the result of the first expression is a Maybe). The bind-function only executes the following operation if the value is Just value, otherwise it just passes the Nothing along.

"bind" is when

Monad a -> (a -> Monad a) -> Monad b

And it seems like the code above first does getUser 17 that is a Maybe String. So it's Int -> Maybe String. Then it passes the Maybe String to getAdress user which is then a

Maybe String -> Maybe String

it should be

String -> Maybe String

So we have:

Maybe String -> (Maybe String -> Maybe String) -> Maybe String

but if it was a "bind", shouldn't it be this?

Maybe String (M a) -> (String (a) -> Maybe String (M a)) -> Maybe [Something Else] (M b)

But even if that was to make sense, what does that have to do with endofunctors?

4
  • 2
    have you looked at en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe or blog.ploeh.dk/2022/04/25/the-maybe-monad ? Commented Sep 7 at 9:36
  • @mb21 No, I will read it and see if I can glean anything. Commented Sep 7 at 9:38
  • ah, or if you want to get even more into category theory, I can highly recommend Bartosz work, e.g. bartoszmilewski.com/category/monads Commented Sep 7 at 9:39
  • "Then it passes the Maybe String to getAddress user which is then a Maybe String -> Maybe String" is not correct, and may be the core of your confusion. A corrected statement is "Then, depending on whether the Maybe String has a String inside or not, it may or may not pass a String to getAddress user which is then a String -> Maybe String.". Commented Sep 7 at 14:57

2 Answers 2

7

Maybe is supposedly then a monoid, which means that it is: an object of a category, some operation : Maybe x Maybe -> Maybe, and an identity morphism I -> Maybe. Where are they?

One is join and the other is return, both specialised to the Monad Maybe instance. Keep in mind that the tensor product under consideration in the category of endofunctors is composition, which means that join is a natural transformation Maybe `Compose` Maybe ⇒ Maybe (which unfolds to forall a. Maybe (Maybe a) → Maybe a) and return is a natural transformation Identity ⇒ Maybe (which unfolds to forall a. a → Maybe a). Other monoidal structures on [Set, Set] yield different notions of computation.

What is X in this case? The category of library functions in Haskell?

Some would say Hask, the "category of Haskell types and functions", but this is hardly a formal notion and there is a lot of debate about whether this is the right way to think about things. For categorical matters, I recommend thinking of Haskell as an approximation of a total language for reasoning about Set, the category of sets and functions.

And it seems like the code above first does getUser 17 that is a Maybe String. So it's Int -> Maybe String Then it passes the Maybe String to getAdress user

No; while getUser 17 is a Maybe String, this value is do-bound to the variable user, which then has type String. This translation uses the >>= operator (which is another formulation of join) to convert a function String → Maybe String into Maybe String → Maybe String.

Sign up to request clarification or add additional context in comments.

11 Comments

Thank you for these answers! Some things have become more clear, but I have new questions. If return is an identity function, and it is also of the type a -> Maybe a, how can I reconcile this with my understanding of an identity function as a function that for some x maps to x? It seems as though an element a is being mapped to Maybe a, which is a different structure. I understand that it makes sense somehow, but to me it seems like return cannot be an identity function since a != Maybe a. Also, I thought >>= was a representation of M a -> (a -> M a) -> M b, as in 'bind'.
An "identity" (N.B. not "identity function") is something that gets ignored when doing a binary operation. For example, 0 is an identity for + because 0 + x = x and x + 0 = x; or the empty list is an identity for list append because [] ++ xs = xs and xs ++ [] = xs. This is a generalization of the concept of identity function because the identity function does nothing when used in function composition: id ∘ f = f and f ∘ id = f. In the case of categorical monoids, return is the arrow that "does nothing" for join -- specifically, it makes a certain diagram commute.
Is join the same as bind? And equivalent to M (M a) -> M a?
return is not an identity function. Where did you get that idea? join :: M (M a) -> M a and (>>=) :: M a -> (a -> M b) -> M b are interderivable, meaning that you can define one from the other (using fmap and id). This is a nice exercise; try it yourself. If you're familiar with the Yoneda lemma, you can take that as a hint.
I've seen return being referred to as an identity element, probably from the monoid object terminology. That's an overloaded meaning different from the "identity function" as a function a -> a (though these meanings are certainly connected).
It's the identity morphism in the Kleisli category of M.
I mean "a monad is a triple of an M, an identity I -> M and a multiplication M . M -> M" is a sentence that certain people will utter.
|
1

Maybe is a Monad

instance Monad Maybe where
  pure :: a -> Maybe a
  pure = Just

  join :: Maybe (Maybe a) -> Maybe a
  join (Just (Just a)) = Just a
  join _               = Nothing 

and under a different guise, we can think of Monad = MonoidalOf (~>) Identity Compose as a monoid type:

instance MonoidalOf (~>) Identity Compose Maybe where
  unit :: Identity ~> Maybe
  unit (Identity a) = pure @Maybe a

  mult :: Compose Maybe Maybe ~> Maybe
  mult (Compose ass) = join @Maybe ass 

Monoid = MonoidalOf (->) () (,) from base is also a monoid type:

instance Monoid a => MonoidalOf (->) () (,) a where
  unit :: () -> a
  unit () = mempty

  mult :: (a, a) -> a
  mult = uncurry (<>)

Further information:

1 Comment

I like that you took on the monoidal endofunctor angle directly and gave a good reference.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.