Difference between revisions of "Meet Bob The Monadic Lover"

From HaskellWiki
Jump to navigation Jump to search
(Delete absurd tutorial)
Line 1: Line 1:
==Meet Bob The Monadic Lover==
 
 
'''Note: The source of this page can be used as a Literate Haskell file and can be run with ghci or hugs: so cut paste change and run (in emacs for instance) while reading it...'''
 
 
 
So, this is what I have in mind: suppose we have a friend who does very
 
well with females/males. A lot of dating and so...
 
 
Now, we would like to keep track of all his/her ... ehm, affairs...
 
 
Let's create a type for that: we'll call it "Lover", and a "Lover"
 
will be its constructor.
 
 
There it is:
 
<haskell>
 
 
> newtype Lover a = Lover { loverDiary :: (Name,a) }
 
> deriving (Show)
 
> type Name = String
 
 
</haskell>
 
 
Very very simple: it is a type where we can store the name of our
 
friend's beloveds.
 
 
Suppose our friend is a male. We will call him Bob.
 
 
Ok, we now start playing a bit. But first some useful functions we are
 
going to need:
 
<haskell>
 
 
> createLover name times = Lover (name,times)
 
> startAffairWith name (Lover (names,times)) = Lover (name,0)
 
 
</haskell>
 
 
Indeed we need a way to create a lover, Bob, and start an affair with
 
some beloved.
 
 
Very simple: createLover takes a name of a beloved and the number of
 
... let's call them "dates".
 
 
The other function, startAffairWith, takes the beloved's name and a
 
lover. It will then substitute the lover's past beloved names with the
 
new beloved's one and remove every track of Bob's previous activities.
 
 
Yes, you can say that: she's a very jealous type of a chick and hates
 
Bob's past, as you can imagine... But, let's face it, Bob is not a saint,
 
after all, and I frankly understand her.
 
 
If you want you can visualize "startAffairWith" with the name of the
 
person you are starting a relationship with:
 
 
<haskell>
 
 
> jenny = startAffairWith "Jenny "
 
> luisa = startAffairWith "Luisa "
 
> antonia = startAffairWith "Antonia "
 
 
</haskell>
 
 
As you may see, jenny, luisa and antonia are just partial
 
applications. They need a lover! Well, we know this kind of types,
 
don't we?
 
 
Be honest. With yourself, at least!
 
 
Now we need to create our lover. So, let's do it the right way.
 
 
I'd like to introduce my friend Bob:
 
 
<haskell>
 
 
> bob = createLover "Paula " 5
 
 
</haskell>
 
 
Bob had a previous beloved: Paula. They dated 5 times...
 
 
Easy, isn't it?
 
 
So let's start playing around:
 
 
*Main> bob
 
Lover {loverDiary = ("Paula ",5)}
 
*Main> luisa bob
 
Lover {loverDiary = ("Luisa ",0)}
 
*Main> antonia bob
 
Lover {loverDiary = ("Antonia ",0)}
 
*Main>
 
 
Obviously when you start an affair you do not just meet once, without
 
doing anything... Well, perhaps the first date you'll just be quite,
 
but in the end...
 
 
What I mean is that Bob is quite proud of his past record and would
 
like to see that 5 increased, not erased! I can understand him.
 
 
Instead everytime he starts a new affair with those "always looking
 
for a lover" chicks, well, he has to pretend it is his first time!
 
 
Not what he wants, really.
 
 
Quite human, I'd say. Still, he has to.
 
 
Why don't we just give Bob a new method to ... well, you know...
 
 
<haskell>
 
 
> oneMoreTime (Lover (name,times)) = Lover (name,times + 1)
 
 
</haskell>
 
 
oneMoreTime does what it says, and does it well: adds one more time in
 
Bob's personal diary.
 
 
Let's see:
 
 
*Main> oneMoreTime bob
 
Lover {loverDiary = ("Paula ",6)}
 
*Main> oneMoreTime (antonia bob)
 
Lover {loverDiary = ("Antonia ",1)}
 
*Main>
 
 
 
Fine, it works as expected.
 
 
Now, Bob is, well, that kind of a type that seems not really believe in
 
the "Real Love", if you know what I mean.
 
 
Indeed he needs one more method:
 
 
<haskell>
 
 
> changeBeloved newname (Lover (name,times)) = Lover (name ++ newname,times)
 
 
</haskell>
 
 
changeBeloved is very simple: takes a name of a new beloved and
 
concatenate it with the names stored in Bob's loverDiary. Bob is proud
 
of his diary, and does not pretend to be a freshman every time he
 
starts a new relationship.
 
 
What kind of a type this Bob is!
 
 
Let's test how our Bob is doing. Remember that he started with Paula
 
and 5 times in his record, that is not a bad start compared to mine:
 
 
*Main> oneMoreTime $ oneMoreTime (luisa bob)
 
Lover {loverDiary = ("Luisa ",2)}
 
*Main> oneMoreTime $ oneMoreTime bob
 
Lover {loverDiary = ("Paula ",7)}
 
*Main> oneMoreTime $ oneMoreTime $ oneMoreTime $ oneMoreTime (antonia bob)
 
Lover {loverDiary = ("Antonia ",4)}
 
*Main> oneMoreTime $ oneMoreTime $ oneMoreTime $ changeBeloved "Carla " bob
 
Lover {loverDiary = ("Paula Carla ",8)}
 
*Main>
 
 
Bob's doing quite fine, I'd say, if you like this kind of types.
 
 
Now you can also see Bob's different approaching techniques: "(antonia
 
bob)" will make Bob forget about Paula, while "(changeBeloved "Carla "
 
bob)" will not.
 
 
I'm sure you know what method Bob likes most.
 
 
Bob is that kind of types who just like to increase the number of
 
"pieces" in their collection. Their lovers, indeed, are just "pieces".
 
 
I mean, if I were to be Bob, well, I would agree with him, I must
 
confess. Luckily I'm not Bob and my beloved seems to appreciate this
 
fact, especially when Bob comes over with a couple of those stupid
 
gorgeous looking chicks. She keeps keeping an eye on me. She doesn't
 
trust me and probably thinks that inside myself there must be some
 
kind of a type like the type of Bob.
 
 
Sometimes I even start to believe that she could be right... But now
 
we are talking about Bob, a much more interesting chap than me.
 
 
Anyway we need a new method, for those kind of types like Bob. This
 
method has to chain affairs without letting those ladies erase our
 
memory! It's just a matter of "lover's self-determination"!
 
 
I hate writing these things, but... let's face reality!
 
 
So, there's the (typically masculine) method:
 
 
<haskell>
 
 
> chainAffairs (Lover (names,oldtimes)) (Lover (newlady,newtimes)) = Lover (newlady++names,newtimes+oldtimes)
 
 
</haskell>
 
 
This method is very simple: it takes two love affairs, the old one and
 
the new one, and chains them together: the new lady (++) with the old
 
ones, and newtimes + oldtimes!
 
 
That's all Bob wants! And needs!
 
 
Let's see if it works:
 
 
*Main> chainAffairs (oneMoreTime $ oneMoreTime (antonia bob)) ( oneMoreTime $ changeBeloved "Carla " bob)
 
Lover {loverDiary = ("Antonia Paula Carla ",8)}
 
 
Remember where Bob was starting from:
 
 
*Main> bob
 
Lover {loverDiary = ("Paula ",5)}
 
*Main>
 
 
Now, this is fine, sure. It fits Bob's needs. Still we would like to
 
have some way of counting how many times an affairs resulted in a ...
 
well, I'm sure you know what I mean, without having to write
 
"oneMoreTime" so many times. This is especially true with a kind of a
 
type like our Bob, whose activity can be quite difficult to track.
 
 
I'd like to take a quite general solution here, because our Bob is
 
quite a lazy guy and sometimes, often, he forgets to update his diary,
 
especially those nights he drunk too much. He is not a heavy drinker,
 
far from it, but sometimes...
 
 
So we would like to be able to write that the number of times ...
 
doubled. Hard to believe, but you never know with types like Bob:
 
 
<haskell>
 
 
> times f (Lover (name,times)) = Lover (name, f times)
 
 
</haskell>
 
 
Let's see how this function works:
 
 
*Main> chainAffairs (times (+3) (antonia bob)) (times (*2) $ changeBeloved "Carla " bob)
 
Lover {loverDiary = ("Paula Carla Antonia ",13)}
 
*Main>
 
 
So: Bob started at 5 with Paula, doubled it when changed Paula for
 
Carla (let me tell you: a good change!). Then he met Antonia, (the
 
real love?) and told her he never did anything bad in his past (I was
 
there and could not refrain from laughing). With Antonia he did it 3
 
times. Or so he pretends. But I know Antonia and this is probably
 
true. Anyway, never trust what Bob says, ever!
 
 
Remember: when an affair is started by a beloved, like "(antonia bob)",
 
we can only use "+", since Antonia pretends Bob to be a freshman!
 
 
*Main> chainAffairs (times (+3) (antonia bob)) (times (*2) (luisa bob))
 
Lover {loverDiary = ("Luisa Antonia ",3)}
 
*Main>
 
 
instead:
 
 
*Main> chainAffairs (times (+3) (antonia bob)) (times (+2) (luisa bob))
 
Lover {loverDiary = ("Luisa Antonia ",5)}
 
*Main>
 
 
I'll ask it again: what kind of a type is this Bob??? A
 
sexual-intercourse calculating machine!
 
 
There's a name for males who just collect ... well ... females: we
 
call them Macho Men!
 
 
Like Bob they just chain love affairs, doing just pure calculations:
 
 
<haskell>
 
 
> class Macho f where
 
> chain :: (Num a) => f a -> f a -> f a
 
 
</haskell>
 
 
It is plain obvious that a lover of the kind of Bob must be an
 
instance of this class:
 
 
<haskell>
 
 
> instance Macho Lover where
 
> chain mychicks = chainAffairs mychicks
 
 
</haskell>
 
 
Do you really need some evidences??
 
 
There you are:
 
 
*Main> chain (times (+3) (antonia bob)) (chain (times (*2) (changeBeloved "Carla " bob)) (times (+2) (luisa bob)))
 
Lover {loverDiary = ("Antonia Paula Carla Luisa ",15)}
 
*Main>
 
 
Look at the way Bob performs his calculations. He is basically mapping
 
his diary with some function. And indeed this is what "times" is
 
supposed to do.
 
 
"times" is just a "map" for Bob's loverDiary.
 
 
In Haskell we have a class for this kind of types. I mean, those types
 
who map objects that can be mapped over as Bob's loverDiary can.
 
 
I think the name of their class is quite appropriate: they are called
 
Functors. Pure calculating machine, without any soul left.
 
 
Bob must be an instance of this class, you can be sure of that:
 
 
<haskell>
 
 
> instance Functor Lover where
 
> fmap f = times f
 
 
</haskell>
 
 
Do you still want some evidence?
 
 
*Main> chain (fmap (+3) (antonia bob)) (chain (fmap (*2) (changeBeloved "Carla " bob)) (fmap (+2) (luisa bob)))
 
Lover {loverDiary = ("Antonia Paula Carla Luisa ",15)}
 
*Main>
 
 
Well, is Bob just that? I mean, I know him and he can be the worst
 
kind of a type, I'm totally aware of that. No doubt. But, you know,
 
there are times when Bob and I hang together, and with me he's not
 
just telling bull... you got it.
 
 
Sometimes I find him alone in his huge, empty apartment down town,
 
staring at the full moon and almost crying in despair... Sometimes he
 
opens up with me, and starts telling me whom he really loved. You
 
won't believe it, I'm sure, but once he said that Paula didn't count
 
anything in his life. I've said it all!
 
 
Now, I'm sure that when he's alone, Bob talks with himself about
 
himself. He's not just a Macho Functor who sums up story after story
 
as a calculating machine. He judges his love, I doesn't say "I
 
changed my beloved" or stuff like that. I'm sure he's able to love.
 
Sometimes.
 
 
I'd like to be there when Bob talks with his soul. I'd like to hear
 
the soul asking Bob about his lovers. And I'd like to see if in these
 
occasions Bob uses the same methods, with himself.
 
 
I'm sure you know what I mean. You too have a soul you talk with. And
 
you know that your soul knows it all. You don't need to talk with her
 
as you would with me. She knows part of your answers, because you two
 
guys, whether you want it or not, share the same past, the same
 
memories. This is you, after all. And you know better then I do. Am I
 
right?
 
 
I don't want to start doing philosophy. This is not the place. But you
 
must agree that it would be unjust to believe that Bob is just a Macho
 
Functor. You must concede that Bob is something more. He is a soul
 
talking with Bob's self... Call it ego, call it psyche, call it as you
 
want, but you perfectly know what we are talking about. Do not
 
lie to yourself!
 
 
Ahh, who was that philosopher that said that lying to others is the
 
exception. The rule is lying to ourselves. Friedrich what? I don't
 
remember anymore...
 
 
Ok, let's stop with all this bull... ops, I start talking like Bob!
 
 
Let's go on and see how we can express this human behavior that Bob
 
seems to have, sometimes.
 
 
We said that the soul asks Bob, but that the soul knows part of the
 
answer. So the answer must imply something the soul knows. In other
 
word, the answer must be some kind of partial application, right?
 
 
So let's write this first:
 
 
<haskell>
 
 
> tellLover newtimes oldtimes = Lover ("", newtimes+oldtimes)
 
 
</haskell>
 
 
And now the question:
 
 
<haskell>
 
 
> askLover lover answer = Lover (oldnames ++ newname,newtimes)
 
> where (oldnames,oldtimes) = loverDiary lover
 
> (newname,newtimes) = loverDiary (answer oldtimes)
 
 
</haskell>
 
 
This seems to be just fine to me. "askLover" takes a partial answer
 
and fills it with the missing part (oldtimes) in the where clause: the
 
soul's memory, extracted from the loverDiary of the lover, memory that
 
Bob and his soul share, is added to the partial answer.
 
 
But, we said, this is just what we see. When Bob's soul is alone
 
with herself, I mean, inside Bob, who is probably sitting somewhere
 
all stoned and drunk, this soul needs some methods to talk to herself
 
about new loves and new times.
 
 
So, let's write these soul's methods:
 
 
<haskell>
 
 
> tellMyself newtimes = Lover ("", newtimes)
 
> newLove love = Lover (love,0)
 
 
 
</haskell>
 
 
To me that seems to be enough. Well, just give it a try:
 
 
*Main> askLover (tellMyself 10) (tellLover 1)
 
Lover {loverDiary = ("",11)}
 
 
Well, this for sure is not Bob! Look at this poor soul of a type. 11
 
dates and no names. Sounds suspicious to me... This guy, all alone,
 
doing what??
 
 
I'd have a name for such a "spirit"! Remember that German philosopher
 
who was talking of this stuff all alone, the essence... I don't
 
remember his name but if you look up at the
 
[http://en.wikipedia.org/wiki/Leibniz#The_Monads Wikipedia] something
 
could come up.
 
 
Let's try again:
 
 
*Main> askLover (newLove "Lory ") (tellLover 1)
 
Lover {loverDiary = ("Lory ",1)}
 
 
Well this is not Bob. I don't know him personally. But he doesn't seem
 
such an interesting guy, judging from numbers (you know, the macho
 
functor stuff).
 
 
So here's Bob:
 
 
*Main> chain (bob) (chain (askLover (newLove "Cris ") (tellLover 2)) (askLover (antonia bob) (tellLover 4)))
 
Lover {loverDiary = ("Paula Cris Antonia ",11)}
 
*Main> askLover bob (tellLover 10)
 
Lover {loverDiary = ("Paula ",15)}
 
*Main>
 
 
Now I recognize him. The old dear Bob. What a type.
 
 
Be careful, with this stuff, though. Do not pretend it being the truth
 
about Bob. When Bob tells something aloud to his soul you never know
 
what he's talking about. Truth is not what Bob likes most.
 
 
You sure know that by now!
 
 
Just to show, this is Bob a couple of weeks ago. We went over to one
 
of his friends, and he started, as usual, talking about what kind of a
 
type of a lover he is, showing off names I would not dare to write
 
here.
 
 
Just a couple of examples:
 
 
*Main> fmap (*3) chain bob (askLover (changeBeloved "Jennyfer L. " (changeBeloved "Berta " (changeBeloved "Claudia " (antonia bob)))) (tellLover 10))
 
Lover {loverDiary = ("Paula Antonia Claudia Berta Jennyfer L. ",45)}
 
*Main> fmap (*3) $ askLover (changeBeloved "Jennyfer L. " (changeBeloved "Berta " (changeBeloved "Claudia " (antonia bob)))) (tellLover 10)
 
Lover {loverDiary = ("Antonia Claudia Berta Jennyfer L. ",30)}
 
*Main> chain bob $ fmap (*5) (askLover (changeBeloved "Jennyfer L. " (changeBeloved "Berta " (changeBeloved "Claudia " (antonia bob)))) (tellLover 10))
 
Lover {loverDiary = ("Paula Antonia Claudia Berta Jennyfer L. ",55)}
 
*Main>
 
 
Would you believe it? Certainly I don't.
 
 
Why? Because I happen to know Bob better then you!
 
 
Well, all this soul stuff looks interesting. We could have some fun
 
with it.
 
 
For sure now we can build female lovers who are not just ... partial
 
applications.
 
 
Introducing Alessia:
 
 
*Main> let alessia = askLover (newLove "Joseph ") (tellLover 4)
 
*Main> alessia
 
Lover {loverDiary = ("Joseph ",4)}
 
*Main>
 
 
And what about the bird of a new soul without any memory and
 
experience.
 
 
Sorry, but I find English not expressive enough for what I mean. Well,
 
I'll admit that it could be just me. But how do you guys say when
 
someone is going to, you know, be born? As far as my English goes
 
"born" is the past participle of "bear". This is fine, but I believe
 
it's just the woman's perspective. She bears what is going to be born.
 
 
Ok, let's start from a pregnant woman. I must confess I do not have
 
very much experience in this field, but I would probably express
 
pregnancy this way:
 
 
*Main> askLover (askLover (newLove "Bob ") (tellLover 0)) (tellLover 1)
 
Lover {loverDiary = ("Bob ",1)}
 
*Main>
 
 
I don't know if it does make sense. But for sure pregnancy doesn't
 
make any sense to Bob. So, possibly, this is the right way to express
 
it. At least when talking about Bob.
 
 
But I need a name for this method: the act of the birth. We need a
 
future participle, this is what we really need. You know, something
 
like the Latin "naturum" (is to be born), the Greek physis, the
 
Italian nascita or natura.
 
 
Yes, something like "nature" seems to be appropriate. But, just to
 
keep it apart from the "real nature" (if such a thing exists), like
 
wildness and stuff like that (Bob lives down town and hates everything
 
that even seems "natural"), we will use the Greek term physis.
 
 
Also as an homage to that Greek philosopher, [http://en.wikipedia.org/wiki/Heraclitus Eraclo, Heracloto], I don't
 
remember, that used to say: "Physis kryptestai phylein" (nature loves
 
to hide herself).
 
 
<haskell>
 
 
> physis = Lover ([],0)
 
 
</haskell>
 
 
Let's try it:
 
 
*Main> let andrea = physis
 
*Main> andrea
 
Lover {loverDiary = ("",0)}
 
*Main>
 
 
Ok, seems to be working. And also the name seems appropriate. Before
 
his birth, he was not. During the evaluation of his "going to be born"
 
he became a "definitely born".
 
 
And how a Lover dies? This is simple:
 
 
<haskell>
 
 
> dies lover = Lover ([],0)
 
 
</haskell>
 
 
*Main> let alessia = askLover (newLove "Joseph ") (tellLover 4)
 
*Main> alessia
 
Lover {loverDiary = ("Joseph ",4)}
 
*Main> dies alessia
 
Lover {loverDiary = ("",0)}
 
*Main>
 
 
Seems to work to me.
 
 
I know what you are going to say now. How can you tell who's just born
 
from who's just died?
 
 
Be careful with this kind of arguments with me. I can be even more
 
demanding. For instance, look at this guy:
 
 
*Main> askLover (tellMyself 0) (tellLover 0)
 
Lover {loverDiary = ("",0)}
 
*Main>
 
 
Can you tell me whether he is alive or dead?
 
 
If you cannot, you'd better start asking yourself a few questions.
 
 
If you can, I'm sure you are going to come up with something funny,
 
like "This guy gotta be a priest!".
 
 
Anyway is far from being a lover, and a kind of a type like Bob would
 
not spend a single second the have a conversation with him.
 
 
From our perspective, though, there are no differences at all. But
 
for a Macho Functor Lover, well, being dead turns out to be a huge
 
loss. Take it for granted!
 
 
I like playing this game, Haskell let us create quite interesting kinds
 
of types. I was thinking, do you remember that guy in that movie?
 
 
How was titled? [http://www.imdb.com/title/tt0209144/ Memento] I think.
 
 
This Leonard kind of a type, who, when falls asleep, looses all his
 
short term memory... I'd like to introduce this kind of type.
 
 
I think this is going to be an easy type:
 
 
<haskell>
 
 
> newtype Leonard a = Leonard { leonardDiary :: (Name,a) }
 
> deriving (Show)
 
 
> askLeonard lover answer = Leonard (oldnames,oldtimes)
 
> where (oldnames,oldtimes) = leonardDiary lover
 
> (newname,newtimes) = leonardDiary (answer oldtimes)
 
 
> leonard = Leonard ("Jorja Fox", 1000)
 
 
> tellLeonard newtimes oldtimes = Leonard ("", newtimes+oldtimes)
 
> tellLeonardSelf newtimes = Leonard ("", newtimes)
 
> newLeonardLove love = Leonard (love,0)
 
 
</haskell>
 
 
I believe this is him. Well, just try:
 
 
*Main> askLeonard (leonard) (tellLeonard 100000000)
 
Leonard {leonardDiary = ("Jorja Fox",1000)}
 
*Main>
 
 
Seems to be Leonard to me. Definitely.
 
 
What do you think, could this kind of a type be a Macho? I believe he can:
 
 
<haskell>
 
 
> instance Macho Leonard where
 
> chain (Leonard (a,b)) (Leonard (c,d)) = (Leonard (a,b))
 
 
</haskell>
 
 
Sure he can. Look here:
 
 
*Main> chain leonard (askLeonard (newLeonardLove "Angolie ") (tellLeonard 3))
 
Leonard {leonardDiary = ("Jorja Fox",1000)}
 
*Main>
 
 
This is definitely the Leonard type.
 
 
Now I'm asking to myself if Leonard can also be considered a Functor.
 
 
Yes, I do believe he can:
 
 
<haskell>
 
 
> instance Functor Leonard where
 
> fmap f (Leonard (a,b)) = Leonard (a,f b)
 
 
</haskell>
 
 
Try him:
 
 
*Main> fmap (+6) (chain leonard (askLeonard (newLeonardLove "Angolie ") (tellLeonard 3)))
 
Leonard {leonardDiary = ("Jorja Fox",1006)}
 
*Main>
 
 
A bit strange, isn't it? Seems like Leonard was thinking to do it with
 
Jorja... Well, perhaps this is because he's awake. Just wait for him
 
to go to sleep and check again when he wakes up. Otherwise, well, my fault!
 
 
Ohh gosh! I'm sure now you are starting to believe I'm going to build up a
 
[http://www.imdb.com/title/tt0133093/ Matrix]!
 
 
No, I'm not. We'd better go back to our [http://www.imdb.com/title/tt0120601/ Being John Malchowich]
 
style. Right?
 
 
Now we can say that Bob, after all, seems to have a soul. Great! The
 
problem, now, is to find a suitable Haskell class for this kind of
 
Lovers, who are not just Macho Functors.
 
 
It seems that Haskell developers were quite aware that this need could
 
show up, and they created that class called Monad class.
 
 
I must tell you the truth: I don't know if I like that name. Anyway,
 
sometimes I think it sounds good. In Italian "monade" sounds a bit
 
like "modo", "mode" "modality", you know, that kind of sound. Sure I
 
was told it comes from Greek and all that. But a name is first a
 
sound. Only secondly a meaning. And what Monad means, well, we know:
 
it's a kind of a type like our Bob. Seems just a Macho Functor, but
 
has an inside ... side. This doing questions and doing answering going
 
on.
 
 
So I could say I like the "monad" name, because its sound makes me
 
remember the it could mean "a way of doing something". And I believe
 
that we are, after all, just the way we do...
 
 
I like this "do" word too. In Italian we don't have something you can
 
put everywhere and it always seems to fit in. It doesn't matter if it
 
really doesn't. It seems it does.
 
 
So, when I think of a kind of a type like a "monad" I always start
 
thinking about ways of doing something, you know, all the questioning
 
and answering, and telling oneself, and so on.
 
 
I believe that the Haskell developers had similar feelings, as it
 
will turn out.
 
 
By the way, first let's check if Bob can really be expressed by the
 
monad class.
 
 
I mean, is this true?
 
 
<haskell>
 
 
> instance Monad Lover where
 
> return a = tellMyself a
 
> m >>= f = askLover m f
 
 
</haskell>
 
 
Well, let's check it. Want to see a drunk Bob?
 
 
<haskell>
 
 
> drunk bob = do newLove "Paula "
 
> paula <- tellMyself 5
 
> newLove "Jennifer L. "
 
> jennyfer <- tellMyself 10
 
> newLove "Britney S. "
 
> brit <- tellMyself 20
 
> newLove "Alex "
 
> alex <- tellMyself 15
 
> tellMyself (jennyfer * brit * alex)
 
 
</haskell>
 
 
Let's try:
 
 
*Main> drunk bob
 
Lover {loverDiary = ("Paula Jennifer L. Britney S. Alex ",3000)}
 
*Main>
 
 
This is definitely the drunk Bob I know.
 
 
So it's true, Haskell provides us with a way of describing the inside
 
side of a soul. All this "do" thing we have just seen.
 
 
Did you see? No more "askingLover" and "tellingLover", just soul's methods
 
such as "tellMyself" and "newLove".
 
 
This is because within that "do-notation" stuff, we are inside our
 
Lover. You can see each line as a soul's answer to an implied soul's
 
question. I told you before, this is Bob's soul talking to herself,
 
without outside-Bob's intervention.
 
 
This is all we have to say about a monad in Haskell: it is just the
 
class of types that happen to have a soul. Or, put it differently,
 
it's the class of types that can be described in terms of their
 
internal side, their doing something to themselves.
 
 
Who can be a member of such an exclusive class? Sure Bob the Macho
 
Functor Lover can. He has a soul, after all.
 
 
So we have some kind of a rule: if you have a soul you are allowed to
 
be a member of this exclusive class of types. If you don't, well, you
 
can be a Macho Functor and nothing more.
 
 
Just to make this point clear, take that nice kind of a type we called
 
the Leonard type. I like him, I must tell you the truth.
 
 
Still, does he have such a soul that will allow him to be a member of
 
our exclusive club, the Monadic class of types?
 
 
Go try yourself:
 
 
<haskell>
 
instance Monad Leonard where
 
return a = tellLeonardSelf a
 
m >>= f = askLeonard m f
 
</haskell>
 
 
If this is true, then Leonard has a soul that fits Haskell definition
 
of a soul. Otherwise...
 
 
Ok, I'm going to tell you anyway: the answer is NO! There must be some
 
kind of regulation, some kind of Law that states that Leonard is unfit
 
for that exclusive club.
 
 
Why? I don't know.
 
 
There must be some kind of a [http://www.mala.bc.ca/~johnstoi/kafka/beforethelaw.htm gatekeeper kind of a type sitting before this Law],
 
and we are not allowed to get in.
 
 
What I'd like to point out is that, deciding whether the poor soul we
 
called Leonard has a soul left or not, is a moral decision, not just a
 
technical one. I'm not sure, but as far as I understand it, this is
 
the central question in the [http://www.imdb.com/title/tt0209144/ movie]
 
where our Leonard does what he does.
 
 
That is to say, if you really believe you are free and you possess
 
self determination (by the way, I do not), you should start asking
 
yourself some questions about Leonard status in Haskell. I'm saying
 
that just to warn you. This decision has been already taken. I'll add,
 
taken away from you.
 
 
Some Haskell guru took that decision for you, and that is it. Period.
 
 
You know, those haskell gurus believe to belong to a superior kind of
 
types. Since they have the power to create souls out of thin air, they
 
came to believe they are some kind of a type of a god.
 
 
Definitely not just monads, as we poor souls are.
 
 
Don't say I didn't tell you: when you start using haskell for your
 
description of the world, keep in mind that in the world you are going
 
to describe types like Leonard are not souls, but just malfunctioning
 
Functors!
 
 
Let's go back to Bob. I promised I would introduce Bob to you, and I
 
think I did it. Still, you could be unsatisfied with my introduction.
 
I said a lot about the outside Bob, and very little about his inside
 
side. I just show you a drunk Bob, not the real Bob's soul.
 
 
You know, the problem is that I can describe only what I know. Pretty
 
obvious.
 
 
What I really wanted to do here, it's just to show you that we could
 
describe Bob's inside if we had enough information.
 
 
And you do not have such information, because you don't know Bob.
 
 
But you know that I do.
 
 
So I'll try to tell you just what I know. If you like it, ok,
 
otherwise, well, your business.
 
 
It was one of those stormy nights and I came over to Bob's apartment,
 
down town, with a couple of bottles of a quite strong red wine. We, I
 
mean me and Bob, hate white wine... females' stuff... And when we are
 
alone, I must confess that, we behave very much like Macho Functors.
 
 
But we are all alone, and nobody can judge us.
 
 
Bob was rolling one of his giant spliff with some weed he got
 
somewhere (he wouldn't tell you where no matter what).
 
 
The radio was playing one of those dreadful Dial Sessions, and when
 
Bird misses the entrance in Lover Man, Bob lit up the joint and
 
stared at me. The sound of an almost dying alto sax was filling the
 
room, mixing with the strong smell of weed when I stared back.
 
 
In that very moment I believed, and still believe, I had a glimpse of
 
Bob's soul.
 
 
I may be wrong, but this is what I believe I saw:
 
 
<haskell>
 
 
> whoLovedBy bob = do newLove "Andrea "
 
> andrea <- tellMyself 1
 
> newLove "Bob "
 
> bob <- tellMyself 1
 
> tellMyself (andrea + bob)
 
 
</haskell>
 
 
*Main> whoLovedBy bob
 
Lover {loverDiary = ("Andrea Bob ",2)}
 
*Main>
 
 
Wait a second. This is not true, I'm just kidding... myself.
 
 
In that very moment this is precisely what I saw:
 
 
<haskell>
 
whoLovedBy bob = do newLove "Andrea "
 
andrea <- tellMyself 1
 
tellMyself (andrea + (whoLovedBy bob))
 
</haskell>
 
 
This is all I know about Bob. He loves me, but I'm not the only one.
 
 
- [[User:AndreaRossato|Andrea Rossato]]
 
 
[[Category:Tutorials]]
 
[[Category:Idioms]]
 
[[Category:Monad]]
 

Revision as of 10:53, 6 February 2021