Why Reader implemented based ReaderT?

They are the same data type to share as much code as possible between Reader and ReaderT. As it stands, only runReader, mapReader, and withReader have any special cases. And withReader doesn't have any unique code, it's just a type specialization, so only two functions actually do anything special for Reader as opposed to ReaderT.

You might look at the module exports and think that isn't buying much, but it actually is. There are a lot of instances defined for ReaderT that Reader automatically has as well, because it's the same type. So it's actually a fair bit less code to have only one underlying type for the two.

Given that, your question boils down to asking why Reader is implemented on top of ReaderT, and not the other way around. And for that, well, it's just the only way that works.

Let's try to go the other direction and see what goes wrong.

newtype Reader r a = Reader (r -> a)
type ReaderT r m a = Reader r (m a)

Yep, ok. Inline the alias and strip out the newtype wrapping and ReaderT r m a is equivalent to r -> m a, as it should be. Now let's move forward to the Functor instance:

instance Functor (Reader r) where
    fmap f (Reader g) = Reader (f . g)

Yep, it's the only possible instance for Functor for that definition of Reader. And since ReaderT is the same underlying type, it also provides an instance of Functor for ReaderT. Except something has gone horribly wrong. If you fix the second argument and result types to be what you'd expect, fmap specializes to the type (m a -> m b) -> ReaderT r m a -> ReaderT r m b. That's not right at all. fmap's first argument should have the type (a -> b). That m on both sides is definitely not supposed to be there.

But it's just what happens when you try to implement ReaderT in terms of Reader, instead of the other way around. In order to share code for Functor (and a lot more) between the two types, the last type variable in each has to be the same thing in the underlying type. And that's just not possible when basing ReaderT on Reader. It has to introduce an extra type variable, and the only way to do it while getting the right result from doing all the substitutions is by making the a in Reader r a refer to something different than the a in ReaderT r m a. And that turns out to be incompatible with sharing higher-kinded instances like Functor between the two types.

Amusingly, you sort of picked the best possible case with Reader in that it's possible to get the types to line up right at all. Things fail a lot faster if you try to base StateT on State, for instance. There's no way to even write a type alias that will add the m parameter and expand to the right thing for that pair. Reader requires you to explore further before things break down.