Use `Traversable.mapM` for cleaner IO/Maybe interaction