
On Tue, Mar 25, 2014 at 6:54 PM, wren romano
* 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.
This situation really should not be a warning. It's an Integral constraint on a type in contravariant position, which by itself can only be ambiguous if it's given something built from numeric literals and basic arithmetic. Having an Integral instance means a type supports conversions to and from Integer, and I would be very dubious about a type where (fromInteger . toInteger) was not equivalent to id. I really can't see how defaulting an Integral constraint alone to Integer is anything other than safe and sensible. Unfortunately the same type may have other class constraints for which defaulting to Integer would be ridiculous, and if memory serves me the way defaults work doesn't distinguish between the clearly sensible-to-default "6 ^ 12" and the equally not sensible "3 ^ read userInput". In fact, I'd prefer that any type with a Read constraint not default at all, ever. That's just asking for trouble. On the other hand, a warning probably makes sense when defaulting a type with e.g. a Show constraint, or Num (without Integral as well). I'm not sure what exact rules would make the most sense here, but I don't think the current defaulting mechanism would support anything more sophisticated anyhow, so it's not a library issue.
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.
...which would require a Natural type similar to Integer, and probably the corresponding type classes as well, which among other things entails adding a superclass to Num containing fromNatural (and, ideally, containing (+) and (*) as well). That's a pretty big bridge to burn, albeit a very temptingly flammable one. - C.