Deprecating fromIntegral

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
44 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Niklas Hambüchen
On 21/09/17 19:27, Evan Laforge wrote:
> If I were to suddenly get 10,000 lines of warnings...

If the built tool is set up sensibly (perhaps we should make it so if
that is not already possible, but I think these days warnings of
dependency packages are omitted anyway, as cabal and stack build them in
parallel), you should get (and care about and fix) only warnings about
those occurrences that are in the packages you maintain / build directly.

You are unlikely to get 10,000 warnings:

I've made a quick histogram over all of Hackage (note, this includes
lots of abanoned code)


https://gist.github.com/nh2/f45d628a81c04f95e14f14ea37d33b22#file-fromintegral-uses-png

There is also a JSON file containing counts for each packet so that you
can quickly look up how many occurrences your packages have.

Most packages have < 3 occurrences of fromIntegral, a few have < 20
occurrences. Very few have more than 20.

Assuming we go for a naming improvement and add 3 functions ala
maybeFromInteger / runtimeCheckedFromInteger / fromIntegerWrap, a
package owner would have to step through their deprecation warnings and
replace each with one of the new 3 functions to get their package
warning-free.

I estimate this to be a very minor task/effort compared to the major
changes GHC Haskell has gone through in the last years.

I could probably already have fixed 1000 of the 7000 total occurrences
on Hackage myself within the time it as taken me to debug integer
conversion related problems in GHC/base in the last week.

(In other words, these changes are cheap and have high payoff.)
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Carter Schonwald
I’m -10 in this proposal 

Every time I write a number literal I’ll now get a warning.  Cause as it hasn’t been remarked : every integer literal uses these operations afaik

The intent / spirit of this proposal is correct, the method of recourse isn’t.  

On Thu, Sep 21, 2017 at 7:20 PM Niklas Hambüchen <[hidden email]> wrote:
On 21/09/17 19:27, Evan Laforge wrote:
> If I were to suddenly get 10,000 lines of warnings...

If the built tool is set up sensibly (perhaps we should make it so if
that is not already possible, but I think these days warnings of
dependency packages are omitted anyway, as cabal and stack build them in
parallel), you should get (and care about and fix) only warnings about
those occurrences that are in the packages you maintain / build directly.

You are unlikely to get 10,000 warnings:

I've made a quick histogram over all of Hackage (note, this includes
lots of abanoned code)


https://gist.github.com/nh2/f45d628a81c04f95e14f14ea37d33b22#file-fromintegral-uses-png

There is also a JSON file containing counts for each packet so that you
can quickly look up how many occurrences your packages have.

Most packages have < 3 occurrences of fromIntegral, a few have < 20
occurrences. Very few have more than 20.

Assuming we go for a naming improvement and add 3 functions ala
maybeFromInteger / runtimeCheckedFromInteger / fromIntegerWrap, a
package owner would have to step through their deprecation warnings and
replace each with one of the new 3 functions to get their package
warning-free.

I estimate this to be a very minor task/effort compared to the major
changes GHC Haskell has gone through in the last years.

I could probably already have fixed 1000 of the 7000 total occurrences
on Hackage myself within the time it as taken me to debug integer
conversion related problems in GHC/base in the last week.

(In other words, these changes are cheap and have high payoff.)
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Herbert Valerio Riedel-3
In reply to this post by Niklas Hambüchen
...there's one minor detail I'd like to point out as it doesn't seem
to have been mentioned so far:

On Thu, Sep 21, 2017 at 5:34 PM, Niklas Hambüchen <[hidden email]> wrote:

> (Though, in practice the current `fromInteger is not partial, e.g.
> `(fromInteger 256 :: Word8) == 0` without error

That's true. However, here's something you can do already now with
recent GHCs which gives turns literal-overflows GHC is able to detect into
hard compile errors:


  $ ghci -Wall -Werror=overflowed-literals
  GHCi, version 8.2.1: http://www.haskell.org/ghc/  :? for help
  Prelude> (256 :: Data.Word.Word8) == 0

  <interactive>:1:2: warning: [-Woverflowed-literals]
      Literal 256 is out of the GHC.Word.Word8 range 0..255

  <no location info>: error:
  Failing due to -Werror.
  Prelude>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Dominic Steinitz-2
In reply to this post by Niklas Hambüchen

> On 22 Sep 2017, at 13:43, Dominic <[hidden email]> wrote:
>
> Coincidentally, I was playing with this a few days ago. I didn’t seem to have to do anything to get a warning.
>
>> GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
>> Prelude Data.Word> :m Data.Int
>> Prelude Data.Int> 0x80000000 :: Int32
>>
>> <interactive>:27:1: warning: [-Woverflowed-literals]
>>    Literal 2147483648 is out of the Int32 range -2147483648..2147483647
>>    If you are trying to write a large negative literal, use NegativeLiterals
>> -2147483648
>> Prelude Data.Int> :set -XNegativeLiterals
>> Prelude Data.Int> 0x80000000 :: Int32
>>
>> <interactive>:29:1: warning: [-Woverflowed-literals]
>>    Literal 2147483648 is out of the Int32 range -2147483648..2147483647
>> -2147483648
>
> I am not clear why it wanted me to use NegativeLiterals but still give the same warning. Does anyone understand the intent here?
>
>> Message: 1
>> Date: Fri, 22 Sep 2017 14:14:12 +0200
>> From: Herbert Valerio Riedel <[hidden email]>
>> To: Niklas Hambüchen <[hidden email]>
>> Cc: Haskell Libraries <[hidden email]>
>> Subject: Re: Deprecating fromIntegral
>> Message-ID:
>> <CAOFsArv1rDT1=[hidden email]>
>> Content-Type: text/plain; charset="UTF-8"
>>
>> ...there's one minor detail I'd like to point out as it doesn't seem
>> to have been mentioned so far:
>>
>> On Thu, Sep 21, 2017 at 5:34 PM, Niklas Hambüchen <[hidden email]> wrote:
>>
>>> (Though, in practice the current `fromInteger is not partial, e.g.
>>> `(fromInteger 256 :: Word8) == 0` without error
>>
>> That's true. However, here's something you can do already now with
>> recent GHCs which gives turns literal-overflows GHC is able to detect into
>> hard compile errors:
>>
>>
>> $ ghci -Wall -Werror=overflowed-literals
>> GHCi, version 8.2.1: http://www.haskell.org/ghc/  :? for help
>> Prelude> (256 :: Data.Word.Word8) == 0
>>
>> <interactive>:1:2: warning: [-Woverflowed-literals]
>>     Literal 256 is out of the GHC.Word.Word8 range 0..255
>>
>> <no location info>: error:
>> Failing due to -Werror.
>> Prelude>
>>
>>
>> ------------------------------
>>
>> Subject: Digest Footer
>>
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>>
>> ------------------------------
>>
>> End of Libraries Digest, Vol 169, Issue 30
>> ******************************************
>

Dominic Steinitz
[hidden email]
http://idontgetoutmuch.wordpress.com

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Niklas Hambüchen
In reply to this post by Carter Schonwald
On 22/09/17 13:30, Carter Schonwald wrote:
> I’m -10 in this proposal
>
> Every time I write a number literal I’ll now get a warning.

Hi Carter, is this true?

It was my understanding that if you deprecate a function, you get
deprecation warnings only where you make literal use of that function, e.g.

  x = 10

would not raise a deprecation because you didn't explicitly write
"fromInteger" here (and certainly not fromIntegral).

Is this not the case?

> Cause as it hasn’t been remarked : every integer literal uses these
operations afaik

Both Henning and Edward have remarked that.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Evan Laforge
In reply to this post by Niklas Hambüchen
On Thu, Sep 21, 2017 at 4:19 PM, Niklas Hambüchen <[hidden email]> wrote:
> On 21/09/17 19:27, Evan Laforge wrote:
>> If I were to suddenly get 10,000 lines of warnings...
>
> If the built tool is set up sensibly (perhaps we should make it so if
> that is not already possible, but I think these days warnings of
> dependency packages are omitted anyway, as cabal and stack build them in
> parallel), you should get (and care about and fix) only warnings about
> those occurrences that are in the packages you maintain / build directly.

I mean dependencies within the project, not external packages.  If
modify something in the middle of the dependency tree, I'll be usually
recompiling (say) a couple of hundred modules, for my personal
medium-ish project.  I assume in a real company with a larger codebase
you could easily be recompiling thousands.  Maybe just the mono-repo
ones though.

Also I'm assuming most code is not in packages, and is not in hackage.
I have no real basis for that, other than experience with other
languages.  But, as shown below, my guesses can be pretty wrong:

> Most packages have < 3 occurrences of fromIntegral, a few have < 20
> occurrences. Very few have more than 20.
>
> Assuming we go for a naming improvement and add 3 functions ala
> maybeFromInteger / runtimeCheckedFromInteger / fromIntegerWrap, a
> package owner would have to step through their deprecation warnings and
> replace each with one of the new 3 functions to get their package
> warning-free.

I'm surprised about that, I assumed more.  Grepping for fromIntegral
in a local project, I get 259 occurrences over 693 modules... I
expected a lot more.

However, a lot of those I think would be false positives, because
they're converting across newtypes, where the underlying type is the
same.  I'm not sure what I would use for those... I guess it would be
fromIntegerWrapped, but it's kind of verbose and awkward and is
implying wrapping when it's not actually present.  Maybe they should
be using 'coerce'?  Most of them existed before coerce did, but that's
not an excuse any more.  I think I'd be more likely to try out
int-cast.

> I could probably already have fixed 1000 of the 7000 total occurrences
> on Hackage myself within the time it as taken me to debug integer
> conversion related problems in GHC/base in the last week.
>
> (In other words, these changes are cheap and have high payoff.)

Of course that's the bottom line, so if it's the case then it's hard
to argue against.

I've had similar bugs due to sloppy haskell -> C FFI conversions so
I'm sympathetic to the idea.  It's just a blanket deprecation on
fromIntegral seems like a broad brush.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

amindfv
In reply to this post by John Wiegley-2


El 21 sept 2017, a las 18:01, John Wiegley <[hidden email]> escribió:

>>>>>> "NH" == Niklas Hambüchen <[hidden email]> writes:
>
> NH> Because `fromIntegral` is not a partial function, it fails silently.
>
> Ah, yes, I didn't mean "partial" per se, but more in the sense of "not having
> a sane answer for all inputs".
>
> I'm -1 to changing the behavior of fromIntegral now, but +1 on adding other
> functions to make the behavior more explicit.
>

This is my view. I am specifically against adding a {-# DEPRECATED #-} pragma.

Tom

> --
> John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
> http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Henning Thielemann
In reply to this post by Evan Laforge

On Fri, 22 Sep 2017, Evan Laforge wrote:

> However, a lot of those I think would be false positives, because
> they're converting across newtypes, where the underlying type is the
> same.  I'm not sure what I would use for those... I guess it would be
> fromIntegerWrapped, but it's kind of verbose and awkward and is
> implying wrapping when it's not actually present.  Maybe they should
> be using 'coerce'?

Why not just use the newtype constructor or field accessor for packing and
unpacking? Usually I wrap Ints in newtypes for identifiers. Identifiers
should not support Num arithmetic and thus would not allow fromIntegral
anyway.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Henning Thielemann
In reply to this post by Evan Laforge

On Fri, 22 Sep 2017, Evan Laforge wrote:

> I've had similar bugs due to sloppy haskell -> C FFI conversions so I'm
> sympathetic to the idea.  It's just a blanket deprecation on
> fromIntegral seems like a broad brush.

I assume that conversion causes problems depending on the architecture.
E.g. Int -> CInt might be a lossless conversion on a 32-bit architecture
and lossy on 64-bit.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Thomas Jakway
In reply to this post by Niklas Hambüchen
I can see both sides of this and am dismayed.  On the one hand, -Wall
literally means with all warnings--so it makes sense to pack as many
warnings as possible into it.  If that's too many warnings for the end
user, they can disable individual ones when looking through the output.  
If we wanted to be really thorough we could provide a suggestion at the
end of the output ("90% of your warnings are from ____").  On the other
hand,

grep -I -R --include="*.hs" "fromIntegral" | wc -l

on ghc prints 2598, which is a lot.

For what it's worth I'm in favor of adding it to -Wall because I would
rather be warned about too many things and have to force myself not to
ignore them than spend a long time figuring out the source of a bug.  At
the very least when I do encounter a bug it'll give me somewhere to start.

There's no great solution here, only tradeoffs.  I won't lose any faith
in Haskell whichever route we take.

On 09/22/2017 02:53 PM, Evan Laforge wrote:
 > On Thu, Sep 21, 2017 at 4:19 PM, Niklas Hambüchen <[hidden email]> wrote:
 >> On 21/09/17 19:27, Evan Laforge wrote:
 >>> If I were to suddenly get 10,000 lines of warnings...
 >> If the built tool is set up sensibly (perhaps we should make it so if
 >> that is not already possible, but I think these days warnings of
 >> dependency packages are omitted anyway, as cabal and stack build them in
 >> parallel), you should get (and care about and fix) only warnings about
 >> those occurrences that are in the packages you maintain / build
directly.
 > I mean dependencies within the project, not external packages.  If
 > modify something in the middle of the dependency tree, I'll be usually
 > recompiling (say) a couple of hundred modules, for my personal
 > medium-ish project.  I assume in a real company with a larger codebase
 > you could easily be recompiling thousands.  Maybe just the mono-repo
 > ones though.
 >
 > Also I'm assuming most code is not in packages, and is not in hackage.
 > I have no real basis for that, other than experience with other
 > languages.  But, as shown below, my guesses can be pretty wrong:
 >
 >> Most packages have < 3 occurrences of fromIntegral, a few have < 20
 >> occurrences. Very few have more than 20.
 >>
 >> Assuming we go for a naming improvement and add 3 functions ala
 >> maybeFromInteger / runtimeCheckedFromInteger / fromIntegerWrap, a
 >> package owner would have to step through their deprecation warnings and
 >> replace each with one of the new 3 functions to get their package
 >> warning-free.
 > I'm surprised about that, I assumed more.  Grepping for fromIntegral
 > in a local project, I get 259 occurrences over 693 modules... I
 > expected a lot more.
 >
 > However, a lot of those I think would be false positives, because
 > they're converting across newtypes, where the underlying type is the
 > same.  I'm not sure what I would use for those... I guess it would be
 > fromIntegerWrapped, but it's kind of verbose and awkward and is
 > implying wrapping when it's not actually present.  Maybe they should
 > be using 'coerce'?  Most of them existed before coerce did, but that's
 > not an excuse any more.  I think I'd be more likely to try out
 > int-cast.
 >
 >> I could probably already have fixed 1000 of the 7000 total occurrences
 >> on Hackage myself within the time it as taken me to debug integer
 >> conversion related problems in GHC/base in the last week.
 >>
 >> (In other words, these changes are cheap and have high payoff.)
 > Of course that's the bottom line, so if it's the case then it's hard
 > to argue against.
 >
 > I've had similar bugs due to sloppy haskell -> C FFI conversions so
 > I'm sympathetic to the idea.  It's just a blanket deprecation on
 > fromIntegral seems like a broad brush.
 > _______________________________________________
 > Libraries mailing list
 > [hidden email]
 > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

David Feuer
In reply to this post by Niklas Hambüchen
I'm -1 on deprecating it, and +1 on adding additional conversion functions of various sorts: explicit widening, explicit narrowing, etc.

On Sep 21, 2017 8:25 AM, "Niklas Hambüchen" <[hidden email]> 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
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Andrew Martin
In reply to this post by Niklas Hambüchen
I'm -1 on deprecating this, but I would like to see the docs warn about its behavior.

On Thu, Sep 21, 2017 at 8:24 AM, Niklas Hambüchen <[hidden email]> 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
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries



--
-Andrew Thaddeus Martin

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Niklas Hambüchen
In reply to this post by David Feuer
Hey David,

> I'm -1 on deprecating it, and +1 on adding additional conversion
> functions of various sorts: explicit widening, explicit narrowing, etc.

What is your reasoning against deprecating it?

That `fromIntegral` is a function that should be used in new code?
That emitting a warning for potentially wrong code is bad by itself?
Or that people have to change their code to be warning free?

To me, a deprecation constitutes an organised, non-disruptive migration
from the old function to the new explicit functions, and I'd really like
to understand what people's reservations against it are.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Edward Kmett-2
To me deprecation is a big deal, especially for something exported from Prelude and which has been around since before Haskell 98, when we simply do not have a clear migration path for users at this point.

The way I see it there are several gates between this proposal and any actual deprecation of fromIntegral.

1. At present there is no story here for how users change their code to address the deprecation. They'd just get to stare at a -Wall full of warnings and have no migration path.

2. To start a deprecation process here I'd at the very least want to have a replacement that a decent cross-section of folks have been able to agree is an improvement. This could be packaged up independently, could be selected from among other solutions that folks have already packaged up, etc. I don't care where it comes from so long as you can get enough people agree that it is the right solution.

3. Build consensus to move it into base. That way to address any eventual deprecation there can be a road map that doesn't incur new dependencies for users.

4. Then once it has been around in base long enough that users can migrate to it in accordance to the "3 Release Policy" then we could build consensus to perform a deprecation of the existing method.

This is unfortunately a relatively slow and tedious process, but the alternative is a Prelude-affecting change that breaks our release policies and all of the books being made with no real notice. 

The current usage pattern and policies we have around deprecations isn't to use them as the first notice of "hey you might want to do something else", but rather to catch folks on the tail end right before something gets removed and long after what the user should do to in response has been carefully documented and considered.

At least it seems to me that this is a large part of the resistance you are encountering here.

-Edward

On Tue, Sep 26, 2017 at 11:08 AM, Niklas Hambüchen <[hidden email]> wrote:
Hey David,

> I'm -1 on deprecating it, and +1 on adding additional conversion
> functions of various sorts: explicit widening, explicit narrowing, etc.

What is your reasoning against deprecating it?

That `fromIntegral` is a function that should be used in new code?
That emitting a warning for potentially wrong code is bad by itself?
Or that people have to change their code to be warning free?

To me, a deprecation constitutes an organised, non-disruptive migration
from the old function to the new explicit functions, and I'd really like
to understand what people's reservations against it are.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

David Feuer
 I would double down on the "no one has a great replacement yet".
There are several (potential, imaginary) replacements that may be
better in different contexts, depending on the precise programmer
intent. And then there's the question of how far we want to push
(relatives of) a function that doesn't really seem like entirely the
right idea. Completely aside from correctness issues, fromIntegral
also has efficiency trouble: it is completely dependent on
hand-written rewrite rules to avoid serious inefficiencies. A version
based on MultiParamTypeClasses would inspire much more confidence--but
it would require instances out the wazoo and surely lead to many
orphan instances. I suspect there are ways we can get better results
with fewer problems by designating several different intermediate
types and allowing Integral instances to place themselves in relation
to those. But that is ad hoc, and it requires one or more language
extensions, and I don't know if anyone's really played with it enough.
We shouldn't even be thinking about deprecation in the short term; we
should be working toward a medium-term replacement and a
very-long-term *potential* deprecation.

On Tue, Sep 26, 2017 at 12:41 PM, Edward Kmett <[hidden email]> wrote:

> To me deprecation is a big deal, especially for something exported from
> Prelude and which has been around since before Haskell 98, when we simply do
> not have a clear migration path for users at this point.
>
> The way I see it there are several gates between this proposal and any
> actual deprecation of fromIntegral.
>
> 1. At present there is no story here for how users change their code to
> address the deprecation. They'd just get to stare at a -Wall full of
> warnings and have no migration path.
>
> 2. To start a deprecation process here I'd at the very least want to have a
> replacement that a decent cross-section of folks have been able to agree is
> an improvement. This could be packaged up independently, could be selected
> from among other solutions that folks have already packaged up, etc. I don't
> care where it comes from so long as you can get enough people agree that it
> is the right solution.
>
> 3. Build consensus to move it into base. That way to address any eventual
> deprecation there can be a road map that doesn't incur new dependencies for
> users.
>
> 4. Then once it has been around in base long enough that users can migrate
> to it in accordance to the "3 Release Policy" then we could build consensus
> to perform a deprecation of the existing method.
>
> This is unfortunately a relatively slow and tedious process, but the
> alternative is a Prelude-affecting change that breaks our release policies
> and all of the books being made with no real notice.
>
> The current usage pattern and policies we have around deprecations isn't to
> use them as the first notice of "hey you might want to do something else",
> but rather to catch folks on the tail end right before something gets
> removed and long after what the user should do to in response has been
> carefully documented and considered.
>
> At least it seems to me that this is a large part of the resistance you are
> encountering here.
>
> -Edward
>
> On Tue, Sep 26, 2017 at 11:08 AM, Niklas Hambüchen <[hidden email]> wrote:
>>
>> Hey David,
>>
>> > I'm -1 on deprecating it, and +1 on adding additional conversion
>> > functions of various sorts: explicit widening, explicit narrowing, etc.
>>
>> What is your reasoning against deprecating it?
>>
>> That `fromIntegral` is a function that should be used in new code?
>> That emitting a warning for potentially wrong code is bad by itself?
>> Or that people have to change their code to be warning free?
>>
>> To me, a deprecation constitutes an organised, non-disruptive migration
>> from the old function to the new explicit functions, and I'd really like
>> to understand what people's reservations against it are.
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Niklas Hambüchen
In reply to this post by Edward Kmett-2
Hey Edward and David,

Edward Kmett wrote:
> 1. [...] no migration path.
> 2. To start a deprecation process here I'd at the very least want to
> have a replacement that a decent cross-section of folks have been able
> to agree is an improvement

I agree, as stated before, deprecation without replacement makes no sense.

It's the point of this thread to

* determine what replacements people would consider good
* find if, assuming we have found good replacements, there would be
still other obstacles (such as the ones you mention below)

So far, it seems that there is broad support for more appropriately
named functions while a type-based approach is controversial; I consider
this a useful outcome of this thread, and think that this is also the
approach that can provide the easiest migration path.

> 4. Then once it has been around in base long enough that users can
> migrate to it in accordance to the "3 Release Policy"
> <https://prime.haskell.org/wiki/Libraries/3-Release-Policy> then we
> could build consensus to perform a deprecation of the existing method.

Waiting for 3 releases seems fine.
But I don't see why consensus could only be built after that.

It seems that if consensus exists already at a time before, deprecation
can be planned ahead of time.
The linked page contains examples of that, e.g. the deprecation of
`Monad.fail` that is already scheduled for 8.6.

> The current usage pattern and policies we have around deprecations isn't
> to use them as the first notice of "hey you might want to do something
> else", but rather to catch folks on the tail end right before something
> gets removed and long after what the user should do to in response has
> been carefully documented and considered.

That's a good point; are there reasons why we should not use
deprecations for both patterns ("hey you might want to do something
else" and "this is your last notice")?

If yes, maybe we should add means to support the first pattern.

That goes along with another thought:

The fact that the 3-release-policy says that warnings cannot be added
even for -Wall means that currently there is no flag one can use to get
all of the "latest" warnings GHC can produce to make code safer and more
correct.
Perhaps a -Wextra equivalent is needed?

(Personally I find it unfortunate to have a flag called -Wall not emit
all warnings, or it complaining about benign topics like unused imports
while letting data corruption pass unnoticed for long, or an
off-by-default flag intended to produce as many warnings as possible to
be restricted by a backwards compatibility policy, but C compilers at
least make these a common occurrence.)

> At least it seems to me that this is a large part of the resistance you
> are encountering here.

Thanks for the insights, very appreciated.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

David Feuer
On Tue, Sep 26, 2017 at 2:49 PM, Niklas Hambüchen <[hidden email]> wrote:

> It seems that if consensus exists already at a time before, deprecation
> can be planned ahead of time.
> The linked page contains examples of that, e.g. the deprecation of
> `Monad.fail` that is already scheduled for 8.6.

David Luposchainsky drafted the MonadFail proposal in December 2013,
nearly four years ago. But that's not the beginning of the story. In
November 2009, Michael Snoyman wrote, in
https://wiki.haskell.org/index.php?title=Failure&oldid=31465,

> Fail is referring to the "fail" function, which is part of the Monad typeclass and is almost universally despised.

And that's not the beginning of the story either. By March 2008, Real
World Haskell http://book.realworldhaskell.org/read/monads.html
warning about fail. I don't have the history of the text, but it
currently reads, in a giant warning box,

> Beware of fail
>
> Many Monad instances don't override the default implementation of fail that we show here, so in those monads, fail uses error. Calling error is usually highly undesirable, since it throws an exception that callers either cannot catch or will not expect. Even if you know that right now you're executing in a monad that has fail do something more sensible, we still recommend avoiding it. It's far too easy to cause yourself a problem later when you refactor your code and forget that a previously safe use of fail might be dangerous in its new context.

In a comment on the text in March 2008, Lennart Augustssen wrote

> The fail function has no business being in the monad class at all, and it should be removed. So I think you should just discourage people from using it in general.

and the next month Cale Gibbard stated

> [Most] monads can't implement it sensibly, and it's not actually part of the definition of a monad.
>
> The fail function was just a hack to make the do-notation translation as described in the Report "simpler", but it really belongs in a separate typeclass, something more along the lines of the way that Haskell 1.4 did it.

Beginning in February 2008, as
https://stackoverflow.com/questions/8163852/should-i-avoid-using-monad-fail
points out, there was a thread,
http://haskell.1045720.n5.nabble.com/Proposal-Add-Text-Read-maybeRead-Read-a-gt-String-gt-Maybe-a-td3174167.html,
in which several luminaries spoke out, explicitly or implicitly,
against fail being in Monad.

So it seems that there was a fairly clear consensus that having fail
in Monad was a bad idea almost ten years ago, and that it would be
better to put it in a subclass. It's a bit hard to compare that to the
case of fromIntegral, which I think people have generally been only
mildly uncomfortable with, and when we don't know if there is anything
sufficiently better!
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Bardur Arantsson-2
In reply to this post by Niklas Hambüchen
On 2017-09-26 20:49, Niklas Hambüchen wrote:
> Hey Edward and David,
>
>
> The fact that the 3-release-policy says that warnings cannot be added
> even for -Wall means that currently there is no flag one can use to get
> all of the "latest" warnings GHC can produce to make code safer and more
> correct.
> Perhaps a -Wextra equivalent is needed?
>

This is called -Weverything in Clang-land.

AFAICT it was introduced because it does imply some warnings that are
ridiculously easy to trigger accidentally, and so you don't to run it
along with e.g. -Werror. Obviously you don't want -Werror on anything
you release to the world, but it can be useful to use "-Weverything" +
"-Werror" for local development. The idea is that you get literally
every warning that the compiler developers can think of and then have to
selectively turn off individual warnings. This squares pretty well with
the
'deprecation-before-we-have-replacements-because-you-can-provide-your-own'
narrative, at least.

> (Personally I find it unfortunate to have a flag called -Wall not emit
> all warnings, or it complaining about benign topics like unused imports
> while letting data corruption pass unnoticed for long, or an
> off-by-default flag intended to produce as many warnings as possible to
> be restricted by a backwards compatibility policy, but C compilers at
> least make these a common occurrence.)
>

I think ship has sailed on naming, but a "-Weverything" might be very
useful, I think.

(A "-Wfuture-deprecation" or similar might be warranted too, and should
probably be included in "-Weverything".)

Regards,

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Deprecating fromIntegral

Bardur Arantsson-2
On 2017-09-26 22:56, Bardur Arantsson wrote:
>
> I think ship has sailed on naming, but a "-Weverything" might be very
> useful, I think.

Sorry, that was a brain fart. There *is* a -Weverything these days.

>
> (A "-Wfuture-deprecation" or similar might be warranted too, and should
> probably be included in "-Weverything".)
>

This might still be relevant.

Regards,

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Monad.fail, was Re: Deprecating fromIntegral

Jacques Carette
In reply to this post by David Feuer
And pre-dating all of that was a little noticed paper

http://www.cas.mcmaster.ca/~kahl/Publications/Conf/Kahl-Carette-Ji-2006a.html

with a semantics that shows that "pattern matching" is an effect, and
how to couple that effect with other effects.  It explains the choices
one sees out there 'in the wild' and augments that with many new options.

Jacques

@InProceedings{Kahl-Carette-Ji-2006a,
   author = {Wolfram Kahl and Jacques Carette and Xiaoheng Ji},
   title = {Bimonadic Semantics for Basic Pattern Matching Calculi},
   crossref =  {MPC2006},
   pages = {253--273}
}

@Proceedings{MPC2006,
   title = {Mathematics of Program Construction, {MPC 2006, Kuressaare, Estonia}},
   booktitle = {Mathematics of Program Construction, {MPC 2006}},
   editor = {Tarmo Uustalu},
   year = 2006,
   publisher = Springer,
   series = LNCS,
   volume = {4014},
   URL = {http://link.springer.de/link/service/series/0558/tocs/t4014.htm}
}


On 2017-09-26 03:46 PM, David Feuer wrote:

> On Tue, Sep 26, 2017 at 2:49 PM, Niklas Hambüchen <[hidden email]> wrote:
>
>> It seems that if consensus exists already at a time before, deprecation
>> can be planned ahead of time.
>> The linked page contains examples of that, e.g. the deprecation of
>> `Monad.fail` that is already scheduled for 8.6.
> David Luposchainsky drafted the MonadFail proposal in December 2013,
> nearly four years ago. But that's not the beginning of the story. In
> November 2009, Michael Snoyman wrote, in
> https://wiki.haskell.org/index.php?title=Failure&oldid=31465,
>
>> Fail is referring to the "fail" function, which is part of the Monad typeclass and is almost universally despised.
> And that's not the beginning of the story either. By March 2008, Real
> World Haskell http://book.realworldhaskell.org/read/monads.html
> warning about fail. I don't have the history of the text, but it
> currently reads, in a giant warning box,
>
>> Beware of fail
>>
>> Many Monad instances don't override the default implementation of fail that we show here, so in those monads, fail uses error. Calling error is usually highly undesirable, since it throws an exception that callers either cannot catch or will not expect. Even if you know that right now you're executing in a monad that has fail do something more sensible, we still recommend avoiding it. It's far too easy to cause yourself a problem later when you refactor your code and forget that a previously safe use of fail might be dangerous in its new context.
> In a comment on the text in March 2008, Lennart Augustssen wrote
>
>> The fail function has no business being in the monad class at all, and it should be removed. So I think you should just discourage people from using it in general.
> and the next month Cale Gibbard stated
>
>> [Most] monads can't implement it sensibly, and it's not actually part of the definition of a monad.
>>
>> The fail function was just a hack to make the do-notation translation as described in the Report "simpler", but it really belongs in a separate typeclass, something more along the lines of the way that Haskell 1.4 did it.
> Beginning in February 2008, as
> https://stackoverflow.com/questions/8163852/should-i-avoid-using-monad-fail
> points out, there was a thread,
> http://haskell.1045720.n5.nabble.com/Proposal-Add-Text-Read-maybeRead-Read-a-gt-String-gt-Maybe-a-td3174167.html,
> in which several luminaries spoke out, explicitly or implicitly,
> against fail being in Monad.
>
> So it seems that there was a fairly clear consensus that having fail
> in Monad was a bad idea almost ten years ago, and that it would be
> better to put it in a subclass. It's a bit hard to compare that to the
> case of fromIntegral, which I think people have generally been only
> mildly uncomfortable with, and when we don't know if there is anything
> sufficiently better!
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
123