Haskell bounded worker pool using QSem

Haskell
import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
import Control.Concurrent.QSem (newQSem, signalQSem, waitQSem)
import Control.Exception (SomeException, try)
import Control.Monad (forM)

workerPool :: Int -> [IO a] -> IO [Either SomeException a]
workerPool workers jobs = do
  sem <- newQSem (max 1 workers)
  slots <- forM jobs $ \job -> do
    slot <- newEmptyMVar
    _ <- forkIO $ do
      waitQSem sem
      outcome <- try job
      putMVar slot outcome
      signalQSem sem
    pure slot
  mapM takeMVar slots