
Jake McArthur
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/* <\ * (__ */\ <