[Haskell-cafe] Avoiding orphan instances and dependency blowups

Clinton Mead clintonmead at gmail.com
Sun Jun 4 12:50:59 UTC 2017

Hi All

Consider this common situation.

1. Class C in package A.
2. A data type D in package B.
3. There is a clear instance C D but:
4. We do not want A to depend on B as most users of A do not use B.
5. We do not want B to depend on A as most users of B do not use A.

Currently the proposed solutions are:

1. Create a third package, say AB, that depends on both A and B, wrap D in
a newtype, and define an instance there.
2. Create a third package, say AB, that depends on both A and B as above,
but instead create an orphan instance C D in this package.
3. Just give in and either make A depend on B or B depend on A.

None of these solutions seem very satisfying. The first one, wrapping D in
a newtype, destroys much of the interoperability that is attempting to be
achieved by defining the instance in the first place. The second solution
uses orphan instances and for a variety of reasons many seem to suggest
these should be avoided. The third option introduces a snowball of
dependencies that the vast majority of the time will be completely unused.

I've heard some conversations of changes to GHC to deal with this, like
"authoritative instances" but nothing seems to have come of it?

I thought to myself, maybe this is a problem that could be solved by the
package manager, not GHC.

Here's the draft of how this could work:

1. Create a package, AB, that depends on A and B, but passes an "option" to
B, in this case "A". So the dependencies of AB are A and B(A).
2. The package B defines the instance C D, but wrapped in some preprocessor
#ifdef style macros.
3. The package manager passes the requested flags to B during it's
compilation, and those flags trigger the sections of code required to be
compiled and also additional dependencies.
4. If a new package is installed adds to the flags of B, B is recompiled.

This way, packages could define instances for each other but if those
dependencies are not used, they do not need to be compiled. But the user
has a way to explicitly activate the instances.

My questions:

1. Is this a roughly okay idea?
2. Is there already a better way of doing what I'm proposing (perhaps
through backpack which I don't know much about yet)?
3. Is there a way to make this happen currently in Stack or Cabal, perhaps
with custom setup scripts, or will this need some significant changes to
Stack/Cabal themselves?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20170604/46521612/attachment.html>

More information about the Haskell-Cafe mailing list