
Daniel Yokomizo
On Tue, Mar 24, 2009 at 1:27 PM, Xiao-Yong Jin
wrote: Henning Thielemann
writes: Try to never use exception handling for catching programming errors! Division by zero is undefined, thus a programming error when it occurs. http://www.haskell.org/haskellwiki/Error http://www.haskell.org/haskellwiki/Exception I'm afraid, a Maybe or Either or Exceptional (see explicit-exception package) return value is the only way to handle exceptional return values properly. Maybe in the larger context of your problem zero denominators can be avoided? Then go this way.
Using div is just an example I'm testing with what I read in the book Real World Haskell. The real thing I'm trying to do is inverting a matrix. Say, I want to write
invMat :: Matrix -> Matrix
You won't be able to invert all the matrix, mathematically. And computationally, even a larger set of matrix might fail to be inverted because of the finite precision. It is relatively easier and more efficient to spot such a problem within this 'invMat' function. Because testing the singularity of a matrix is equally hard as invert it. So all I can do when 'invMat' spot a singular matrix are
a) Return Either/Maybe to signal an error. b) Wrap it in a monad. c) Define a dynamic exception and throw it.
In general if a function is partial we can either make it total by extending its range or restricting its domain. Also we can signal it using runtime or compile-time mechanisms. Options a & b are equivalent (i.e. extend the range, compile-time notification) and option c is also another way of extending the range, but using runtime notification.
If we try the other approach, we need to express the totality of invMat by restricting its domain, so we can add, for example, a phantom type to Matrix to signal it is invertible. As you need to construct the Matrix before trying to invert it you can always make the constructors smart enough to bundle the Matrix with such properties. Of course there's need to do some runtime verifications earlier, but the clients of invMat are required to do the verification earlier or pass it to their clients (up to the level that can handle with this issue):
data Invertible tryInvertible :: Matrix a -> Maybe (Matrix Invertible) invMat :: Matrix Invertible -> Matrix Invertible
You could use different forms of evidence (e.g. phantom types, type classes) but the idea is the same.
This is theoretically sound, we can make a type 'Integer Invertible' and make a 'safeDiv' to get rid of one of the ArithException. But as I said above, "testing the singularity of a matrix is equally hard as inverting it", doing it with matrix is more impractical than make 'div' safe. I don't mind my haskell code runs 6 times slower than c++ code. But I'm not ready to make it 10 times slower just because I want to do something twice and it might as well be useless most of the time. -- c/* __o/* <\ * (__ */\ <