dhall-lang / dhall-to-cabal

Compile Dhall expressions to Cabal files
MIT License
100 stars 19 forks source link

Compatibility and upgrade guidelines for Dhall code #92

Open quasicomputational opened 6 years ago

quasicomputational commented 6 years ago

The type of the input Dhall expression to dhall-to-cabal is going to have to change sooner or later. If a future version of Cabal introduces a new feature (which it's surely going to), then dhall-to-cabal is going to expect a different type, and never mind any other changes it might be necessary or useful to make.

We probably should have some kind of story here about what user code can do to avoid fragility and what to do when the breaking update comes.

One idea might be to say that the prelude's defaults should be used as much as possible, and to avoid writing explicit sum types in user code. If new fields or constructors are added, this provides a reasonable upgrade path: just change the version of the prelude you're importing and off you go. It deals well even if existing fields or constructors are changed: only the parts directly affected will need additional changes.

However, this sort of resilience isn't preserved by normalisation or import resolution. Maybe we should warn about that in the docs or something?

We can detect if an expression isn't importing prelude.dhall and types.dhall and warn, which isn't foolproof but should have very good false positive and false negative rates; the question is whether that's a good idea.

A second, complimentary possibility: we could provide a compatibility Dhall function, accepting the old Package type and returning a new one. That's more work for us, and it might only be a deferral of the pain for users if they've somehow painted themselves into a corner where upgrading is hard. Possibly worth experimenting with partial normalisation to see if that gives good results here.

Finally we might advise users who are in an upgrade corner to put their generated Cabal files through cabal-to-dhall and then refactor the Dhall as necessary. At least the presence of this option will keep users from being totally trapped by legacy Dhall code. Maybe we can make cabal-to-dhall better (e.g., floating out common dependency versions to the top level?) so that less manual refactoring is needed to get back to where you were; on the other hand, it's slightly difficult to predict what will be useful here without having seen how dhall-to-cabal gets used in the wild and what sorts of abstracting users do.

None of this is critical or needs solving soon, mostly because anyone using dhall-to-cabal today had better have a taste for adventure, but it's something to think about for the future if we want to become a Serious Tool.

jneira commented 6 years ago

I completely agree with this. The situation is somewhat not so bad cause most (?) changes in cabal spec are retrocompatible (f.e. show warnings with additional fields in stanzas). Generated files with the actual spec 2.2 can be used in older versions of cabal (if you dont use the new ^> bound or DPSX licenses among others).

Another possibility would be keep the history of cabal specs from the most used in actual packages ( >= 1.10 , stick to the actual one or 2.0?) and use the cabal spec to choose the appropiate cabal GenericPackageDescripcion type. I guess it would be a titanic effort, maybe involving a lot of duplication in both dhall code (./dhall/cabal-2.0/..., ./dhall/cabal-2.1/.. and so on) and haskell one (we would need a copy of cabal types for all versions?) so not sure it it worths, although (or cause) this way dhall-to-cabal would be a source of truth for the history of cabal specs.

jneira commented 6 years ago

Well, as cabal specs usually add not required new fields each ./cabal-x.y/package.dhall could add fields to a ./cabal-base/package.dhall. Work with new cases of sum types or the different cabal GenericPackageDescriptions would be a very different story..