
On Thu, Dec 03, 2009 at 01:50:06PM -0800, Gregory Crosswhite wrote:
Or, even more concisely:
================================================== sumWithError_3 = liftM2 (+) ==================================================
Unfortunately though, neither of these definitions have the same semantics as the original @sumWithError@, as using both we get the following error message for @showSumOrErrorOf (-1) (-2)@:
================================================== Error computing the square root of -1: Square roots cannot be taken of negative numbers. ==================================================
That is, we have lost the second of the two error messages. The reason for this is that 'Monad'-style error processing expresses the computation as a sequence, and gives up as soon as it sees any error. In this case of @sumWithError@, however, the evaluation of the second argument can proceed even if there was an error in the first argument. Thus, rather than using a 'Monad' pattern, we use an 'Applicative' pattern:
================================================== sumWithError_4 = liftA2 (+) ==================================================
Now both error messages are displayed.
I see no inherent reason that liftM2 (+) cannot collect both error messages. No one says that "monad-style error processing" *must* stop as soon as it sees an error. And having different semantics for liftA2 and liftM2 (etc.) is strange at best. They ought to be equivalent for any type constructor with both Monad and Applicative instances. -Brent