I'm -1 on this proposal.

fromInteger and fromIntegral are a huge part of our ecosystem. They comprise a large part of the difference between how we handle numeric literals and how literally every other language on the planet handles numeric literals. fromIntegral shows up all over the place in any code that is even remotely mathematical to deal with converting between integer indices and other numeric types for computation.

If we pretend Num is about working with rings fromInteger provides the canonical ring homomorphism from Z into every ring, so that half of the equation has to remain in place. toInteger is Integral reason for existence, so you're just asking the existing users to replace fromIntegral with 'fromInteger . toInteger' do dodge a warning that doesn't come with any other clear explanation about how to fix.

Any properly replacement requires language extensions such as multi parameter type classes that we've failed to demonstrate an ability to standardize as well as n^2 instances and makes it difficult to convert between integral types and numbers supplied by different packages.

Now, if you wanted to write a package that provided widening and shrinking conversions and this gradually was picked up by a larger and larger cross section of the community and more organically worked its way into base that'd be one thing, but these nicer safe conversions haven't yet been adopted by any significant fraction of the community at this point, so any form of deprecation is very much premature.

On the other hand I'm definitely +1 on adding documentation to hWaitForInput or on fromIntegral about how you should be careful when switching between numeric types of different sizes.

-Edward

On Thu, Sep 21, 2017 at 8:24 AM, Niklas Hambüchen <mail@nh2.me> wrote:
This is not a joke.

I just found a bug in base (https://ghc.haskell.org/trac/ghc/ticket/14262):

  import System.IO
  hWaitForInput stdin 4294968296

This code should wait for 49.something days, but it waits for 1 second.

It is caused by a quick use of `fromIntegral` to "convert" `Int -> CInt`
(where CInt = Int32), causing an overflow.

I argue that `fromIntegral` causes unnoticed data corruption without any
warning, and thus are worse than partial functions.

In this case, this data corruption occurs in the most fundamental code
that we all use and have to rely upon (`base`).

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.

For some inspiration, `foundation` provides ideas in that direction:

http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-From.html
http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-IntegralConv.html

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.

Let's fix that.

It avoids real problems in real production systems that are difficult to
debug when they happen (who writes a unit test checking that a timeout
of 50 days still works? This is the kind of stuff where you have to rely
on -- very basic -- types).

I'd like to probe support for such a change before doing any work on it.

Niklas
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries