Hi, Shishir,
As a recovering complexity addict (i.e. Java programmer ;-), I'd put it this way.
There are many methods (on many types) that can either succeed and return a meaningful value, or be unable to fulfill the intent of the caller's request. Example include indexOf on String, get on Map, and read on a Reader. Every time such a partial function scenario occurs, the author must decide what to do if the intent can't be fulfilled. That freedom of choice has led to a proliferation of techniques.
- indexOf returns -1, which is a valid int, but not a valid position within a string.
- get returns null, which is the only value common to all reference types that means 'I have nothing'. Of course, that also prevents one from storing null in a Map and simply retrieving it. Worse, if that result is passed along elsewhere, one can eventually receive a NullPointerException occurring in a completely different part of the code.
- And, horrors!, read responds in a totally different way, by forcing the caller to "jump" somewhere.
Maybe provides a general, reusable solution to all such cases.
- It allows one to "stretch" any type to include an extra "out of band" value.
- The type declaration clearly (uniformly) notifies anyone else that the function may have to return "lack of result".
- The type system prevents a caller from simply assuming that a result is present, and then accidentally propagating failure.
- Because Maybe is an instance of Functor, one can use map to safely apply a function (or do nothing gracefully) without littering the calling code with if-statements.
- etc.
I don't think of Maybe as enabling a computation that is impossible otherwise, but I do regard it as providing a consistency and simplicity that is otherwise not present.
Hope this helps,
Joel