Proposal: Applicative => Monad: Call for consensus

Gábor Lehel illissius at gmail.com
Thu Jan 6 20:52:56 CET 2011


On Thu, Jan 6, 2011 at 5:42 PM, Iavor Diatchki <iavor.diatchki at gmail.com> wrote:
> Hi,
>
> On Wed, Jan 5, 2011 at 3:29 PM, <roconnor at theorem.ca> wrote:
>>
>> On Wed, 5 Jan 2011, Iavor Diatchki wrote:
>>
>>> Hi,
>>>
>>> On Wed, Jan 5, 2011 at 8:04 AM, <roconnor at theorem.ca> wrote:
>>>      On Tue, 4 Jan 2011, Iavor Diatchki wrote:
>>>      In my completion monad, "join" is more efficent than "bind id"
>>>
>>>
>>> This suggests that your monad will work less efficiently if you use it
>>> with the do-notation.
>>
>> No.  If I need to use fmap, there is no getting around it.  Only if I use
>> "bind id" is it faster to use "join".
>
> I am not familiar with your monad but if you are not making essential use of
> "bind" (or join and fmap together), then perhaps the monadic structure is
> not particularly important?
>
>>>
>>> Join and bind are very similar and, at least in standard Haskell code, I
>>> think that "bind" has proven to be a lot
>>> more useful then "join".
>>
>> AFAIU, In applicative style programming "join" has proven to be a lot more
>> useful than "bind".
>
> I am not sure what you mean here, I find the "do" notation quite useful.
>
>>>
>>> Also, as I mentioned before, if people find "join" easier to define then
>>> "bind", then they can define "join", and
>>> then define "bind" in terms of that---I am still not convinced that we
>>> need a new method added to the Monad class.
>>
>> If people find "bind" easier to define "join", then they can define
>> "bind", and then define "join" in terms of that---Your argument is totally
>> symetric in the terms "bind" and "join".
>
> The situation is not symmetric because we already have a class with ">>="
> and lots of code which depends on it---so I don't think that replacing ">>="
> with "join" is really plausible (I would certainly not support such a
> change).  I am not convinced that adding "join" to the class, in addition to
> ">>=", buys us anything but complexity.
> -Iavor

I'm not sure what you mean here by "replace" -- to _remove_ bind from
Monad, and add join instead? I don't know of anyone proposing this.

You're perfectly correct that it's possible to define a standalone
join function yourself, and then write in what would be the proposed
default definition for bind manually -- but roconnor is also perfectly
correct that if the situation were the other way around, the same
thing would be true in reverse. In other words, the argument is that
the situation with bind being a method of Monad and join not being
such is a historical accident, and not one supported by the merits.

The fact that you can still write the function outside the class and
define the class method in terms of it manually is true of
approximately every class method and standalone function ever written.
We could write all of our classes so that the most complicated and
impressive functions are the methods, while defining the simple ones
standalone in terms of those, with perhaps only a small amount of
annoyance overhead resulting for our users -- but we don't. We tend to
seek the ability to write minimal class definitions using the simplest
and most straightforward methods we can find. It sends a message: this
is the easiest/best way to write an instance. If you resort to writing
what should've been a method as a standalone function instead and
defining the method in terms of it, the message it sends is "the
definition of this class is flawed and I'm working around it". But
most people probably don't think of doing this, and just define the
simplest out of whatever methods they are given. After all, writing
simple functions and then defining the more complex ones as
combinations of those is what Haskell is all about, isn't it? So we
should strive to support that, even if it can be done in our spite
when we don't.

And as has been argued at length in this thread, for a great many
types it is easier, cognitively if not physically, to define fmap and
join than to define bind. (And for the others, like Oleg's example,
they can just say fmap = liftM and keep merrily on.) It was actually
thinking about the type signature of join which made the whole Monad
thing finally 'click' for me, which isn't bad considering that
Applicative has only about halfway clicked so far. It absolutely feels
more fundamental as an operation than bind does, even if bind might be
the more useful combinator.

There's also the consideration that when defining instances for a new
type, many (most?) people tend to write an instance for the superest
class in a hierarchy first, and then to work their way down. (Even
without the hierarchy being explicit a lot of people, myself included,
already do this for Functor/Applicative/Monad). So by the time they
get to Monad they have an fmap already written, and they're like --
"why do I have to reimplement essentially the same functionality again
as part of (>>=)? Oh wait, here's join instead, that'll be easier."


>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>
>



-- 
Work is punishment for failing to procrastinate effectively.



More information about the Libraries mailing list