In practice, this means that you write a decent part of your program using these techniques, which creates a block of code that produces a Maybe value after taking a bunch of Maybe inputs. Then you only use a case statement at the very end, when you need to plug the Maybe value back into normal code.
All these functions are useful for one particular case: you don't know what to do with a Nothing value, so if you see one anywhere, you just pass it on: your final result is Nothing. That pattern just turns out to be very useful.
Like NaN, it can be hard to track down where things went wrong.
This is a great reason to avoid huge chunks of code stitched together staying inside Maybe, while still being convenient on the small scale.
data Employee = Employee { name : Text, spouse : Maybe Text }
You may also want to use Either to store two possible outcomes of an operation, though I would recommend using your own sum type for clarity: data MyOwnEither a b = MyLeft a | MyRight bUnlike NaN, you have the freedom to not use it when you don't want it.
However, sometimes a Maybe represents an inherently "optional" part of your data model, such as "a Foo may have zero or one Bar". In that case, you'll probably hold onto the Maybe until the point where you'd actually read and use that field.