https://wiki.haskell.org/api.php?action=feedcontributions&user=Nathaniel&feedformat=atomHaskellWiki - User contributions [en]2021-12-03T14:40:15ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Talk:Monads_as_containers&diff=61187Talk:Monads as containers2016-10-15T05:13:47Z<p>Nathaniel: /* More details on the state monad */ new section</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<br />
<br />
----<br />
For those starting out with monads, it's probably helpful to actually have the Tree monad code, in case they want to "check their answer." Here it is:<br />
<br />
<haskell><br />
instance Monad Tree where<br />
-- return :: a -> Tree a<br />
return = Leaf<br />
<br />
-- (>>=) :: Tree a -> ( a -> Tree b ) -> Tree b<br />
( Leaf x ) >>= f = f x<br />
( Branch l r ) >>= f = Branch ( l >>= f ) ( r >>= f )<br />
</haskell><br />
<br />
And here are the other functions, for reference:<br />
<br />
<haskell><br />
-- fmap :: ( a -> b ) -> Tree a -> Tree b<br />
fmap f ( Leaf x ) = Leaf ( f x )<br />
fmap f ( Branch l r ) = Branch ( fmap f l ) ( fmap f r )<br />
<br />
-- join :: Tree ( Tree a ) -> Tree a<br />
join ( Leaf t ) = t<br />
join ( Branch l r ) = Branch ( join l ) ( join r )<br />
</haskell><br />
<br />
<br />
Unrelated to the above Monad Tree stuff, I was wondering if anyone had an idea of the kind of container a Continuation represents? :)<br />
<br />
[[User:Kelan|Kelan]] 22:49, 12 December 2007 (UTC)<br />
<br />
----<br />
<br />
I'm trying to understand what the tree monad might be used for. Can anyone provide an example?<br />
<br />
-- [[User:Dangph|Dangph]] 11:14, 12 January 2008 (UTC)<br />
----<br />
<br />
This is an excellent article, but I would advise learners to be aware of the limits of the Monads as Containers analogy.<br />
<br />
The Monad comes from Category Theory. Mathematicians invented Category Theory because they needed a new language to take them past the point where their old analogies broke down.<br />
<br />
The container analogy owes more to Set Theory than Category Theory. It's useful as a pair of training wheels but, ultimately, it must be discarded.<br />
<br />
I think that the way forward is to find a way to teaching Monads that is informed by Category Theory, but doesn't actually teach Category Theory. (After all, we don't have to teach Group Theory to teach arithmetic.)<br />
<br />
-- [[User:Peter McArthur|Peter McArthur]] 12:21, 20 August 2009 (UTC)<br />
<br />
== More details on the state monad ==<br />
<br />
I know this is an old post and I hope you're still active here. I'd really like to understand the state monad in terms of map and join, but I'm completely mystified by<br />
<br />
join :: (State s (State s a)) -> (State s a)<br />
join xss = State (\s -> uncurry runState (runState xss s))<br />
<br />
I can mentally parse that, but I can't seem to get any intuition about what it's really doing, or why. I don't suppose it would be possible to expand in a bit more detail on the motivation for this code?<br />
<br />
[[User:Nathaniel|Nathaniel]] ([[User talk:Nathaniel|talk]]) 05:13, 15 October 2016 (UTC)</div>Nathaniel