Not for more than a passing mention. Using the name of the module to control the default makes me unhappy (should choice of name be relevant in the correctness / interpretation of a program?). Other heuristics (presence of constrained functions) seem quite fragile. Of everything said so far, I think the closest suggestion is to use constrained datatypes (like `data Ord a => Set a = ...`), but that mis-appropriates datatype contexts (which are silly) into something new and different, and so I personally don't think it's really viable.
Following Mark's idea of breaking this problem up into more manageable chunks, I would want us to think about two separate (and conflicting, often) users: 1. Users of today's Haskell who have to update their code. 2. Users of Haskell in 10 years. Would users in group (2) like these heuristics? I doubt it. I think users in group (2) would probably most like a default of nominal with role annotations (in some concrete syntax). But, users in group (1) would hate a nominal default, so we have a compromise. Richard On Mar 26, 2014, at 11:40 AM, Casey McCann <c...@uptoisomorphism.net> wrote: > Were any rules considered along the lines of "Representational by > default if all the type's constructors are exported by a module not > named 'Internal', nominal by default otherwise"? Better would probably > include "exported by a module the package exposes" but that's > disgustingly non-local if it's even possible at all. The module name > thing is hacky to the extreme but at least it's a simple rule rather > than some obscure and opaque heuristics. > > Anyway, the goal of something like that would be not so much "figure > out what it should be", since that's impossible, but more "default to > nominal if and only if there's clear indication the user is already > thinking about restricting how the type is used". > > Not that I'm really even suggesting such a rule, just wondering if it > was discussed. > > - C. > > > On Tue, Mar 25, 2014 at 7:23 PM, Richard Eisenberg <e...@cis.upenn.edu> wrote: >> Hi Mark, >> >> I appreciate your analysis in terms of classes of users -- I think that is >> helpful for framing the discussion. >> >> About transitivity: I think we're in the clear here. Let's say package A >> exports types missing role annotations. If package B imports package A and >> wants to have the full safety afforded by roles, that is no problem >> whatsoever. Package B has annotations on its types (which may use package >> A's types) that may restrict certain parameters to be nominal, as >> appropriate. If package A had role annotations, it's quite possible that >> package B could omit some annotations (as role inference propagates nominal >> roles), but there is no problem inherent in this. (Indeed, if package A adds >> annotations in the future, package B would have redundant, but harmless, >> annotations.) So, I disagree with Mark's "partially" below -- I think we're >> fully OK in this regard. >> >> About heuristics: we briefly considered some, though there's no >> documentation of this anywhere. Specifically, we thought about giving >> nominal roles to parameters used in class constraints. The problem is, in >> the actual datatype definition, the constraints tend not to appear? Should >> we look around for other functions with constraints? That seems likely to be >> more confusing than helpful. Furthermore, I strongly don't like the idea of >> using heuristics to infer a feature such as this -- it can cause strange >> behavior and is hard to specify. >> >> Richard >> >> On Mar 25, 2014, at 11:09 AM, Mark Lentczner wrote: >> >> Thank you to everyone who has been helping me understand this issue in >> greater depth. >> >> tl;dr: As long as we don't expect any libraries beyond to core to annotate, >> I'm cool. This presumes that the extra safety isn't, in practice, dependent >> on transitive adoption by libraries. It also implies that representational >> is the only possible default, and that there can be no migration from it. >> >> My approach to thinking about this is guided by thinking about supporting an >> eco-system with 1000s of libraries (hackage), a few dozen of which are >> heavily promoted (the platform), and a small set that are closely tied to >> the compiler (the core). The availability, speed of release, motivation, and >> even skill of the the developers varies widely over that range. >> >> I also think about the various "stances" of different developers: >> >> End developer: makes use of libraries, but just builds apps >> Internal developer: makes libraries for internal use in a project >> Casual library writer: makes libraries, primarily for their own needs, but >> distributed on hackage >> Popular library writer: actively maintains libraries which are widely used >> Core library writer: maintainer of a core package that stays in lock step >> with the compiler >> >> Then, I think about, for each of these, what is the effect on a new feature >> on them, their existing code, and future code? Does it affect them only if >> they are using the feature? If they aren't using the feature? For library >> writers, how does the feature affect clients? If a client wants to use a >> feature, under what conditions does the library need to do something? This >> last issue of the "transitivity" the feature is often the biggest concern. >> >> Given that... onto type roles: >> >> The default of representational is the only option, because a default of >> nominal would require far too many developers to have to update their code. >> I don't believe that we can ever migrate to nominal as default. >> >> The feature implies that any abstract data type that uses a type parameter >> in certain ways needs annotate to get the full safety afforded now afforded. >> However, without annotation, the data type is still no worse off than it was >> before (there is added safety, but not perhaps relevant to the stand point >> of the library writer). Further, this (pre-existing) non-safety isn't likely >> a huge concern. Making sure the docs take the tone that most developers need >> to nothing, and when developers need to be concerned seems like an important >> way to ensure the right outcome. >> >> A key question here is transitivity: Is it possible for module A to not >> annotate a type, and then have module B by a different author use the type >> in A in another abstract type, that is annotated, and get the benefit. Seems >> the answer is "partially". If the answer were "no", then use of the feature >> would be dependent on transitive adoption, and that is where the big burden >> on developers comes from. >> >> The degree to which we believe this "partially" is important: If we are >> willing to believe that the only library writers we care about doing this >> are those in the core, then fine. In this case we shouldn't feel compelled >> to suggest to library writers that they annotate, ever. I'm good with this. >> If the team here thinks otherwise, that we need to start a campaign to get >> every library writer to eventually annotate, then I have deep objections. >> >> I read the paper, and understand how the authors felt the syntax options >> were all less than perfect, and choose what they did. But that choice, >> perhaps unwittingly, the implication that it forces -XCPP on all libraries >> except perhaps some of the core. This is because they all need to support >> previous compilers. So, a one line annotation has turned into an ugly beast, >> and perhaps added -XCPP where there was none, which is really unfortunate. >> (I, like many, consider it a defeat when one has to resort to -XCPP.) >> >> It seems to me that the paper didn't really consider less-perfect, heuristic >> solutions. It might have had significantly less impact on library writers >> were some heuristic (no constructors exported? has any type constraint on >> the parameter? etc..) might have allowed most data types to go without >> annotation at the cost of a few (where nominal was incorrectly inferred) >> requiring immediate action. In this situation, a non-language feature >> (pragma or other device) might have been more palatable. >> >> Finally, on the choice of terms, nominal, representational, and phantom all >> seem like clear, self-explanatory choices to me. >> >> - Mark >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs@haskell.org >> http://www.haskell.org/mailman/listinfo/ghc-devs >> >> >> >> _______________________________________________ >> Libraries mailing list >> librar...@haskell.org >> http://www.haskell.org/mailman/listinfo/libraries >> _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs