The first issue situations like Data.Int → GHC.Int, where the interface is standard enough but the implementation is GHC-specific. But we can now use backpack to save us from that.
The orphans proposal doesn’t spell out the exact method of declaring an orphan module or package, but I imagine at the top level it would be some new syntax in the Cabal package, like
Cabal could ensure that there is no more than one orphan-meet for any two packages in the package set, that part is easy. I don’t quite see how this trickles down to the compiler, though.
@blamario No worries, it hasn’t been exactly worked out yet.
One would additionally need to specify the exact modules, say Data.Map and Control.Lens.At, and the module in the current library that is the meet. All that information is then handed off to GHC when it is compiling modules.
When checking say Ord k => At (Map k a) in the third module, it can see that this instance uses items from the two modules, At, and Map. Furthermore, the only possible instance head that would overlap is the At v, which would have to go in Control.Lens.At if it exists. So GHC can approve of Ord k => At (Map k a) knowing that any other overlapping instance would either violate the lattice rules, or be in a module that’s already imported and thus caught when Ord k => At (Map k a)` is defined. Together, GHC can be sure is no other way to have two overlapping orphan instances that are both valid in isolation.
Thank you for your contributions on that! I only follow half, but I can understand the general problem and how that increases resistance to improving/changing this. It seems like now is a good time to get attention on your proposals/work in an effort to see them thru and keep momentum going on this.
head :: a -> [a] -> a
head d [] = d
head _ (x:xs) = x
tail :: a -> [a] -> a
tail d [] = d
tail _ (_:xs) = xs
init :: a -> [a] -> [a]
init d [] = d
init _ [_] = []
init d (x:xs) = xs : init d xs
last :: a -> [a] -> [a]
last d [] = d
last _ [x] = x
last _ (_:xs) = last d xs