What is the relationship between bind and join?

A monad can be either defined in terms of:

  • return :: a -> m a
  • bind :: m a -> (a -> m b) -> m b

or alternatively in terms of:

  • return :: a -> m a
  • fmap :: (a -> b) -> m a -> m b
  • join :: m (m a) -> m a

To your questions:

  1. No, we cannot define fmap in terms of join, since otherwise we could remove fmap from the second list above.
  2. No, "every monad is a functor" is a statement about monads in general, regardless whether you define your specific monad in terms of bind or in terms of join and fmap. It is easier to understand the statement if you see the second definition, but that's it.
  3. Yes, bind is more "powerful" than join. It is exactly as "powerful" as join and fmap combined, if you mean with "powerful" that it has the capacity to define a monad (always in combination with return).

For an intuition, see e.g. this answer – bind allows you to combine or chain strategies/plans/computations (that are in a context) together. As an example, let's use the Maybe context (or Maybe monad):

λ: let plusOne x = Just (x + 1)
λ: Just 3 >>= plusOne
Just 4

fmap also let's you chain computations in a context together, but at the cost of increasing the nesting with every step.[1]

λ: fmap plusOne (Just 3)
Just (Just 4)

That's why you need join: to squash two levels of nesting into one. Remember:

join :: m (m a) -> m a

Having only the squashing step doesn't get you very far. You need also fmap to have a monad – and return, which is Just in the example above.

[1]: fmap and (>>=) don't take their two arguments in the same order, but don't let that confuse you.


Is there a [definition] of fmap in terms of join?

No, there isn't. That can be demonstrated by attempting to do it. Suppose we are given an arbitrary type constructor T, and functions:

returnT :: a -> T a
joinT :: T (T a) -> T a

From this data alone, we want to define:

fmapT :: (a -> b) -> T a -> T b

So let's sketch it:

fmapT :: (a -> b) -> T a -> T b
fmapT f ta = tb
    where
    tb = undefined  -- tb :: T b

We need to get a value of type T b somehow. ta :: T a on its own won't do, so we need functions that produce T b values. The only two candidates are joinT and returnT. joinT doesn't help:

fmapT :: (a -> b) -> T a -> T b
fmapT f ta = joinT ttb
    where
    ttb = undefined  -- ttb :: T (T b)

It just kicks the can down the road, as needing a T (T b) value under these circumstances is no improvement.

We might try returnT instead:

fmapT :: (a -> b) -> T a -> T b
fmapT f ta = returnT b
    where
    b = undefined  -- b :: b

Now we need a b value. The only thing that can give us one is f:

fmapT :: (a -> b) -> T a -> T b
fmapT f ta = returnT (f a)
    where
    a = undefined  -- a :: a

And now we are stuck: nothing can give us an a. We have exhausted all available possibilities, so fmapT cannot be defined in such terms.

A digression: it wouldn't suffice to cheat by using a function like this:

extractT :: T a -> a

With an extractT, we might try a = extractT ta, leading to:

fmapT :: (a -> b) -> T a -> T b
fmapT f ta = returnT (f (extractT ta))

It is not enough, however, for fmapT to have the right type: it must also follow the functor laws. In particular, fmapT id = id should hold. With this definition, fmapT id is returnT . extractT, which, in general, is not id (most functors which are instances of both Monad and Comonad serve as examples).


Is "every monad is a functor" a conclusion when using bind (in the definition of a monad), but an assumption when using join?

"Every monad is a functor" is an assumption, or, more precisely, part of the definition of monad. To pick an arbitrary illustration, here is Emily Riehl, Category Theory In Context, p. 154:

Definition 5.1.1. A monad on a category C consists of

  • an endofunctor T : C → C,

  • a unit natural transformation η : 1CT, and

  • a multiplication natural transformation μ :T2T,

so that the following diagrams commute in CC: [diagrams of the monad laws]

A monad, therefore, involves an endofunctor by definition. For a Haskell type constructor T that instantiates Monad, the object mapping of that endofunctor is T itself, and the morphism mapping is its fmap. That T will be a Functor instance, and therefore will have an fmap, is, in contemporary Haskell, guaranteed by Applicative (and, by extension, Functor) being a superclass of Monad.

Is that the whole story, though? As far as Haskell is concerned. we know that liftM exists, and also that in a not-so-distant past Functor was not a superclass of Monad. Are those two facts mere Haskellisms? Not quite. In the classic paper Notions of computation and monads, Eugenio Moggi unearths the following definition (p. 3):

Definition 1.2 ([Man76]) A Kleisli triple over a category C is a triple (T, η, _*), where T : Obj(C) → Obj(C), ηA : A → T A for A ∈ Obj(C), f* : T A → T B for f : A → T B and the following equations hold:

  • ηA* = idT A
  • ηA; f* = f   for   f : A → T B
  • f*; g* = (f; g*)*   for   f : A → T B   and   g : B → T C

The important detail here is that T is presented as merely an object mapping in the category C, and not as an endofunctor in C. Working in the Hask category, that amounts to taking a type constructor T without presupposing it is a Functor instance. In code, we might write that as:

class KleisliTriple t where
    return :: a -> t a
    (=<<) :: (a -> t b) -> t a -> t b

-- (return =<<) = id
-- (f =<<) . return = f
-- (g =<<) . (f =<<) = ((g =<<) . f =<<)

Flipped bind aside, that is the pre-AMP definition of Monad in Haskell. Unsurprisingly, Moggi's paper doesn't take long to show that "there is a one-to-one correspondence between Kleisli triples and monads" (p. 5), establishing along the way that T can be extended to an endofunctor (in Haskell, that step amounts to defining the morphism mapping liftM f m = return . f =<< m, and then showing it follows the functor laws).

All in all, if you write lawful definitions of return and (>>=) without presupposing fmap, you indeed get a lawful implementation of Functor as a consequence. "There is a one-to-one correspondence between Kleisli triples and monads" is a consequence of the definition of Kleisli triple, while "a monad involves an endofunctor" is part of the definition of monad. It is tempting to consider whether it would be more accurate to describe what Haskellers did when writing Monad instances as "setting up a Klesili triple" rather than "setting up a monad", but I will refrain out of fear of getting mired down terminological pedantry -- and in any case, now that Functor is a superclass of Monad there is no practical reason to worry about that.


Is bind more "powerful" than join? And what would "more powerful" mean?

Trick question!

Taken at face value, the answer would be yes, to the extent that, together with return, (>>=) makes it possible to implement fmap (via liftM, as noted above), while join doesn't. However, I don't feel it is worthwhile to insist on this distinction. Why so? Because of the monad laws. Just like it doesn't make sense to talk about a lawful (>>=) without presupposing return, it doesn't make sense to talk about a lawful join without pressuposing return and fmap.

One might get the impression that I am giving too much weight to the laws by using them to tie Monad and Functor in this way. It is true that there are cases of laws that involve two classes, and that only apply to types which instantiate them both. Foldable provides a good example of that: we can find the following law in the Traversable documentation:

The superclass instances should satisfy the following: [...]

In the Foldable instance, foldMap should be equivalent to traversal with a constant applicative functor (foldMapDefault).

That this specific law doesn't always apply is not a problem, because we don't need it to characterise what Foldable is (alternatives include "a Foldable is a container from which we can extract some sequence of elements", and "a Foldable is a container that can be converted to the free monoid on its element type"). With the monad laws, though, it isn't like that: the meaning of the class is inextricably bound to all three of the monad laws.