<div dir="ltr"><div dir="ltr"></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 10, 2020 at 12:15 AM Bardur Arantsson <<a href="mailto:spam@scientician.net">spam@scientician.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Why would a massive overhaul be necessary for deprecation? If that's the<br>
case then there's a deeper more serious underlying issue around<br>
deprecation, IMO.<br></blockquote><div><br>Deprecation would at a minimum first require us to offer an alternative, let that percolate through code that uses base and only then apply the deprecation pragma under the 3 release policy. Otherwise there isn't a path for users to write code that compiles without warnings without pragmas.<br><br>Keep in mind fromIntegral is a Haskell Report facing change, so it is the sort of thing that the CLC tends to hold to a higher bar still. Changes to it will per force invalidate a lot of training material. I'm not really weighing in on if this is a good or a bad change with that, just that there is a non-trivial amount of process to enacting it if the community does decide to move forward. That isn't "a serious underlying issue", so much as establishing a baseline of stability and usability.<br><br>I'm personally +1 on the <i>idea</i> that it'd be good to find a solution that allows you to safely identify whether you want a coercion that can truncate or not. <br><br>The issue re-raised is a good one. But I don't happen to like the solution that was offered when the corpse of this issue was disinterred.<br><br>Now for where I think this proposal at least insofar as it references a concrete plan of attack falls down, fromIntegral leans on toInteger and fromInteger as a common intermediary. This allows O(n) instances where the modules linked by Niklas would require O(n^2). But it is even worse than that. As a library author I don't need to know your integral type to be able to fromIntegral from mine to yours today, but I really would in a world where that became unavailable. Both of the modules linked use fundep-less multi-parameter typeclasses, which means type inference for them is terrible, (and even in the single parameter type class case we have, remember, with Num, defaulting can kick in, we're even farther removed from such a safety net here) and instances will easily accidentally overlap the moment you go to define something like From a (Forward a), making this problem even worse for any non-trivial numeric type. <br><br>So in light of that I'm personally strongly -1 on the concrete set of actions being proposed untless a decent API can be found that scales, doesn't have those problems, and could be written into something like a Haskell Report without dipping into language extensions we haven't formalized in a Report.<br><br>That isn't to say there isn't some variant of a proposal that can't be found, but I'm having a hard time satisfying all the constraints that a Prelude facing change really should meet. <br><br>Now, that isn't to say something can't be done, for instance, weaker compromises like providing a module in base with safer casts and the like could perhaps use whatever language extensions were suited to the task, as there you have a lot more freedom to use more modern Haskell. <br><br>But even there I'd still like to see a way that factors the O(n^2) cases into O(n) and which doesn't block any decently polymorphic numeric types behind overlapping instances and don't make type inference go to hell.<br><br>So, let's see if we can't find a proposal that doesn't violate the gauntlet of constraints imposed above. Off the cuff:<br><br>Add a variant of fromInteger to Num that returns Maybe a.<div><br>class Num a where<br> ...<br> fromIntegerMaybe :: Integer -> Maybe a<br> fromIntegerMaybe a = Just (fromInteger a)<br><br>Modify the existing instances of Num to implement this extra member, and having it return Nothing if the Integer is out of bounds.<br><br>As a concrete point in the proposal design space, keep the existing fromInteger/fromIntegral as a wrapping conversion. Why? It dodges the Haskell Report change. Others might disagree. I'm just trying to offer fuel for the debate that takes it in a productive direction.</div><div><br></div><div>fromIntegralMaybe :: (Integral a, Num b) => a -> Maybe b</div><div>fromIntegralMaybe = fromIntegerMaybe . toInteger<br><br>can now be used for safe conversions.<br><br>There are 3 target semantics one might reasonably want to see in their code:</div><div><br></div><div>1.) Wrapping (existing fromIntegral)<br>2.) throwing an exception on overflow (via some wrapping combinator that just handles the above Maybe)<br>3.) Return Nothing so the error can be handled in pure code. <br><br>Each can be build on top of fromIntegral and fromIntegralMaybe.<br><br>Room for variation: <br><br>* fromIntegralMaybe could be switched to something like Integer -> Either String a, which would let you give back an error message saying why you didn't like the Integer. <br><br>* fromIntegralWrapped could be added explicitly, and then after a suitable period fromIntegral could be deprecated, but this would require an annoying dance where users would have to switch what they define, which is non-trivial to the point of ner impossibility under the 3 release policy, so I'd personally not go that way, but hey, it is not my call.<br><div><br>* Shorter names might be nice. fromIntegral is long enough that we get mocked by other language communities. Adding more words to the combinator name here compounds that issue.<br><br>I mention this because something along these lines would address the substance of the issue here without inducing the horrible unusability that I feel the concrete proposal offered here would create.<br><br></div></div>-Edward </div></div></div>