Hacker News new | past | comments | ask | show | jobs | submit login

In the case of arithmetic, strong typing is kind of nice, because math is different dependent on what types you are using. 3/2 = 1 for integers, 1.5 for floats, etc... You really don't want to mix those up in mission critical sections of code.



> In the case of arithmetic, strong typing is kind of nice, because math is different dependent on what types you are using. 3/2 = 1 for integers, 1.5 for floats, etc... You really don't want to mix those up in mission critical sections of code.

While I agree that you don't want to mix up actual division and floor division, I also rather strongly prefer “/” to be actual division, not floor division, irrespective of the operands. int/int -> rational is the most correct behavior. Scheme’s numeric tower is the poster child for getting this right (not just for division but for things involving numbers generally, including decimal literals specifying exact numbers and not approximate binary floats by default.)

If I want an operation that is not actual division, that that is what is happening should be visually distinct in code.


I quite like what Haskell has here. You type in number literals, but they get a type based on context. So 2*3.14 will work there.


Haskell's number system has its good points, but there are some hidden gotchas there as well. For example, all integer literals are interpreted by starting from the most general type (arbitrary-precision integers) and narrowing them with `fromInteger`, a member of the `Num` typeclass—which doesn't offer any means of handling failure (e.g. `321483209423 :: Word8`) other than a runtime error or overflow. It can also be rather verbose since all other conversions must be explicit, even ones which cannot possibly fail.

IMHO Rust's `Into` and `TryInto` traits offer a better solution than Haskell's `fromInteger`, distinguishing between conversions which cannot fail and ones which may. It also infers the correct width for unsuffixed integer literals from the context—but it draws a sharp distinction between integer and floating-point literals, which is why `2 * 3.14` (integer * float) is a type error while `2 * 314u16` would be accepted without issue. The downside of the Rust approach is that the type inference rules for integer literals are hard-coded into the language and can't easily be extended to cover user-defined types, whereas Haskell's approach can accept integer literals where any type with an instance of the `Num` typeclass is expected. One alternative, combining the best of both worlds, would be to infer the narrowest type which can hold the literal value and add an implicit `.into()` for non-lossy conversion to any compatible type.


That is nice and common in high-level languages, but most math is done at runtime with some kind of input. That's when strict typing is helpful.


> That's when strict typing is helpful.

How does it help? I don't mean "strict typing" in general, but specifically how does making us decorate numeric literals help with "math done at runtime with some kind of input"?


> specifically how does making us decorate numeric literals help with "math done at runtime with some kind of input"

It forces you to be specific about rounding, minimum/maximum, and floating-point arithmetic.

Your compiler doesn't/can't know expected extremes of a value. If it defaults to, let's say, int64, then you're potentially wasting enormous amounts of memory (depending on the size of your data).

Similarly, the programmer needs to be specific about precision. If you know you're dealing with integers, then an integer type is great. If you know you need N digits of precision, you can select a numeric type that fits.

The type system becomes useful if/when you start to mix these numbers together. It can warn you that you're losing precision (or adding artificial precision, by casting an integer to a double, for example).

And that isn't even getting into questions of whether you want the number stored on the stack or the heap, which I believe Rust gives you more control over than most languages do.


> Your compiler doesn't/can't know expected extremes of a value.

Yes, it can! For one thing, it's a literal; it has one value; trivially, that's both extremes. But even leaving aside possibilities for anything new and smart, Rust has type inference so it knows what type a given literal has to be (or it doesn't; I have no objection to making the programmer be specific in that case).

I'm asking what problem you see arising from a policy like "`2u32` means 2 as a 32 bit unsigned integer, but `2` means 2 as whatever type is inferred, no defaulting, and we catch it at compile time when the literal can't be represented exactly in the type." (Ignoring simple path dependence - it would be a breaking change because it would make some expressions ambiguous where they relied on a lack of suffix meaning i32 or f64.)

> The type system becomes useful if/when you start to mix these numbers together.

As mentioned, I'm not objecting to the type system, or asking for any implicit conversions except a lossless(!) implicit conversion from the string the programmer typed to the datatype inferred by the type checker.


Actually, it seems to already do this, although it requires the type be integer!

https://play.rust-lang.org/?version=stable&mode=debug&editio...


> it's a literal

This is the situation I was explicitly excluding from my original comment. I was talking about runtime input, which is by far the more common use-case for numbers in code.

A smart compiler will just optimize operations on literals into their result at compile time anyway.


I think that makes your original comment non-sequitur?

Haskell does not allow Integer * Double (or even Integer * Int32), but it does allow `2 * 3.14`, and you seemed to be saying that what Haskell does is somehow dangerously weakly typed.


Go does this too.


Yeah seriously. I'm surprised by the other comments here. It seems like people want loosy goosey typing that magically inserts lossy casts with convoluted semantics, as if they've been brainwashed by JavaScript and C.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: