Reputation: 44634
The Monad
class defines a >>
method, which sequences two monadic actions:
>> :: Monad m => m a -> m b -> m b
The binding operator >>=
has a flipped-argument equivalent, =<<
; as do the monadic function composition ('fish') operators >=>
and <=<
. There doesn't seem to be a <<
, though (after a few minutes of Hoogling). Why is this?
Edit: I know it's not a big deal. I just like the way certain lines of code look with the left-pointing operators. x <- doSomething =<< doSomethingElse
just looks nicer, with the arrows all going the same way, than x <- doSomethingElse >>= doSomething
.
Upvotes: 12
Views: 362
Reputation: 50864
Here's an alternative answer, as a similar question was recently asked and marked a duplicate. It turns out that it's not at all clear what the definition of (<<)
should be! While this issue was alluded to in the comments on the older answer, I don't think it was made entirely clear that there's a significant problem here.
Obviously, the two reasonable possibilities for a definition are:
(<<) :: Monad m => m a -> m b -> m a
p << q = do {x <- p; q; return x} -- definition #1
p << q = do {q; p} -- definition #2
By analogy with the applicative operators (<*)
and (*>)
, it's clear that the new (<<)
operator should preserve the ordering of side effects from left to right and only have the effect of switching which action's return value is used, so definition #1 is obviously the correct one. This has the desirable property that <<
and <*
will be synonymous for (well-behaved) monads, just as >>
and *>
are synonymous, so no surprises.
Of course, by analogy with =<<
and >>=
, it's clear that flipping the direction of the greater than signs should have the effect of flipping the arguments, so definiton #2 is obviously the correct one. This has the desirable property that a pipeline of monadic operations:
u >>= v >>= w >> x >>= y
can be reversed by flipping the operators:
y =<< x << w =<< v =<< u
This also preserves the identities for the Kleisli operators:
(f >=> g) x === f x >>= g
(f <=< g) x === f =<< g x
which certainly look like they ought to hold.
Anyway, I don't know if this was the original reason (<<)
was left out. (Probably not, as the decision would have predated the introduction of applicative operators, so people would have assumed "definition #2" as the only possibility), but I'm pretty sure it would be a sticking point now, as the different behavior of (<<)
and (<*)
would be quite unexpected given the close association people expect between applicative and monad operations.
Upvotes: 6
Reputation: 28539
To the best of my knowledge there is no good reason. Note, that your Monad
should also be an instance of Applicative
, so you can use <*
and *>
instead as your sequencing tools.
Upvotes: 11