
On Sun, Mar 23, 2014 at 3:11 AM, Edward Kmett
That said, implicit conversions are something where personally I feel Haskell does take the right approach. It is the only language I have access to where I can reason about the semantics of (+) sanely and extend the set of types.
Ditto. It can sometimes be unfortunate that we don't get the subset inclusions for free, but in my experience the few extra annotations required are a small price to pay for all the bugs caught by not doing so-- when doing numerical work! Not to mention that Int does not really have a subset inclusion into Double, and so this implicit coercion should be forbidden even if we did allow implicitly coercing Int to Integer, etc.
* The multiplicity of exponentiation functions, one of which looks exactly like C's XOR operator, which I've watched trip up newbies a bunch of times. (Indeed, NumericPrelude seems to have added more of these, including the IMHO poorly-named (^-) which has nothing to do with numeric negation as far as I can tell. See "unary negation" above.)
It is unfortunate, but there really is a distinction being made.
I'd go even farther and say that this is another case where Haskell is doing the right thing. There's a fundamental distinction going on here. The only complaints I have here are: 1) Because the type of the second argument to (^) and (^^) is polymorphic, numeric literals introduce warnings about defaulting. This is the one place where needing to make coercions explicit really does get on my nerves. 2) (^) does not restrict the second argument to non-negative values and thus can throw runtime errors, when it really should be a type error. 3) (**) should probably be split to distinguish exponentials and rational/real-valued powers. To see a clear example of how (^) and (^^) are fundamentally different operators, consider their instantiation for square matrices. We can use (^) whenever the scalars of the matrix form a semiring; whereas using (^^) requires that we be able to invert the matrix, which means the scalars must form a field[1]. [1] I'm not sure off hand if we can weaken the requirements to just be a division ring or (strongly) von Neuman regular ring; but certainly my implementation assumes it's a field. -- Live well, ~wren