Foldable, Monoid and Monad

后端 未结 3 1710
你的背包
你的背包 2020-12-24 06:58

Consider the following signature of foldMap

foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m

This is very

3条回答
  •  滥情空心
    2020-12-24 07:16

    Monoid and Monad

    Wow, this is actually one of the rare times we can use the quote:

    A monad is just a monoid in the category of endofunctors, [...]

    Let's start with a monoid. A monoid in the category Set of sets is a set of elements m with an empty element mempty and an associative function mappend to combine elements such that

    mempty `mappend` x == x -- for any x
    x `mappend` mempty == x -- for any x
    -- and
    a `mappend` (b `mappend` c) == (a `mappend` b) `mappend` c -- for all a, b, c
    

    Note that a monoid is not limited to sets, there also exist monoids in the category Cat of categories (monads) and so on. Basically anytime you have an associative binary operation and an identity for it.

    Now a monad, which is a "monoid in the category of endofunctors" has following properties:

    It's an endofunctor, that means it has type * -> * in the Category Hask of Haskell types.

    Now, to go further you must know a little bit of category theory I will try to explain here: Given two functors F and G, there exists a natural transformation from F to G iff there exists a function α such that every F a can be mapped to a G a. α can be many-to-one, but it has to map every element of F a. Roughly said, a natural transformation is a function between functors.

    Now in category theory, there can be many functors between two categories. Ina simplified view it can be said that we don't even care about which functors map from where to where, we only care about the natural transformations between them.

    Coming back to monad, we can now see that a "monoid in the category of endofunctors" must posess two natural transformations. Let's call our monad endofunctor M:

    A natural transformation from the identity (endo)functor to the monad:

    η :: 1 -> M -- this is return
    

    And a natural transformation from the conposition of two monads and produce a third one:

    μ :: M × M -> M
    

    Since × is the composition of functors, we can (roughly speaking) also write:

    μ :: m a × m a -> m a
    μ :: (m × m) a -> m a
    μ :: m (m a) -> m a -- join in Haskell
    

    Satisfying these laws:

    μ . M μ == μ . μ M
    μ . M η == μ . η M
    

    So, a monad is a special case of a monoid in the category of endofunctors. You can't write a monoid instance for monad in normal Haskell, since Haskell's notion of composition is too weak (I think; This is because functions are restricted to Hask and it's weaker than Cat). See this for more information.

    What about Foldable?

    Now as for Foldable: there exist definitions of folds using a custom binary function to combine the elements. Now you could of course supply any function to combine elements, or you could use an existing concept of combining elements, the monoid. Again, please note that this monoid restricted to the set monoid, not the catorical definition of monoid.

    Since the monoid's mappend is associative, foldl and foldr yield the same result, which is why the folding of monoids can be reduced to fold :: Monoid m, Foldable t => t m -> m. This is an obvious connection between monoid and foldable.

    @danidiaz already pointed out the connection between Applicative, Monoid and Foldable using the Const functor Const a b = Const a, whose applicative instance requires the first parameter of Const to be a monoid (no pure without mempty (disregarding undefined)).

    Comparing monad and foldable is a bit of a stretch in my opinion, since monad is more powerful than foldable in the sense that foldable can only accumulate a list's values according to a mapping function, but the monad bind can structurally alter the context (a -> m b).

提交回复
热议问题