I'm delighted to see the possibility of adding join as a Monad method. I almost always have an easier time thinking about join than (>>=) and wish I could define join instead of (>>=), without having to pay the cost of defining an additional joinFoo function and then having the actual join function end up implemented via (>>=) via joinFoo.<br>
<br>I relate to Gábor's points that<br><br>* The familiarity advantage of (>>=) is a historical accident. I like to see the language improve over time, rather than accumulate accidents.<br>* I prefer functions & methods with simpler interfaces over more complex interfaces. I'm happy to compose these simpler operations to get more complex operations, e.g. join+fmap vs (>>=).<br>
<br> - Conal<br><br><div class="gmail_quote">2011/1/6 Gábor Lehel <span dir="ltr"><<a href="mailto:illissius@gmail.com">illissius@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div></div><div class="h5">On Thu, Jan 6, 2011 at 5:42 PM, Iavor Diatchki <<a href="mailto:iavor.diatchki@gmail.com">iavor.diatchki@gmail.com</a>> wrote:<br>
> Hi,<br>
><br>
> On Wed, Jan 5, 2011 at 3:29 PM, <<a href="mailto:roconnor@theorem.ca">roconnor@theorem.ca</a>> wrote:<br>
>><br>
>> On Wed, 5 Jan 2011, Iavor Diatchki wrote:<br>
>><br>
>>> Hi,<br>
>>><br>
>>> On Wed, Jan 5, 2011 at 8:04 AM, <<a href="mailto:roconnor@theorem.ca">roconnor@theorem.ca</a>> wrote:<br>
>>> On Tue, 4 Jan 2011, Iavor Diatchki wrote:<br>
>>> In my completion monad, "join" is more efficent than "bind id"<br>
>>><br>
>>><br>
>>> This suggests that your monad will work less efficiently if you use it<br>
>>> with the do-notation.<br>
>><br>
>> No. If I need to use fmap, there is no getting around it. Only if I use<br>
>> "bind id" is it faster to use "join".<br>
><br>
> I am not familiar with your monad but if you are not making essential use of<br>
> "bind" (or join and fmap together), then perhaps the monadic structure is<br>
> not particularly important?<br>
><br>
>>><br>
>>> Join and bind are very similar and, at least in standard Haskell code, I<br>
>>> think that "bind" has proven to be a lot<br>
>>> more useful then "join".<br>
>><br>
>> AFAIU, In applicative style programming "join" has proven to be a lot more<br>
>> useful than "bind".<br>
><br>
> I am not sure what you mean here, I find the "do" notation quite useful.<br>
><br>
>>><br>
>>> Also, as I mentioned before, if people find "join" easier to define then<br>
>>> "bind", then they can define "join", and<br>
>>> then define "bind" in terms of that---I am still not convinced that we<br>
>>> need a new method added to the Monad class.<br>
>><br>
>> If people find "bind" easier to define "join", then they can define<br>
>> "bind", and then define "join" in terms of that---Your argument is totally<br>
>> symetric in the terms "bind" and "join".<br>
><br>
> The situation is not symmetric because we already have a class with ">>="<br>
> and lots of code which depends on it---so I don't think that replacing ">>="<br>
> with "join" is really plausible (I would certainly not support such a<br>
> change). I am not convinced that adding "join" to the class, in addition to<br>
> ">>=", buys us anything but complexity.<br>
> -Iavor<br>
<br>
</div></div>I'm not sure what you mean here by "replace" -- to _remove_ bind from<br>
Monad, and add join instead? I don't know of anyone proposing this.<br>
<br>
You're perfectly correct that it's possible to define a standalone<br>
join function yourself, and then write in what would be the proposed<br>
default definition for bind manually -- but roconnor is also perfectly<br>
correct that if the situation were the other way around, the same<br>
thing would be true in reverse. In other words, the argument is that<br>
the situation with bind being a method of Monad and join not being<br>
such is a historical accident, and not one supported by the merits.<br>
<br>
The fact that you can still write the function outside the class and<br>
define the class method in terms of it manually is true of<br>
approximately every class method and standalone function ever written.<br>
We could write all of our classes so that the most complicated and<br>
impressive functions are the methods, while defining the simple ones<br>
standalone in terms of those, with perhaps only a small amount of<br>
annoyance overhead resulting for our users -- but we don't. We tend to<br>
seek the ability to write minimal class definitions using the simplest<br>
and most straightforward methods we can find. It sends a message: this<br>
is the easiest/best way to write an instance. If you resort to writing<br>
what should've been a method as a standalone function instead and<br>
defining the method in terms of it, the message it sends is "the<br>
definition of this class is flawed and I'm working around it". But<br>
most people probably don't think of doing this, and just define the<br>
simplest out of whatever methods they are given. After all, writing<br>
simple functions and then defining the more complex ones as<br>
combinations of those is what Haskell is all about, isn't it? So we<br>
should strive to support that, even if it can be done in our spite<br>
when we don't.<br>
<br>
And as has been argued at length in this thread, for a great many<br>
types it is easier, cognitively if not physically, to define fmap and<br>
join than to define bind. (And for the others, like Oleg's example,<br>
they can just say fmap = liftM and keep merrily on.) It was actually<br>
thinking about the type signature of join which made the whole Monad<br>
thing finally 'click' for me, which isn't bad considering that<br>
Applicative has only about halfway clicked so far. It absolutely feels<br>
more fundamental as an operation than bind does, even if bind might be<br>
the more useful combinator.<br>
<br>
There's also the consideration that when defining instances for a new<br>
type, many (most?) people tend to write an instance for the superest<br>
class in a hierarchy first, and then to work their way down. (Even<br>
without the hierarchy being explicit a lot of people, myself included,<br>
already do this for Functor/Applicative/Monad). So by the time they<br>
get to Monad they have an fmap already written, and they're like --<br>
"why do I have to reimplement essentially the same functionality again<br>
as part of (>>=)? Oh wait, here's join instead, that'll be easier."<br>
<div class="im"><br>
<br>
><br>
> _______________________________________________<br>
> Libraries mailing list<br>
> <a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
> <a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
><br>
><br>
<br>
<br>
<br>
</div><div class="im">--<br>
Work is punishment for failing to procrastinate effectively.<br>
<br>
_______________________________________________<br>
</div><div><div></div><div class="h5">Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
</div></div></blockquote></div><br>