We cannot generally implement return in terms of fmap. Monad is just more powerful than Functor.
As an exercise, however, we can try and ask this question: what second operation, if any, would make it possible to implement return in turns of fmap? We can attack this question by looking at the types. (We'll use pure from the Applicative class instead of return—they're basically the same operation.)
fmap :: Functor f => (a -> b) -> f a -> f b
pure :: Applicative f => a -> f a
Well, one possible way this could go is if we have the following function:
-- This is like the standard `const` function, but restricted to the `()` type:
const' :: a -> () -> a
const' a = \() -> a
Then we can write this, which is "almost" pure/return:
almostThere :: Functor f => a -> f () -> f a
almostThere a = fmap (const' a)
And then if we had the following class, we could write pure in terms of it:
class Functor f => Pointed f where
unit :: f ()
pure :: Pointed f => a -> f a
pure a = almostThere a unit
To make a long story short, what this boils down to is that return, pure and unit all are functions that allow you to make an f from scratch, while fmap only allows you to make an f if you already have another one. There is no way you can use fmap to implement return/pure unless you have access to some third operation that has the "power" to make an f from scratch. The unit operation I showed is probably the simplest one that has this "power."
fmapcan only transform a wrapped value to another wrapped value. To create a wrapped value you need something more powerful like an Applicative where you havepure :: a -> f a.do { y <- f x; return (a:y) }is the same asfmap (a:) (f x)(can you prove it? hint: use your equation forfmap').join :: Monad m => m (m a) -> m a.joincan be written in terms of>>=andid, and>>=can be written in terms ofjoinandfmap. You might be interested to work out how.