Why is there no << in the Haskell standard library?

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.


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.

Tags:

Haskell

Monads