246 lines
10 KiB
Plaintext
246 lines
10 KiB
Plaintext
|
|
Episode: 3028
|
||
|
|
Title: HPR3028: Monads and Haskell
|
||
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr3028/hpr3028.mp3
|
||
|
|
Transcribed: 2025-10-24 15:25:17
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
This is Hacker Public Radio Episode 3028 for Wednesday 11 March 2020.
|
||
|
|
Today's show is entitled, Monads and Haskell,
|
||
|
|
and is part of the series, Haskell.
|
||
|
|
It is the first show by new hosts CRVS,
|
||
|
|
and is about 21 minutes long,
|
||
|
|
and carries an explicit flag. The summer is
|
||
|
|
a hopefully not too rambly introduction
|
||
|
|
to functives and monads in and out of Haskell.
|
||
|
|
This episode of HPR is brought to you by
|
||
|
|
An Honesthost.com.
|
||
|
|
Get 15% discount on all shared hosting
|
||
|
|
with the offer code HPR15.
|
||
|
|
That's HPR15.
|
||
|
|
Better web hosting that's honest and fair
|
||
|
|
at An Honesthost.com.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
.
|
||
|
|
that are lists of other types, and this is very simple and very important to
|
||
|
|
understand. Also there is this well-known other monad, which is also a
|
||
|
|
functor, which is the maybe monad. It goes from the category of Haskell types to
|
||
|
|
the category of maybe a type, maybe types. So these are types that can be either
|
||
|
|
nothing or just something. Just something can be really anything, really. But
|
||
|
|
nothing, nothing and just are the keywords that like the type constructors.
|
||
|
|
Nothing is, you can think of it as, it's a nullary type constructor in the sense
|
||
|
|
that it takes nothing, and it is nothing. Just like, think of it as none in Python.
|
||
|
|
And then the just operator takes an object of any type and produces a type of
|
||
|
|
and produces a type of maybe that initial type. Okay. So I already dropped the
|
||
|
|
f word here, the functor, of course. And now what's so formidable about them?
|
||
|
|
Well, nothing really. The funters are just this, you can really think of them as
|
||
|
|
design patterns, where you have, they have these properties that you can map
|
||
|
|
over them. Or the most important part of a functor is that, not sure, you know how
|
||
|
|
to take an object from type a to type f of a, f being your functor. And you
|
||
|
|
also, if you know how to take an element of type a into type V, you also need to
|
||
|
|
know how to take an element of type a to type, type f of a to type f of b. And this
|
||
|
|
is what we mean when we say that, well, funters are the things that you can map
|
||
|
|
over. So just like if you have a list, you can map over the list by substituting
|
||
|
|
each element. You can map f over a list by substituting each element of the list
|
||
|
|
with f applied to that element. Same thing with funters. If you have a now a
|
||
|
|
functor f, you can take an element of type f of a by mapping a function f from a
|
||
|
|
to b into an element of type f of b. And here, basically, you would go from, for
|
||
|
|
example, from a list of integers to lists of strings by, by showing, by doing
|
||
|
|
show on the string. For show is the function that basically takes any object that is
|
||
|
|
showable and makes a string out of it. For example, if I do show three, then I get the
|
||
|
|
string, the string whose only character that only has the character three. Okay. So that
|
||
|
|
is what a functor is. And it's nothing really more. And like this is sort of the, the
|
||
|
|
tau of funters. So what about monads? Well, monads appear in, and this is how I learned
|
||
|
|
about them. It was in while studying category theory. Basically, a monad is a functor from
|
||
|
|
a category to itself. So a Haskell Functor can be a monad that has two things. One, it
|
||
|
|
has what is called a natural transformation from the identity functor to itself, meaning
|
||
|
|
that basically if I have any object, then there is a function, not a functor, a function
|
||
|
|
that maps that object, that type to the type to monad of a. So a function that maps every
|
||
|
|
element of type a to type monad of a. And that is, that an Haskell is called the return
|
||
|
|
functor, the return function, which is pretty different from returning other languages.
|
||
|
|
And finally, you have this product operation. And the product basically says that if I have
|
||
|
|
a monad applied to itself, then I can get the monad applied only once. So I have, I say
|
||
|
|
I have a monad M. So if I have M of M of A, then I have a function that takes M of something
|
||
|
|
of type M of M of A, and I'll put something of type M of A. And it's important that there
|
||
|
|
are functions here. So this is basically what makes it an international transformation,
|
||
|
|
is that there are functions that you don't actually need a functor to go from one category
|
||
|
|
to the other, because you stayed within the same category. Okay. However, this is not the
|
||
|
|
case this seem. And so I wanted to learn about fun about monads in Haskell. And so I tried
|
||
|
|
to apply this intuition. And that just got me more confused. Because when you reply, when
|
||
|
|
you when you define the monad in Haskell, and remember, monad is a type class. So it has
|
||
|
|
it's these interfaces that you need to define. And interfaces are the return function. And
|
||
|
|
this other binary operation that you call bind. And how is bind defined? Well, bind is defined
|
||
|
|
as a function that takes an element of type monad of A and a function that takes a type
|
||
|
|
A and produce a type monad of B. And then producing is a function that produces an element
|
||
|
|
of type monad of B. Okay. So how do you actually get this from this operation that I said
|
||
|
|
that I said before, this function that I said before that takes a type monad of monad
|
||
|
|
of A into type monad of A. Well, it's pretty simple, really, because a monad is a function
|
||
|
|
so you can map over it. So if you have a function, if you have an element of type monad of
|
||
|
|
A and a function that goes from type A to type A monad of B, then you can apply that function
|
||
|
|
on over, you can map that function over the monad of A to get an element of type monad
|
||
|
|
of monad of B. And once you have an element of type monad of monad of B, remember that
|
||
|
|
what defines a monad in terms of category theory at least is this having this aside from
|
||
|
|
the return is having this operation that takes an element of type monad of monad of A to
|
||
|
|
an element of type monad of A. And here I have an element of type monad of monad of B, so
|
||
|
|
I can get an element of type monad of B of B. And this is the absolutely natural way
|
||
|
|
of implementing it. However, in Haskell, you need to do it the other way around. You
|
||
|
|
need to define how you do this operation, a monad of monad of A into monad of A from this
|
||
|
|
bind operation called bind that takes an element of type monad of A, a function of type
|
||
|
|
a to monad of B and produces an element of type monad of B. And so what is so difficult here is
|
||
|
|
that when you look at the types and now you want to figure out how would you create your
|
||
|
|
your product operation. And here is this product because it's quashing two monads in one,
|
||
|
|
two applications of a monad into one. Well, how would you get it out from just the monad of A?
|
||
|
|
Just using the bind because this is what you use to define the monads, so you need to be able
|
||
|
|
to define everything else you could eventually do with a monad from it and return of course.
|
||
|
|
But in this case, we only really need this part. So it's actually exceedingly simple.
|
||
|
|
All you need to do is to pass the is to define the operation. So there's an IEV intuition,
|
||
|
|
which is once we once you see that what the bind operation does is it maps over the monad,
|
||
|
|
maps the function, the second argument over the monad application and then applies this product.
|
||
|
|
You just need the monad application to do nothing and then you will get the product out.
|
||
|
|
So this gives you an IEV idea, which just says, well, bind, apply bind, where the second argument is
|
||
|
|
just the identity. And the identity is of course the function that does nothing. It takes a type A
|
||
|
|
and produces a type A. However, this should not type check because we actually need a function of
|
||
|
|
type mod out of A, mod out of A. We need to give it a function from type A to mod out of B.
|
||
|
|
However, it does work. So it does work. It works and you get what you expect out. If you give it
|
||
|
|
if you give it in the list, a list containing only containing a single list with the one inside
|
||
|
|
and you bind it to the identity ID, you get just the list with the single element that had there
|
||
|
|
that was within the list inside. Or rather, if you do it, if you do a list of lists, what you get
|
||
|
|
is all those lists joined together, which is what gives the operation the name in Haskell
|
||
|
|
join, which can be obtained from data.monad. Okay. So basically, I just wanted to explain
|
||
|
|
why this works. So the naive intuition, the naive, so basically I just wanted to say, well,
|
||
|
|
there's this naive idea. And now I wanted to explain why this would actually work.
|
||
|
|
And the idea is pretty simple, really. So the main hang up is that the identity function goes
|
||
|
|
from type A to type A and not from type A to mod out of B. However, these are, of course,
|
||
|
|
dummy types. A is a dummy type. And if we let A equals to mod out of B,
|
||
|
|
then because we're inputting a mod ad, we're mapping this over something that is of type
|
||
|
|
mod out of mod out of A. We're mapping over the first mod out. We really have a type
|
||
|
|
element or type mod out of A to mod out of A. But if we let C equals to mod out of A,
|
||
|
|
then we now have an element function of type C to mod out of A. So it does in the end type check
|
||
|
|
once we rename that, once we rename the types to give us a function of type A to mod out of B.
|
||
|
|
And so I have like some show notes on a post I wrote on my blog, which I will just add it
|
||
|
|
to the show notes and the link also. And yeah, that's all I had to say for today. And thank you
|
||
|
|
for sticking with me and have a nice evening. Oh yes. And follow me on social media or something.
|
||
|
|
I don't know. You don't need to. No, you don't. Yeah. See you next time. This is CRVS for Hacker
|
||
|
|
Public Radio. Have a nice evening.
|
||
|
|
You've been listening to Hacker Public Radio at HackerPublicRadio.org. We are a community podcast
|
||
|
|
network that releases shows every weekday Monday through Friday. Today's show, like all our shows,
|
||
|
|
was contributed by an HBR listener like yourself. If you ever thought of recording a podcast,
|
||
|
|
then click on our contributing to find out how easy it really is. Hacker Public Radio was found
|
||
|
|
by the digital dog pound and the infonomican computer club and is part of the binary revolution
|
||
|
|
at binrev.com. If you have comments on today's show, please email the host directly, leave a comment
|
||
|
|
on the website or record a follow-up episode yourself. Unless otherwise stated, today's show is
|
||
|
|
released on the Creative Commons Attribution ShareLight 3.0 license.
|