Avoiding the hazards of orphan instances without dependency problems

Jan Stolarek jan.stolarek at p.lodz.pl
Mon Oct 20 07:51:42 UTC 2014


In the past I've spent some time thinking about the orphan instances problem. I concluded that the 
Right Thing to do is to turn instances into first-class citizens and allow them to be explicitly 
imported and exported. I think devising pragmas is a workaround, not a solution.

Janek

Dnia poniedziałek, 20 października 2014, David Feuer napisał:
> OK, so first off, I don't have anything against your pragma; I just think
> that something akin to mine would be good to have too. Mine was not
> intended to require both class and type to be in scope; if one of them is
> not, then it should be given its full name:
>
> {-# InstanceIn Module Foo.Class Type #-}
> {-# InstanceIn Module Class Bar.Type #-}
>
> As Edward Kmett explained to me, there are reasons for module authors not
> to want to include instances for lens stuff—in particular, they apparently
> tend to use a lot of non-portable code, but even aside from that, they may
> just not want to have to deal with maintaining that particular code. This
> leads to a slew of instances being dumped into lens modules, forcing the
> lens package to depend on a bunch of others. What I'm suggesting is that
> sticking {-# InstanceIn Data.Text.Lens Strict Data.Text.Lazy.Text
> Data.Text.Text #-} into Control.Lens.Iso (and so on) would allow
> Data.Text.Lens to be broken off into a separate package, removing the text
> dependency from lens.
>
> Note also: I described a way to (try to) support overlapping instances for
> mine, but I think it would be valuable to offer mine even without that
> feature (dropping the context stuff), if it's just too complex.
>
> On Sun, Oct 19, 2014 at 9:43 PM, John Lato <jwlato at gmail.com> wrote:
> > I fail to see how this doesn't help lens, unless we're assuming no buy-in
> > from class declarations.  Also, your approach would require c*n pragmas
> > to be declared, whereas mine only requires c.  Also your method seems to
> > require having both the class and type in scope, in which case one could
> > simply declare the instance in that module anyway.
> >
> > On Mon, Oct 20, 2014 at 9:29 AM, David Feuer <david.feuer at gmail.com>
> >
> > wrote:
> >> I don't think your approach is flexible enough to accomplish the
> >> purpose. For example, it does almost nothing to help lens. Even my
> >> approach should, arguably, be extended transitively, allowing the named
> >> module to delegate that authority, but such an extension could easily be
> >> put off till later.
> >>
> >> On Oct 19, 2014 7:17 PM, "John Lato" <jwlato at gmail.com> wrote:
> >>> Thinking about this, I came to a slightly different scheme.  What if we
> >>> instead add a pragma:
> >>>
> >>> {-# OrphanModule ClassName ModuleName #-}
> >>>
> >>> and furthermore require that, if OrphanModule is specified, all
> >>> instances can *only* appear in the module where the class is defined,
> >>> the involved types are defined, or the given OrphanModule?  We would
> >>> also need to add support for the compiler to understand that multiple
> >>> modules may appear under the same name, which might be a bit tricky to
> >>> implement, but I think it's feasible (perhaps in a restricted manner).
> >>>
> >>> I think I'd prefer this when implementing orphan instances, and
> >>> probably when writing the pragmas as well.
> >>>
> >>> On Mon, Oct 20, 2014 at 1:02 AM, David Feuer <david.feuer at gmail.com>
> >>>
> >>> wrote:
> >>>> Orphan instances are bad. The standard approach to avoiding the orphan
> >>>> hazard is to always put an instance declaration in the module that
> >>>> declares the type or the one that declares the class. Unfortunately,
> >>>> this forces packages like lens to have an ungodly number of
> >>>> dependencies. Yesterday, I had a simple germ of an idea for solving
> >>>> this (fairly narrow) problem, at least in some cases: allow a
> >>>> programmer to declare where an instance declaration must be. I have no
> >>>> sense of sane syntax, but the rough idea is:
> >>>>
> >>>> {-# InstanceIn NamedModule [Context =>] C1 T1 [T2 ...] #-}
> >>>>
> >>>> This pragma would appear in a module declaring a class or type. The
> >>>> named module would not have to be available, either now or ever, but
> >>>> attempting to declare such an instance in any module *other* than the
> >>>> named one would be an error by default, with a flag
> >>>> -XAllowForbiddenInstancesAndInviteNasalDemons to turn it off. The
> >>>> optional context allows multiple such pragmas to appear in the
> >>>> type/class-declaring modules, to allow overlapping instances (all of
> >>>> them declared in advance).
> >>>>
> >>>> _______________________________________________
> >>>> ghc-devs mailing list
> >>>> ghc-devs at haskell.org
> >>>> http://www.haskell.org/mailman/listinfo/ghc-devs




More information about the ghc-devs mailing list