[Haskell-cafe] Re: Exception handling in numeric computations

Xiao-Yong Jin xj2106 at columbia.edu
Tue Mar 24 17:14:17 EDT 2009


Jake McArthur <jake at pikewerks.com> writes:

> Xiao-Yong Jin wrote:
> | The problem is that there will be many functions using such
> | a function to invert a matrix, making this inversion
> | function return Either/Maybe or packing it in a monad is
> | just a big headache.
>
> I disagree. If you try to take the inverse of a noninvertable matrix,
> this is an *error* in your code. Catching an error you created in pure
> code and patching it with chewing gum it is just a hack. A monadic
> approach (I'm putting Either/Maybe under the same umbrella for brevity)
> is the only solution that makes any sense to me, and I don't think it's
> ugly as you are making it out to be.
>

Then, why is 'div' not of type 'a -> a -> ArithExceptionMonad a' ?
Why does it throws this /ugly/ /error/ when it is applied to
0?  Why is it not using some beautiful
'ArithExceptinoMonad'?  Is 'Control.Exception' just pure
/ugly/ and doesn't make any sense?

>
> | It is impractical to use method (a),
> | because not every function that uses 'invMat' knows how to
> | deal with 'invMat' not giving an answer.  So we need to use
> | method (b), to use monad to parse our matrix around.
> |
> |> > invMat :: Matrix -> NumericCancerMonad Matrix
> |
> | It hides the exceptional nature of numerical computations
> | very well, but it is cancer in the code.  Whenever any
> | function wants to use invMat, it is mutated.  This is just
> | madness.  You don't want to make all the code to be monadic
> | just because of singularities in numeric calculation.
>
> For functions that don't know or don't care about failure, just use fmap
> or one of its synonyms.
>
> ~    scalarMult 2 <$> invMat x
>
> See? The scalarMult function is pure, as it should be. There is no
> madness here.

Of course, 'scalarMult' is invulnerable and free of monad.
But take a look at the following functions,

> f1 = scalarMult 2 . invMat
> f2 l r = l `multMat` invMat r
> ff :: Matrix -> Matrix -> YetAnotherBiggerMonad Matrix
> ff x y = do let ff' = f1 x + f2 y
>             put . (addMat ff') . f1 << get
>             tell $ f2 ff'
>             when (matrixWeDontLike (f1 ff') $
>                  throwError MatrixWeDontLike
>             return $ scalarMult (1/2) ff'

Yes, I know, it's not really complicate to rewrite the above
code.  But, what do I really gain from this rewrite?
-- 
    c/*    __o/*
    <\     * (__
    */\      <


More information about the Haskell-Cafe mailing list