https://wiki.haskell.org/api.php?action=feedcontributions&user=Dynamix&feedformat=atomHaskellWiki - User contributions [en]2024-03-29T07:58:32ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=Talk:Monads_as_containers&diff=14998Talk:Monads as containers2007-08-10T19:58:24Z<p>Dynamix: different mental model ?</p>
<hr />
<div>I am reading this article for the N-th time now, and though I'm quite a bit<br />
clearer on the subject, there still appears to be something at the corner of<br />
the picture that eludes me. Treating Monads as either Containers or<br />
Computations makes perfect sense, each on its own, but both ways brought<br />
together are void, somehow.<br />
<br />
On the one hand, once you understand <code>bind</code>, it seems to be more basic than<br />
<code>join</code> and <code>map</code>, and its definition in terms of those seems a bit<br />
far-fetched. On the other hand, <code>bind</code> presents a significant semantic<br />
threshold to overcome before you can say you understand what it does, while<br />
<code>join</code> and <code>map</code> are much more straightforward.<br />
<br />
Thus, the real problem seems to be reconciling both views. How about a<br />
"Computations as Containers" article? :)<br />
<br />
-- Rambler<br />
<br />
Sorry for the late reply, I hadn't noticed this change until now. The basic<br />
connection is that a (parameterless) computation is a container for its<br />
results. To pass from a value of type (m a) to one of type a, possibly<br />
special circumstances will be necessary and extra context supplied to run the<br />
computation and extract the result from the computation/container. Sometimes,<br />
this will be statically impossible, as is the case with the IO monad.<br />
<br />
The container/computation duality is a bit odd at first, but if you look at<br />
enough parallels in how things work, you'll essentially come to see it as<br />
just two ways of thinking about the same thing. Neither view is really<br />
perfect, but the correct description is rather abstract, so to work with it,<br />
you want some intuitive picture of what's happening.<br />
<br />
Perhaps some clarification as to what <code>join</code> and <code>map</code> do for computations<br />
would be in order. I agree that for computations, bind is more<br />
primitive-seeming than map and join, but map and join aren't all that bad<br />
either. Map is fairly easy - mapping f over some computation gives the<br />
computation which returns f of the result of the original computation. In<br />
do-notation, this looks like: (I have something like this above, but here it<br />
has the interpretive comments)<br />
<br />
<haskell><br />
fmap f x = do r <- x -- run x<br />
return (f r) -- apply f to its result before returning it.<br />
</haskell><br />
<br />
Join is conceptually slightly more bizarre, but still not so bad if you look<br />
at the types: <code>join :: (Monad m) => m (m a) -> m a</code>. It takes a computation<br />
whose result is a computation, and produces the computation which runs that<br />
computation and then runs its result, removing the level of indirection. So<br />
in do notation, that looks like:<br />
<haskell><br />
join x = do a <- x -- run x, getting its result, a<br />
r <- a -- run a, getting its result, r<br />
return r<br />
</haskell><br />
or more simply:<br />
<haskell><br />
join x = do a <- x -- run x<br />
a -- run its result<br />
</haskell><br />
<br />
Looking at those examples is a good way to set up a correspondence of what's<br />
going on with the computations and what's going on with the containers. I'm<br />
not sure how much this helps, but really, being able to switch back and forth<br />
between the two analogies is enough to get a lot done.<br />
<br />
hope this helps,<br />
-- CaleGibbard<br />
<br />
----<br />
<br />
It does help, as far as it points the finger at the key notions to consider. <br />
The relationship is still elusive though, and I am growing ever more likely<br />
to think that the only proper way to appreciate something as fundamental as<br />
this is by rumination (I was hoping I could be spared of that :) This is<br />
partially reinforced by my impression that the topic seems to be the source<br />
of the same amount of confusion for just about anyone else who has approached<br />
it for the first time.<br />
<br />
Thanks for the tips.<br />
<br />
-- Rambler<br />
<br />
----<br />
<br />
Well, the connection between the two analogies is important, but it's good to<br />
remember that you only really need to think of it in one way at a time. It's<br />
possible to get things done even if you only know one way to think about<br />
things. The reason that I put this page up is that I found that at first the<br />
idea of monads as abstractions of computation didn't work so well for me, so<br />
I needed to figure out my own analogy for the way that things worked, and<br />
containers is what worked for me. If you can understand the analogies<br />
separately, then you should have enough material to get work done, and<br />
together with a little experience in using them, to create your own monads. :)<br />
<br />
-- CaleGibbard<br />
<br />
--------<br />
Cale, <br />
the mental model i had initially corresponds most closely to "Monads as Tags" where you tag a value with the name of the monad and the tagged values are treated differently.<br />
Later I refreshed it to "Monads as environments" . This made more sense .. especially with phrases like " in the IO Monad" littered all over the place.<br />
i find it very difficult to think of Monads as just containers.<br />
<br />
-Dynamix</div>Dynamix