<p dir="ltr">I believe that a way to avoid orphan instances without needing huge modules (such as my instance declaration idea) would help a lot in this regard, long term—the smaller modules are, the less trouble changes cause and the better a system you propose can work.</p>
<div class="gmail_quote">On Feb 26, 2015 8:36 AM, "Joachim Breitner" <<a href="mailto:mail@joachim-breitner.de">mail@joachim-breitner.de</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
= Introduction (can be skipped) =<br>
<br>
Recently, I find myself often worried about stability of our ecosystem –<br>
may it be the FTP discussion, or the proposed¹ removal of functions you<br>
shouldn’t use, like fromJust. While all that makes our language and base<br>
libraries nicer, it also means that my chances that code from 3 or 4<br>
years ago will compile without adjustment on newer compilers are quite<br>
low.<br>
<br>
Then I remember that a perl based webpage that I wrote 12 years ago just<br>
keeps working, even as I upgrade perl with every Debian stable release,<br>
and I’m happy about that. It makes me wonder if I am ever going to<br>
regret using Haskell because there, I’d have to decide whether I want to<br>
invest time to upgrade my code or simply stop using it.<br>
<br>
I definitely do not want to stop Haskell from evolving. Maybe we can<br>
make a more stable Haskell experience opt-in? This is one step in that<br>
direction, solving (as always) only parts of the problem.<br>
<br>
= The problem =<br>
<br>
One problem is that our central library "base" is both an implementation<br>
and an interface. As the implementation is tied to the compiler, and the<br>
interface comes with the implementation, you cannot upgrade one without<br>
the other.<br>
<br>
= My solution: frozen-base =<br>
<br>
My solution would be to provide a new library, let’s call it<br>
frozen-base, which decouples the interface (frozen-base) from the<br>
implementation (still base).<br>
<br>
We would start with one particular version of base, say, 4.6. With<br>
GHC-7.6 (which comes with base 4.6), frozen-base would simply re-export<br>
its modules². On newer compilers and newer versions of base, it would<br>
re-create the old interface using CPP. So if your program depends on<br>
frozen-base only, you can expect it to compile with newer versions of<br>
GHC – achievement unlocked.<br>
<br>
= How to get new features, then? =<br>
<br>
But does that mean that you do not get to use great new functionality in<br>
later versions of base, such as Data.Bool.bool? No: When a new version<br>
of base gets released, and a module gets changed, than frozen-base will<br>
ship a _new_ module, named<br>
        Data.Bool1<br>
that matches that interface. The next change in base causes yet another<br>
module to be created, i.e.<br>
        Data.Bool2<br>
So if you need to use Data.Bool.bool, in one of your modules, you simply<br>
change the import from "import Data.Bool" to "import Data.Bool2", adjust<br>
your code to the new interface, and are ready to go. Note that you only<br>
had to adjust to the changes in Data.Bool, nothing else. Note that you<br>
also had to touch only a single module in your program, the others still<br>
use whatever interface they were using.<br>
<br>
Your dependency on frozen-base would have to indicate a lower version<br>
bound, i.e. specify the lowest version that has all the Data.Bool<n><br>
variants that you desire, but – by design – never an upper version.³<br>
<br>
= When does it not work? =<br>
<br>
Of course, the promises by froze-base are not absolute: There are<br>
changes in base that frozen-base cannot protect you against: Data type<br>
changes, some type class changes, type class instances. I don’t have any<br>
great ideas here, but maybe they are rare enough so that frozen-base is<br>
still useful.<br>
<br>
= What about the Prelude? =<br>
<br>
I did not talk about the Prelude. There probably is not a good solution,<br>
and I’d simply leave the Prelude frozen. Maybe later GHC has a nice way<br>
to specifying which Prelude to use in a certain module, then you could<br>
use "Prelude1", "Prelude2" etc. in the same manner.<br>
<br>
= How does it related to base-compat? =<br>
<br>
The idea is similar to what base-compat provides, but the other way<br>
around: base-compat allows you to use the latest features of base on<br>
older compilers, while frozen-base would allow you to use the API of old<br>
base versions on newer systems.<br>
<br>
Frozen-base might subsume base-compat by providing, say Data.Bool2 with<br>
the API from base-4.8 also on systems with base-4.6.<br>
<br>
= How does it related to the split base proposal =<br>
<br>
Depending on how exactly base is being reconstructed, it might become a<br>
pure interface package on its own, or at least independent from<br>
compiler-specific bits. Then it might be feasible that, say, after the<br>
release of ghc-7.10 there is a new upload of base-4.6.0.n that provides<br>
the 4.6 API, but compiles on ghc-7.10. This way, if you depend on<br>
  base == 4.6.*<br>
you could still expect your program to work. If that happens, and also<br>
cabal would learn that a plan with different versions of a interface<br>
only library like base are not a problem, frozen-base might be<br>
obsoleted.<br>
<br>
See <a href="https://ghc.haskell.org/trac/ghc/wiki/SplitBase" target="_blank">https://ghc.haskell.org/trac/ghc/wiki/SplitBase</a> for more on that.<br>
<br>
<br>
= No Conclusion and lots of future work =<br>
<br>
So what do you think? Would you be interested in using this? Do you have<br>
reasons to believe that this will not work as nicely as I think i could?<br>
<br>
<br>
<br>
Greetings,<br>
Joachim<br>
<br>
<br>
<br>
<br>
¹ but rejected, it seems<br>
² or a sensible subset; I could imagine not exporting certain .Internal<br>
  modules and things like OldTypeable that are about compatibility<br>
  themselves.<br>
³ or just one on the very major version number (frozen-base < 2), which<br>
  to allow for exceptional breaking changes  – a redesign of the module<br>
  naming scheme for example.<br>
<br>
--<br>
Joachim “nomeata” Breitner<br>
  <a href="mailto:mail@joachim-breitner.de">mail@joachim-breitner.de</a> • <a href="http://www.joachim-breitner.de/" target="_blank">http://www.joachim-breitner.de/</a><br>
  Jabber: <a href="mailto:nomeata@joachim-breitner.de">nomeata@joachim-breitner.de</a>  • GPG-Key: 0xF0FBF51F<br>
  Debian Developer: <a href="mailto:nomeata@debian.org">nomeata@debian.org</a><br>
<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div>