- Joined
- Sep 11, 2024
Monad is category that combines two other categories
Endofunctors and Monoids.
Monoids are defined as group and natural operation that have neutral element and are associative.
So for example addition (with zero) is monoid. So is multiplication with one.
And so are lists with concat and empty list. As
Functors are defined as mapping between categories that preserve structure.
So probably best example is Optional/Maybe.
As anything that is Maybe X can have applied function that are applicable to X.
For example
And so is true for lists. As you can apply function to each element of lists the same way as you would to them individually.
Endofunctor just category that maps category to itself.
Now Monads combine Monoid and Endofunctor, they need associative operation with neutral element.
What gives us is a way to combine operations using Bind
take Monad a, unwrap it to get a, apply function to a, use monads natural operation to create Monad b.
Easiest way imho is again to look at lists. Let's say we have function
Now if we take list [1,2,3] and do
Because first Monad will take each element of list and apply function to it creating [1,1] [2,2] [3,3] and then will use lists natural operation, which will be concat, to combine them into [1,1,2,2,3,3].
So the difference between between Functor and Monad, is Functor fmap will only operate on inner values, where as Monadic bind will change context as well.
The IO monad encapsulates the context change in World -> World function. So there is no reall run, it's just a way to enforce that World is never copied, and it is used up after next World is created.
Because
So
so if we decompose it:
getLine is gonna take, and return changed world and line
then (>>=) bind operator will pipe world' and line into putStrLn which will take it and change world' creating new world''
and so on.
That's not really rigorous mathematically, but that's how I understand Monads. Feel free to correct.
Endofunctors and Monoids.
Monoids are defined as group and natural operation that have neutral element and are associative.
So for example addition (with zero) is monoid. So is multiplication with one.
And so are lists with concat and empty list. As
[a,b,c] : [] = [a, b, c]
and ([a, b, c] : [d]) : [e] = [a,b,c] : ([d] : [e]) = [a,b,c,d,e]
Functors are defined as mapping between categories that preserve structure.
So probably best example is Optional/Maybe.
As anything that is Maybe X can have applied function that are applicable to X.
For example
Maybe Int + Maybe Int = Maybe Int
(technically you need fmap) etc. And so is true for lists. As you can apply function to each element of lists the same way as you would to them individually.
Endofunctor just category that maps category to itself.
Now Monads combine Monoid and Endofunctor, they need associative operation with neutral element.
What gives us is a way to combine operations using Bind
m a -> (a -> m b) -> m b
which you can read as; take Monad a, unwrap it to get a, apply function to a, use monads natural operation to create Monad b.
Easiest way imho is again to look at lists. Let's say we have function
f a = [a, a]
. It just takes number and returns 2 numbers inside list. Now if we take list [1,2,3] and do
bind f [1,2,3]
we will get [1,1,2,2,3,3]. Why? Because first Monad will take each element of list and apply function to it creating [1,1] [2,2] [3,3] and then will use lists natural operation, which will be concat, to combine them into [1,1,2,2,3,3].
So the difference between between Functor and Monad, is Functor fmap will only operate on inner values, where as Monadic bind will change context as well.
The IO monad encapsulates the context change in World -> World function. So there is no reall run, it's just a way to enforce that World is never copied, and it is used up after next World is created.
Because
IO x = World -> (World, x)
. And natural operation for IO monad will be to take resulting World and put it in new World -> (World, x) function. So
Code:
main = getLine >>= \line ->
putStrLn line
getLine is gonna take, and return changed world and line
world -> (world', line)
then (>>=) bind operator will pipe world' and line into putStrLn which will take it and change world' creating new world''
world' -> (world'', ())
and so on.
That's not really rigorous mathematically, but that's how I understand Monads. Feel free to correct.