Maybe-summary was: Re: [Haskell-cafe] Re: [Haskell] ANN:random-access-list-0.1

Claus Reinke claus.reinke at
Fri Jun 13 10:43:19 EDT 2008

>> 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).


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).

More information about the Libraries mailing list