
Hi On 2 Sep 2011, at 16:34, Brandon Allbery wrote:
I hope I am misunderstanding this....
I wrote:
I agree that such a scenario is possible. The present situation gives no choice but to do things badly, but things often get done badly the first time around anyway. Perhaps I'm just grumpy, but I think we should aim to make bad practice erroneous where practicable. Once the mistake is no longer forced upon us, it becomes a mistake that deserves its penalty in labour. Silent pre-emption is bad practice and
with the response:
So, when the whole point is that an unfortunate design years ago can't be reasonably fixed without rewriting massive amounts of code, the only correct answer is to rewrite massive amounts of code?
I'm not sure what you're asking here. Of course we should compare the pain of the treatment with that of the symptoms.
Especially when the original proposal was put forward *specifically to avoid* rewriting massive amounts of code?
Which original proposal? How does it avoid rewriting code?
Yes, we'd love a perfect world. We don't have one. That's the *point*.
Recall that Option 2 resolves the duplicate superclass instances in favour of an explicit prior instance, but issues a warning (which should offer the data to choose between explicit resolutions). That deals with a chunk of the legacy scenario (although it doesn't handle the situation where some M is made a Monad in one module and made Applicative in a later module, which is possible (common, even?) because Applicative is not currently a superclass of Monad). If we make one existing class a superclass of another existing class, some disruption is inevitable: we can try to minimize that disruption, but we can't eliminate it entirely. For another example, if some F is made Applicative and Traversable in the same module, which default Functor instance pre-empts the other? We should question whether the disruption of even Option 2/3 makes it worth adding default superclass instances at all. Maybe, depressingly, we've reached the can't-fix-it stage. It would be good to get some data. It's also worth considering tools to support migration, using the diagnostics generated by warnings. If it is worth adding default superclass instances, Option 2 looks like a crucial disruption-minimizing expedience, while we have a legacy of newly extraneous instances to deal with. As far as "an unfortunate design years ago" is concerned, we should be careful to minimize the amount of rewriting required. If that minimum is still too much, we'd better not go there. I'm in favour of moving to Option 1 eventually, as somehow the better choice for code comprehension. But I can see reasons to resist the changeover: * too much unmigrated code still relying on pre-emption under Option 2; * new instances of the old problem (an existing S is suddenly made a superclass of an existing C, with a default S instance for C) come into being, The former is a real risk, but hopefully with a finite lifespan. It would be too costly to switch from a warning to an error while too much code relies on the deprecated practice. Please don't imagine I'm in favour of that. The latter, however, requires us to be a bit dim in a way which was certainly not in evidence when most of the current motivating examples arose. In the legacy code (Monad-Applicative-Functor, Traversable-Foldable-Functor), we've had to choose between two bad options, but the candidate superclass-with-default-implementation has usually been evident. I'm sure we're capable of being that dim. I'm also sure we're capable of screwing up by writing an instance and assuming we get the default superclass instance we expect, without noticing that someone else's chunk of the codebase pre-empts it. I'd be troubled if someone knackered my applicative- style use of Monad [] by adding a zipping Applicative [], or even an instance which appeared to have the same functionality but also did some sneaky unsafePerformIO badness. That's an example of the risk we take by allowing pre-emption. We have to balance the risk of going back and resolving duplicates with the risk of bugs caused by code meaning less than it says. So, are default superclass instances just too disruptive? All the best Conor PS We'd love a perfect world. We don't have one. That's why we change things.