I know some people consider fail to be a mistake, and I can see why. (It seems like MonadPlus was made to replace it). But as long as it is there, it seems like it would make sense for partial functions to use fail and pure instead of Just and Nothing. As this would allow you to do everything you can currently do and more, so something like safeHead could give you the traditional Just/Nothing or instead you could return [x]/[].
From what I have read about MonadPlus it seems like it would be better than using fail. But I don't know enough about it to say for sure, and it also would probably involve pulling into Prelude, which might be a good idea, but would be a larger change than just using fail.
So I guess my question is why partial functions don't use fail OR MonadPlus, both seem better than using a concrete type.
Well, I can't speak to the motivations of the folks who wrote them, but I certainly share their preference. What I'd say here is that many of us follow a school of thought where the concrete type like
Maybewould be our default choice, because:Types like
a -> Maybe bmodel the concept of a partial function perfectly, because a partial function either returns a result (Just b) or it doesn't (Nothing), and there are no finer distinctions to be made (e.g., there aren't different kinds of "nothingness").Point #3 can be illustrated by this function, which generically transforms
Maybe ainto any instance ofAlternative(which is a superclass ofMonadPlus):So going by this philosophy, you write the partial functions in terms of
Maybe, and if you need the result to be in some otherAlternativeinstance then you use afromMaybefunction as an adapter.This could be however be argued the other way around, where you'd have this:
...with the argument that typing just
safeHead xsis shorter thanfromMaybe (safeHead xs). To each their own.