Burning more bridges (mostly numeric ones)

Bart Massey bart at cs.pdx.edu
Sun Mar 23 08:50:43 UTC 2014


On Sun, Mar 23, 2014 at 12:11 AM, Edward Kmett <ekmett at gmail.com> wrote:
> On Sat, Mar 22, 2014 at 8:58 PM, Bart Massey <bart at cs.pdx.edu> wrote:
>>>> let x = 3
>>>> x + 3.5
> 6.5
>
> ghci turns no NoMonomorphismRestriction on newer GHCs.

Nice. AFAICT newer means 7.8, which I haven't tried yet. Major improvement.

>> Even worse, the same sort of thing happens when trying to add a
>> `Data.Word.Word` to an `Integer`. This is a totally safe conversion if
>> you just let the result be `Integer`.
>
> Because of that type inference works better. It can flow both forward and
> backwards through (+), whereas the approach you advocate is strictly less
> powerful. You have to give up overloading of numeric literals, and in
> essence this gives up on the flexibility of the numerical tower to handle
> open sets of new numerical types.

You obviously know far more about this than me, but I'm not seeing it? AFAICT
all I am asking for is numeric subtyping using the normal typeclass mechanism,
but with some kind of preference rules that get the subtyping right in
"normal" cases?
I can certainly agree that I don't want to go toward C's morass of
"widening to unsigned" (???) or
explicitly-typed numeric literals. I just want a set of type rules
that agrees with grade-school
mathematics most of the time. I'm sure I'm missing something, and it
really is that hard, but
if so it makes me sad.

>> * The inability of Haskell to handle unary negation sanely, which
>> means that I and newbies alike are constantly having to figure things
>> out and parenthesize. From my observations of students, this is a huge
>> barrier to Haskell adoption: people who can't write 3 + -5 just give
>> up on a language. (I love the current error message here, "cannot mix
>> `+' [infixl 6] and prefix `-' [infixl 6] in the same infix
>> expression", which is about as self-diagnosing of a language failing
>> as any error message I've ever seen.)
>
>
> That is probably fixable by getting creative in the language grammar. I note
> it particularly because our Haskell like language Ermine here at work gets
> it right. ;)

Almost every PL I've seen with infix arithmetic gets it right. It's
trivial for any
operator-precedence parser, and not too hard for other common kinds. In general
it would be nice if Haskell allowed arbitrary prefix and postfix unary
operators, but I'd settle
for a special case for unary minus.

>> * 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 get that. I even get that static-typing exponentiation is hard. (You
should see how
we did it in Nickle (http://nickle.org) --not because it's good but because
it calls out a lot of the problems.) What I don't get is why the names seem
so terrible to me, nor why the typechecker can't do more to help reduce the
number of needed operators, ideally to one. It might mean extra conversion
operators around exponentiation once in a while, I guess?

>> * The incredible awkwardness of hex/octal/binary input handling, which
>> requires digging a function with an odd and awkward return convention
>> (`readHex`) out of an oddly-chosen module (or rolling my own) in order
>> to read a hex value. (Output would be just as bad except for
>> `Text.Printf` as a safety hatch.) Lord knows what you're supposed to
>> do if your number might have a C-style base specifier on the front,
>> other than the obvious ugly brute-force thing?
>
>
> A lot of people these days turn to lens for that:
>
>>>> :m + Numeric.Lens Control.Lens
>>>> "7b" ^? hex
> Just 123
>>>> hex # 123
> "7b"

Nice. Once this really becomes standard, I guess we'll be somewhere.

>> * Defaulting numeric types with "-Wall" on producing scary warnings.

> This is no longer a problem at ghci due to NMR:
>
>>>> 3 + 3
> 6

Nice.

I'm not sure what to make of something like this (with ghci -Wall
-XNoMonomorphismRestriction)

>> let discard :: Integral a => a -> (); discard _ = ()
>> discard 3

<interactive>:5:1: Warning:
    Defaulting the following constraint(s) to type `Integer'
      (Integral a0)
        arising from a use of `discard' at <interactive>:5:1-7
      (Num a0) arising from the literal `3' at <interactive>:5:9
    In the expression: discard 3
    In an equation for `it': it = discard 3

<interactive>:5:1: Warning:
    Defaulting the following constraint(s) to type `Integer'
      (Integral a0)
        arising from a use of `discard' at <interactive>:5:1-7
      (Num a0) arising from the literal `3' at <interactive>:5:9
    In the expression: discard 3
    In an equation for `it': it = discard 3
()

I get the feeling I just shouldn't worry about it: there's not much to
be done, as this is just a limitation
of the static type system and not really Haskell's fault. (Although I wonder why
the conversion is warned twice? :-)

> You can of course use
>
>>>> :set -Wall -fno-warn-type-defaults
>
> instead of -Wall for cases like
>
>>>> 3 == 3
>
> where the type doesn't get picked.

Of course. I have no idea what warnings
I might be turning off that would actually be useful?

Anyway, thanks much for the response!

--Bart


More information about the Libraries mailing list