So I have this line of code:
[Nothing] >>= \(Just x) -> [x]
which of course gives exception, because the pattern doesn't match Nothing.
On the other hand, this code gives a different result, []:
do
Just x <- [Nothing]
return x
As I see it, they should produce the same result, because do-blocks should be desugared into using (>>=) and return. But this is not the case, making do-notation a feature rather than a syntactic sugar.
I know that fail exists in the monad type class and I know that it is called when a pattern matching fails in a do-block, but I can't understand why it is a wanted behavior that should be different than using normal monad operations.
So my questions is - why should the fail method exist at all?