
On Thu, 21 Sep 2017, Niklas Hambüchen wrote:
It is a bit funny how we argue that Haskell is good for high assurance programming, and we build all sorts of fancy constructs to eliminate more run-time errors, when in fact we do worse than C in detecting errors in the most basic types a computer can use, such as converting between 64-bit and 32-bit integers.
That's all very true! Other safety oriented languages like Modula-3 at least perform a runtime check on integer conversion. However, I'd like to see practical solutions first before adding deprecations. fromInteger will always be partial when converting to a fixed width integer. fromInteger is used for converting number literals to the wanted type. Thus every number literal will issue a warning and I cannot see how to circumvent this. Another problem I see is that integralUpsize and integralDownsize are not Haskell 98 and multi-parameter type classes are not really satisfying here because you have to define n^2 instances for n types. A convenient conversion function would certainly need even more advanced types, e.g. type-level comparison of bit widths. If we have fixed fromIntegral then the next natural question would arise: How to protect arithmetic operations plus, minus, times against overflow? Aren't overflows as dangerous as losing bits on integer conversion? Is there a solution that works both for conversion and arithmetics? For now the least invasive solution would be to provide a partial integer conversion function.
So I propose that we add a deprecation pragma to `fromIntegral` (however, keeping it forever, like Java does, as there's no benefit to removing it, we just want that people use safer functions over time), and instead provide a `safeFromIntegral` that can only widen ranges, and one or more `unsafeFromIntegral` or appropriately named functions that can error, wrap, return Maybe, or have whatever desired behaviour when the input value doesn't fit into the output type.
As always, I object to use the terms 'safe' and 'unsafe' when actually 'total' and 'partial' are meant. LLVM uses 'ext' and 'trunc'. I'd prefer names along these lines.