:: Monad m => (m (m a)) -> m a package:stack is:exact

The join function is the conventional monad join operator. It is used to remove one level of monadic structure, projecting its bound argument into the outer level. 'join bss' can be understood as the do expression
do bs <- bss


A common use of join is to run an IO computation returned from an STM transaction, since STM transactions can't perform IO directly. Recall that
atomically :: STM a -> IO a
is used to run STM transactions atomically. So, by specializing the types of atomically and join to
atomically :: STM (IO b) -> IO (IO b)
join       :: IO (IO b)  -> IO b
we can compose them as
join . atomically :: STM (IO b) -> IO b
to run an STM transaction and the IO action it returns.