Respectfully, I don't think this articles uses monads correctly, because it's not using any. This could be very elegant:
getUser: Option[User]
getFriends(u: User): Seq[Friend]
bestFriends(f: Seq[Friend]): Seq[Friend]
renderFriends(f: Seq[Friend]): Option[UI] // Unit or type UI or HTML or ...
Only `getUser` actually returns an option and is explicit about it. `renderFriends` could arguably do without.
To call, we can do
bestFriends: Option[Seq[Friends]] = getUser.flatMap(u: User => renderFriends(bestFriends(getFriends(u))))
The render function could either gracefully render an empty list or error check as part of the `flatMap`, which takes the form of
flatMap[B](f: A => Option[B]): Option[B]
I really, really dislike it when functions signatures are lying to me, since `User` is clearly != `Option[User]` and `null` will not fit the type semantics of `User`, whatever those are.
And if you don't _call_ it mondads (but rather something more approachable), it's not that wild and scary sounding a concept all of a sudden.
That way, your compiler error checks null-type scenarios for you, your type signatures are clean, don't lie, and your compiler forces you to explicitly do something like `runSafely` (or `runUnsafe` etc.), usually a single point of failure.
Bonus, `MonadError`-type constructs are awesome too, since I get
handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]
type functions (this is from cats in scala) to deal with errors explicitly.