Burning more bridges (mostly numeric ones)

wren romano winterkoninkje at gmail.com
Tue Mar 25 22:54:46 UTC 2014

On Sun, Mar 23, 2014 at 3:11 AM, Edward Kmett <ekmett at gmail.com> wrote:
> 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.


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

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,

More information about the Libraries mailing list