If you type :i Monad in ghci, you will see this instance
instance Monad ((->) r)
What this means is a function where the first argument is of type 'r'... is a monad. You can in fact use do notation / return on a tuple to manipulate its second argument monadically.
So let's look at what that does to the type signature of join when 'm' is ((->) b)
join :: Monad m => m (m a) -> m a
-- m = ((->) b)
join :: ((->) b ((->) b a)) -> (((->) b a))
Now we just have to move the arrows from prefix to infix. Let's do it step by step.
join :: ((->) b (b -> a)) -> (b -> a)
join :: (b -> (b -> a)) -> (b -> a)
x -> (y -> z) is equivalent to x -> y -> z
join :: (b -> b -> a) -> (b -> a)
join :: (b -> b -> a) -> b -> a
So now when you put an operator into it that takes two arguments
(,) :: a -> b -> (a,b)
You get the type you saw.
join (,) :: b -> (b, b)