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.
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
More information about the Libraries
mailing list