
Jake McArthur
Xiao-Yong Jin wrote: | 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?
'div' throws an error because dividing by zero is *programmer error*. *You* are supposed to make sure that you aren't dividing by zero.
I differ from this decision in your case because, as you said, it is easier to check for the error condition in the function itself than to check it externally. This is fine, but because it's so hard to check externally, you have to tell the outside world whether there was an error or not. A functor/applicative/monad is the pure way to do this. An error is not.
| 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?
Code that is fully documented by its type, no harder to compose, more pure, and does what the programmer expects it to do.
Thanks for all the replies. Now I understand more about Exceptions and Errors. I guess all I need is to compose a larger monad, after all. I need to learn how to make two different stacks of monad transformers cooperate seamlessly, though. Thanks, Xiao-Yong -- c/* __o/* <\ * (__ */\ <