
On Sun, Mar 23, 2014 at 12:11 AM, Edward Kmett
On Sat, Mar 22, 2014 at 8:58 PM, Bart Massey
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