
http://thread.gmane.org/gmane.comp.lang.haskell.libraries/9082 .. that Maybe is not the most general abstraction - it loses information wrt to (Either String), for instance:
Prelude> let {f [] = fail "empty"; f [_] = fail "singleton"; f l = return l }
okay, I see, it's just that most partial functions in Data.* / container libraries don't really have multiple failure modes that need distinguishing.
Yes, I noticed that Ross was careful to note that in the message that started that thread. I was more concerned with that specific case being generalized to an argument against not-just-Maybe (I think that was the title on the old wiki?). And single failure mode in the components doesn't imply single failure mode in combinations, either. Consider import Control.Monad import Control.Monad.Error f 1 = return 1 f _ = fail "f" g 2 = return 2 g _ = fail "g" If I call 'f', and it fails, I know that it was 'f' that failed, and it could only fail in a single way, so there's really no point in not replacing 'fail "f"' with 'Nothing', right (and the same goes for 'g')? Wrong (or Left;-)! Combining functions with single failure modes gives combinations with multiple failure modes (think of different branches in a parser/ type system/.., or of different phases in a compiler). Compare the two outputs of 'test' below: forg n = f n `mplus` g n gorf n = g n `mplus` f n fandg n = f n >>= g gandf n = g n >>= f test = do print ([forg 3, gorf 3, fandg 1, fandg 2]::[Maybe Int]) print ([forg 3, gorf 3, fandg 1, fandg 2]::[Either String Int]) I don't know whether that is an immediate concern for the particular functions under discussion from the 'containers' package, apart from all the extra lifting (and re-adding of sensible failure messages) when wanting to use those functions in a non-Maybe Monad? But it is a concern in general monadic programming (and it often requires extra work to ensure that failure paths combine as well as success paths). Claus PS: There was also the argument that there are cases where local failure handling is just not sensible (what the Erlangers call "don't program defensively", or "let it crash"), and where trying to return and handle those 'Nothing's would only make the code less readable as the problem gets passed from Pontius to Pilatus. The "let someone else clean up" approach is also supported by the not-just-Maybe pattern, although not as well in Haskell as in Erlang (with its supervisor trees and heart-beat monitoring).