It's nice to have things pure-by-default; and sprinkle in whatever effects, etc. as desired. (Like Haskell, Idris, Agda, etc.)
For example, I've worked on a lot of Scala code which represented optional values using `Option[T]` (~= Haskell's `Maybe t`); represented possible failures using `Try[T]` (~= `Either Exception t`); and I even used the Cats library to make code polymorphic (i.e. for all `M: Monad`, or `M: MonadThrow`, or indeed `Applicative`, etc.). The older ScalaZ library is a popular alternative to Cats which does similar things. Concurrency is currently quite diverse in Scala: we mostly used `Future[T]`, but there are a bunch of alternatives out there like `Task`, etc. Likewise there are other Scala libraries/frameworks which model side-effects differently, e.g. Zio uses algebraic effects.
However, since Scala is not pure by default, we can't count on any of these fancy types to actually prevent the problems they're meant to address. For example, we can only use `Option` alongside `null`: the latter can't be avoided, since Scala isn't pure; in fact `Option` should technically introduce even more null checks (since `x: Int` might be `null`; but `y: Option[Int]` might be `null` or `Just(null)`!). Likewise, `Try` can only be introduced alongside the possibility of any exception being thrown at any time. And so on.
In contrast, we might have a project e.g. in Haskell, where `IO` appears in all of our types. Such code might use all sorts of confusing effects (e.g. early returns, mutable variables, concurrency, etc.), and may blow up in all sorts of ways, just like Scala, Python, etc. Yet at least they're labelled as such, and we're able to write other values and functions which actually do what they claim (modulo totality, unless we're using Idris, Agda, etc.).