Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24). Type in expressions to have them evaluated. Type :help for more information.
scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : List[Either[A,GCG[A]]] } defined trait GCG
scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } <console>:6: error: covariant type A occurs in invariant position in type => Set[Either[A,GCG[A]]] of method left trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } ^ <console>:6: error: covariant type A occurs in invariant position in type => Set[Either[A,GCG[A]]] of method right trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } ^
P.S. i guess this must be intentional because it was preserved from 2.8.1 to 2.9
Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24). Type in expressions to have them evaluated. Type :help for more information.
scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : List[Either[A,GCG[A]]] } defined trait GCG
scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } <console>:8: error: covariant type A occurs in invariant position in type => Set[Either[A,GCG[A]]] of method left trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } ^ <console>:8: error: covariant type A occurs in invariant position in type => Set[Either[A,GCG[A]]] of method right trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : Set[Either[A,GCG[A]]] } ^
scala>
On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory <lgreg.mered...@gmail.com>wrote:
> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, > Java 1.6.0_24). > Type in expressions to have them evaluated. > Type :help for more information.
> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : > List[Either[A,GCG[A]]] } > defined trait GCG
> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > <console>:6: error: covariant type A occurs in invariant position in type > => Set[Either[A,GCG[A]]] of method left > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^ > <console>:6: error: covariant type A occurs in invariant position in type > => Set[Either[A,GCG[A]]] of method right > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^
<lgreg.mered...@gmail.com> wrote: > P.S. i guess this must be intentional because it was preserved from 2.8.1 to > 2.9 > Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, > Java 1.6.0_24). > Type in expressions to have them evaluated. > Type :help for more information. > scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : > List[Either[A,GCG[A]]] } > defined trait GCG > scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > <console>:8: error: covariant type A occurs in invariant position in type => > Set[Either[A,GCG[A]]] of method left > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^ > <console>:8: error: covariant type A occurs in invariant position in type => > Set[Either[A,GCG[A]]] of method right > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^ > scala> > On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory <lgreg.mered...@gmail.com> > wrote:
>> Dear Scalarazzi, >> i was surprised by the following. >> Best wishes, >> --greg >> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, >> Java 1.6.0_24). >> Type in expressions to have them evaluated. >> Type :help for more information. >> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >> List[Either[A,GCG[A]]] } >> defined trait GCG >> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method left >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^ >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method right >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^ >> scala> >> -- >> L.G. Meredith >> Managing Partner >> Biosimilarity LLC >> 7329 39th Ave SW >> Seattle, WA 98136
I don't think the question was ever fully answered. Daniel makes it clear the issue is the contains method. For both List and Set, you can either have covariance, or you can have a contains method that takes an A (instead of Any), but you can't have both.
In the case of List, covariance was chosen, and List.contains takes Any. In the case of Set, invariance was chosen, and Set.contains takes A.
The question remains: why was this design decision made?
This particular situation strikes me as a case where inheritance is once again being very ... um... helpful. If the choice was made to have an interpretation of Set as Function (via a consumer of Set that produced this interpretation, such as trait SetsAreFunctions[S,T] { def asFunction( s : Set[S] ) : S => T } ) then one could make a lot of interesting choices. For example, Fuzzy Sets might ask for an interpretation Set[T] => T => Float. Finite sets could be defined as partial functions on infinite domains. Etc.
Moreover, the example used to justify the design decision under discussion here doesn't actually distinguish Set from List, imho. There is no compelling a priori reason to prefer the interpretation taking Set[T] to T => Boolean that would exclude demanding the same of List[T].
A good friend of mine suggests that being available is preferable to being helpful. In this case, i'm quite certain i would prefer if inheritance were merely available, and not quite so helpful. i just spent a great deal of time converting some code samples (that really needed Set semantics, but were originally expressed using List) from List to Set. Only to find at the last moment that i have two choices in front of me
- put everything back to using List and redo set semantics in the places where i need to suppress duplication and ignore order (obviously, i'm getting a lot of reuse value from the inheritance here!); or - implement my collection type that has set semantics and corresponding variance (another delightful moment of productivity and reuse value i've derived from the helpfulness of inheritance)
On Sat, May 28, 2011 at 3:49 PM, David Hall <d...@cs.berkeley.edu> wrote: > Set[T] extends T=>Boolean so it can't be covariant.
> -- David
> On Sat, May 28, 2011 at 3:33 PM, Meredith Gregory > <lgreg.mered...@gmail.com> wrote: > > P.S. i guess this must be intentional because it was preserved from 2.8.1 > to > > 2.9 > > Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, > > Java 1.6.0_24). > > Type in expressions to have them evaluated. > > Type :help for more information. > > scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : > > List[Either[A,GCG[A]]] } > > defined trait GCG > > scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > > Set[Either[A,GCG[A]]] } > > <console>:8: error: covariant type A occurs in invariant position in type > => > > Set[Either[A,GCG[A]]] of method left > > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > > Set[Either[A,GCG[A]]] } > > ^ > > <console>:8: error: covariant type A occurs in invariant position in type > => > > Set[Either[A,GCG[A]]] of method right > > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > > Set[Either[A,GCG[A]]] } > > ^ > > scala> > > On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < > lgreg.mered...@gmail.com> > > wrote:
> >> Dear Scalarazzi, > >> i was surprised by the following. > >> Best wishes, > >> --greg > >> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, > >> Java 1.6.0_24). > >> Type in expressions to have them evaluated. > >> Type :help for more information. > >> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : > >> List[Either[A,GCG[A]]] } > >> defined trait GCG > >> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > >> Set[Either[A,GCG[A]]] } > >> <console>:6: error: covariant type A occurs in invariant position in > type > >> => Set[Either[A,GCG[A]]] of method left > >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > >> Set[Either[A,GCG[A]]] } > >> ^ > >> <console>:6: error: covariant type A occurs in invariant position in > type > >> => Set[Either[A,GCG[A]]] of method right > >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > >> Set[Either[A,GCG[A]]] } > >> ^ > >> scala> > >> -- > >> L.G. Meredith > >> Managing Partner > >> Biosimilarity LLC > >> 7329 39th Ave SW > >> Seattle, WA 98136
I'd like to chime in that I too think inheritance from the various function types (for Map, List, Set, etc.) is wrongheaded and overly limiting; implicits would be vastly preferable and could be implemented without breaking source compatibility in most cases, as was done with the collections library in 2.8.0. Much like equality, one very frequently wants function semantics of collections to be contextual and unrelated to the inheritance hierarchy.
Is there any chance of such a change being considered?
P.S. The irony of this particular situation is just too sweet not to share more. i was in the middle of writing up a blog entry from material that i might end up cutting from the book. The subject matter is precisely a critique of this sort of design choice -- but made from the positive side by showing the benefits of organizing things as i have suggested below. You can see a draft of the entry here<https://docs.google.com/document/pub?id=1WPkVvWAil61NdsQOxZHNDGJlH0h5...>. i might as well use the moment to get some feedback on the draft while it's in progress.
On Sat, May 28, 2011 at 4:14 PM, Meredith Gregory <lgreg.mered...@gmail.com>wrote:
> This particular situation strikes me as a case where inheritance is once > again being very ... um... helpful. If the choice was made to have an > interpretation of Set as Function (via a consumer of Set that produced this > interpretation, such as trait SetsAreFunctions[S,T] { def asFunction( s : > Set[S] ) : S => T } ) then one could make a lot of interesting choices. For > example, Fuzzy Sets might ask for an interpretation Set[T] => T => Float. > Finite sets could be defined as partial functions on infinite domains. Etc.
> Moreover, the example used to justify the design decision under discussion > here doesn't actually distinguish Set from List, imho. There is no > compelling a priori reason to prefer the interpretation taking Set[T] to T > => Boolean that would exclude demanding the same of List[T].
> A good friend of mine suggests that being available is preferable to being > helpful. In this case, i'm quite certain i would prefer if inheritance were > merely available, and not quite so helpful. i just spent a great deal of > time converting some code samples (that really needed Set semantics, but > were originally expressed using List) from List to Set. Only to find at the > last moment that i have two choices in front of me
> - put everything back to using List and redo set semantics in the > places where i need to suppress duplication and ignore order (obviously, i'm > getting a lot of reuse value from the inheritance here!); or > - implement my collection type that has set semantics and corresponding > variance (another delightful moment of productivity and reuse value i've > derived from the helpfulness of inheritance)
> Best wishes,
> --greg
> On Sat, May 28, 2011 at 3:49 PM, David Hall <d...@cs.berkeley.edu> wrote:
>> Set[T] extends T=>Boolean so it can't be covariant.
>> -- David
>> On Sat, May 28, 2011 at 3:33 PM, Meredith Gregory >> <lgreg.mered...@gmail.com> wrote: >> > P.S. i guess this must be intentional because it was preserved from >> 2.8.1 to >> > 2.9 >> > Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, >> > Java 1.6.0_24). >> > Type in expressions to have them evaluated. >> > Type :help for more information. >> > scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >> > List[Either[A,GCG[A]]] } >> > defined trait GCG >> > scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> > Set[Either[A,GCG[A]]] } >> > <console>:8: error: covariant type A occurs in invariant position in >> type => >> > Set[Either[A,GCG[A]]] of method left >> > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> > Set[Either[A,GCG[A]]] } >> > ^ >> > <console>:8: error: covariant type A occurs in invariant position in >> type => >> > Set[Either[A,GCG[A]]] of method right >> > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> > Set[Either[A,GCG[A]]] } >> > ^ >> > scala> >> > On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < >> lgreg.mered...@gmail.com> >> > wrote:
>> >> Dear Scalarazzi, >> >> i was surprised by the following. >> >> Best wishes, >> >> --greg >> >> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server >> VM, >> >> Java 1.6.0_24). >> >> Type in expressions to have them evaluated. >> >> Type :help for more information. >> >> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >> >> List[Either[A,GCG[A]]] } >> >> defined trait GCG >> >> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> >> Set[Either[A,GCG[A]]] } >> >> <console>:6: error: covariant type A occurs in invariant position in >> type >> >> => Set[Either[A,GCG[A]]] of method left >> >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> >> Set[Either[A,GCG[A]]] } >> >> ^ >> >> <console>:6: error: covariant type A occurs in invariant position in >> type >> >> => Set[Either[A,GCG[A]]] of method right >> >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> >> Set[Either[A,GCG[A]]] } >> >> ^ >> >> scala> >> >> -- >> >> L.G. Meredith >> >> Managing Partner >> >> Biosimilarity LLC >> >> 7329 39th Ave SW >> >> Seattle, WA 98136
<kris.nuttyco...@gmail.com> wrote: > limiting; implicits would be vastly preferable and could be > implemented without breaking source compatibility in most cases, as
i think Kris' question has some merit. What's your take?
Best wishes,
--greg
On Sat, May 28, 2011 at 4:23 PM, Kris Nuttycombe <kris.nuttyco...@gmail.com>wrote:
> I'd like to chime in that I too think inheritance from the various > function types (for Map, List, Set, etc.) is wrongheaded and overly > limiting; implicits would be vastly preferable and could be > implemented without breaking source compatibility in most cases, as > was done with the collections library in 2.8.0. Much like equality, > one very frequently wants function semantics of collections to be > contextual and unrelated to the inheritance hierarchy.
> Is there any chance of such a change being considered?
On Sun, May 29, 2011 at 1:23 AM, Kris Nuttycombe <kris.nuttyco...@gmail.com>wrote:
> I'd like to chime in that I too think inheritance from the various > function types (for Map, List, Set, etc.) is wrongheaded and overly > limiting; implicits would be vastly preferable and could be > implemented without breaking source compatibility in most cases, as > was done with the collections library in 2.8.0. Much like equality, > one very frequently wants function semantics of collections to be > contextual and unrelated to the inheritance hierarchy.
> Is there any chance of such a change being considered?
> I think it's too late for that. We really have to take binary compatibility
more seriously than up to now. And that means more or less freezing collections. Some small improvements, maybe, but there will be no more changes in the design.
On the issue of sets, I believe the non-variance stems also from the implementations. Common sets are implemented as hashtables, which are non-variant arrays of the key type. I agree it's a slighly annoying irregularity.
-- Martin
On Sun, May 29, 2011 at 11:09 PM, martin odersky <martin.oder...@epfl.ch>wrote:
> On Sun, May 29, 2011 at 1:23 AM, Kris Nuttycombe < > kris.nuttyco...@gmail.com> wrote:
>> I'd like to chime in that I too think inheritance from the various >> function types (for Map, List, Set, etc.) is wrongheaded and overly >> limiting; implicits would be vastly preferable and could be >> implemented without breaking source compatibility in most cases, as >> was done with the collections library in 2.8.0. Much like equality, >> one very frequently wants function semantics of collections to be >> contextual and unrelated to the inheritance hierarchy.
>> Is there any chance of such a change being considered?
>> I think it's too late for that. We really have to take binary > compatibility more seriously than up to now. And that means more or less > freezing collections. Some small improvements, maybe, but there will be no > more changes in the design.
Thanks for your input! If i understand correctly, it will be up to the community to grow some separate Set-like collections with consistent variance; and, if needed, provide views of these collections as functions. That sounds like a worthy task!
Also, just for my own understanding, can you provide pointers to information about the approach to binary compatibility? i'd like to verify for myself that Kris proposal cannot be made to work in a way that supports binary compatibility.
Best wishes,
--greg
On Sun, May 29, 2011 at 2:13 PM, martin odersky <martin.oder...@epfl.ch>wrote:
> On the issue of sets, I believe the non-variance stems also from the > implementations. Common sets are implemented as hashtables, which are > non-variant arrays of the key type. I agree it's a slighly annoying > irregularity.
> -- Martin
> On Sun, May 29, 2011 at 11:09 PM, martin odersky <martin.oder...@epfl.ch>wrote:
>> On Sun, May 29, 2011 at 1:23 AM, Kris Nuttycombe < >> kris.nuttyco...@gmail.com> wrote:
>>> I'd like to chime in that I too think inheritance from the various >>> function types (for Map, List, Set, etc.) is wrongheaded and overly >>> limiting; implicits would be vastly preferable and could be >>> implemented without breaking source compatibility in most cases, as >>> was done with the collections library in 2.8.0. Much like equality, >>> one very frequently wants function semantics of collections to be >>> contextual and unrelated to the inheritance hierarchy.
>>> Is there any chance of such a change being considered?
>>> I think it's too late for that. We really have to take binary >> compatibility more seriously than up to now. And that means more or less >> freezing collections. Some small improvements, maybe, but there will be no >> more changes in the design.
On Sun, May 29, 2011 at 11:54 PM, Meredith Gregory <lgreg.mered...@gmail.com
> wrote: > Dear Martin,
> Thanks for your input! If i understand correctly, it will be up to the > community to grow some separate Set-like collections with consistent > variance; and, if needed, provide views of these collections as functions. > That sounds like a worthy task!
> Also, just for my own understanding, can you provide pointers to > information about the approach to binary compatibility?
Mirco Dotta has recently categorized what incompatibilities can arise. He might be the best source to give more info.
> Also, just for my own understanding, can you provide pointers to information about the approach to binary compatibility?
We have developed a tool that will help you diagnose binary incompatibilities. We plan to get it out as a beta during Scala Days (so just a few days from now!).
As for more detailed information on the sort of binary incompatibilities that the tool checks, I'm working on a document that I hope will be soon public. It should help taking the right decisions when evolving your classes and traits. The form is similar to Java's binary compatibility document (http://java.sun.com/docs/books/jls/second_edition/html/binaryComp.doc...).
Of course if you have specific questions I'll be happy to answer them.
While it is easy to turn an obviously invariant Set[A] to contravariant [A->Boolean], it might make sense to have something covariant... something like Iterable[+A].
What's interesting is how we can casually disambiguate (between) these two functors. And whether it is feasible to disambiguate in current programming practice. What we call "sets" in Scala are not sets in any scientific sense anyway, are they? What Set[A] means is a "powertype", right?
Thanks, -Vlad
On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory <lgreg.mered...@gmail.com>wrote:
> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, > Java 1.6.0_24). > Type in expressions to have them evaluated. > Type :help for more information.
> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : > List[Either[A,GCG[A]]] } > defined trait GCG
> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > <console>:6: error: covariant type A occurs in invariant position in type > => Set[Either[A,GCG[A]]] of method left > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^ > <console>:6: error: covariant type A occurs in invariant position in type > => Set[Either[A,GCG[A]]] of method right > trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : > Set[Either[A,GCG[A]]] } > ^
To my mind there are several possible interpretations of Set[A]. One is that it simply is a concrete specialization of A => Boolean. Another is that it is a duplicate-free, order-insensitive collection. Another is that it is a Set in the sense of FM-Set Theory, i.e. a Set with atoms where the type of atoms is A.
Best wishes,
--greg
On Mon, May 30, 2011 at 12:40 AM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
> While it is easy to turn an obviously invariant Set[A] to contravariant > [A->Boolean], it might make sense to have something covariant... something > like Iterable[+A].
> What's interesting is how we can casually disambiguate (between) these two > functors. And whether it is feasible to disambiguate in current programming > practice. What we call "sets" in Scala are not sets in any scientific sense > anyway, are they? What Set[A] means is a "powertype", right?
> Thanks, > -Vlad
> On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < > lgreg.mered...@gmail.com> wrote:
>> Dear Scalarazzi,
>> i was surprised by the following.
>> Best wishes,
>> --greg
>> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, >> Java 1.6.0_24). >> Type in expressions to have them evaluated. >> Type :help for more information.
>> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >> List[Either[A,GCG[A]]] } >> defined trait GCG
>> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method left >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^ >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method right >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^
On Sun, May 29, 2011 at 11:56 PM, Mirco Dotta <mirco.do...@gmail.com> wrote:
> > Also, just for my own understanding, can you provide pointers to > information about the approach to binary compatibility?
> We have developed a tool that will help you diagnose binary > incompatibilities. We plan to get it out as a beta during Scala Days > (so just a few days from now!).
> As for more detailed information on the sort of binary incompatibilities > that the tool checks, I'm working on a document that I hope > will be soon public. It should help taking the right decisions when > evolving your classes and traits. The form is similar to > Java's binary compatibility document ( > http://java.sun.com/docs/books/jls/second_edition/html/binaryComp.doc... > ).
> Of course if you have specific questions I'll be happy to answer them.
scala> implicit def toTrav[X](set: Set[X]): Traversable[X] = new Traversable[X] { | def foreach[U](f: X => U): Unit = set.foreach(f) | } toTrav: [X](set: Set[X])Traversable[X]
maybe I'm plain wrong here
I mean: variance issues will eventually pop up anyway (and, if yes, then, maybe, it makes sense that type inference would be less strict when implicits are involved than when inheritance is involved (?))
... just a wild thought ...
Luc
On Mon, May 30, 2011 at 9:40 AM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
> While it is easy to turn an obviously invariant Set[A] to contravariant > [A->Boolean], it might make sense to have something covariant... something > like Iterable[+A].
> What's interesting is how we can casually disambiguate (between) these two > functors. And whether it is feasible to disambiguate in current programming > practice. What we call "sets" in Scala are not sets in any scientific sense > anyway, are they? What Set[A] means is a "powertype", right?
> Thanks, > -Vlad
> On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < > lgreg.mered...@gmail.com> wrote:
>> Dear Scalarazzi,
>> i was surprised by the following.
>> Best wishes,
>> --greg
>> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, >> Java 1.6.0_24). >> Type in expressions to have them evaluated. >> Type :help for more information.
>> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >> List[Either[A,GCG[A]]] } >> defined trait GCG
>> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method left >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^ >> <console>:6: error: covariant type A occurs in invariant position in type >> => Set[Either[A,GCG[A]]] of method right >> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >> Set[Either[A,GCG[A]]] } >> ^
> scala> implicit def toTrav[X](set: Set[X]): Traversable[X] = new > Traversable[X] { > | def foreach[U](f: X => U): Unit = set.foreach(f) > | } > toTrav: [X](set: Set[X])Traversable[X]
> maybe I'm plain wrong here
> I mean: variance issues will eventually pop up anyway > (and, if yes, then, maybe, it makes sense that type inference would be less > strict when implicits are involved than when inheritance is involved (?))
> ... just a wild thought ...
> Luc
> On Mon, May 30, 2011 at 9:40 AM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
>> While it is easy to turn an obviously invariant Set[A] to contravariant >> [A->Boolean], it might make sense to have something covariant... something >> like Iterable[+A].
>> What's interesting is how we can casually disambiguate (between) these two >> functors. And whether it is feasible to disambiguate in current programming >> practice. What we call "sets" in Scala are not sets in any scientific sense >> anyway, are they? What Set[A] means is a "powertype", right?
>> Thanks, >> -Vlad
>> On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < >> lgreg.mered...@gmail.com> wrote:
>>> Dear Scalarazzi,
>>> i was surprised by the following.
>>> Best wishes,
>>> --greg
>>> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, >>> Java 1.6.0_24). >>> Type in expressions to have them evaluated. >>> Type :help for more information.
>>> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >>> List[Either[A,GCG[A]]] } >>> defined trait GCG
>>> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>> Set[Either[A,GCG[A]]] } >>> <console>:6: error: covariant type A occurs in invariant position in type >>> => Set[Either[A,GCG[A]]] of method left >>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>> Set[Either[A,GCG[A]]] } >>> ^ >>> <console>:6: error: covariant type A occurs in invariant position in type >>> => Set[Either[A,GCG[A]]] of method right >>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>> Set[Either[A,GCG[A]]] } >>> ^
i guess the point is that it is not *one* functor. There are many reasonable functors, each with different characteristics. This is why inheritance gets in the way. It's not flexible enough to model the range of useful contexts. That's why the implicits route has now been proposed by no less than three parties: myself, Kris and Luc.
Best wishes,
--greg
On Tue, May 31, 2011 at 7:39 PM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
>> scala> implicit def toTrav[X](set: Set[X]): Traversable[X] = new >> Traversable[X] { >> | def foreach[U](f: X => U): Unit = set.foreach(f) >> | } >> toTrav: [X](set: Set[X])Traversable[X]
>> maybe I'm plain wrong here
>> I mean: variance issues will eventually pop up anyway >> (and, if yes, then, maybe, it makes sense that type inference would be >> less strict when implicits are involved than when inheritance is involved >> (?))
>> ... just a wild thought ...
>> Luc
>> On Mon, May 30, 2011 at 9:40 AM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
>>> While it is easy to turn an obviously invariant Set[A] to contravariant >>> [A->Boolean], it might make sense to have something covariant... something >>> like Iterable[+A].
>>> What's interesting is how we can casually disambiguate (between) these >>> two functors. And whether it is feasible to disambiguate in current >>> programming practice. What we call "sets" in Scala are not sets in any >>> scientific sense anyway, are they? What Set[A] means is a "powertype", >>> right?
>>> Thanks, >>> -Vlad
>>> On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < >>> lgreg.mered...@gmail.com> wrote:
>>>> Dear Scalarazzi,
>>>> i was surprised by the following.
>>>> Best wishes,
>>>> --greg
>>>> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, >>>> Java 1.6.0_24). >>>> Type in expressions to have them evaluated. >>>> Type :help for more information.
>>>> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >>>> List[Either[A,GCG[A]]] } >>>> defined trait GCG
>>>> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>> Set[Either[A,GCG[A]]] } >>>> <console>:6: error: covariant type A occurs in invariant position in >>>> type => Set[Either[A,GCG[A]]] of method left >>>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>> Set[Either[A,GCG[A]]] } >>>> ^ >>>> <console>:6: error: covariant type A occurs in invariant position in >>>> type => Set[Either[A,GCG[A]]] of method right >>>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>> Set[Either[A,GCG[A]]] } >>>> ^
So, i looked into this a bit more, from the perspective of where to inject a collection with Set-like capabilities (order insensitive, no duplicates; or, equationally, respecting S + S = S and S1 + S2 = S2 + S1) and not only is SetLike invariant, but Subtractable is also invariant. Subtractable extends AnyRef, so i don't understand the reason for this choice of variance constraint.
Best wishes,
--greg
On Tue, May 31, 2011 at 11:02 PM, Meredith Gregory <lgreg.mered...@gmail.com
> i guess the point is that it is not *one* functor. There are many > reasonable functors, each with different characteristics. This is why > inheritance gets in the way. It's not flexible enough to model the range of > useful contexts. That's why the implicits route has now been proposed by no > less than three parties: myself, Kris and Luc.
> Best wishes,
> --greg
> On Tue, May 31, 2011 at 7:39 PM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
>> Right, Traversable is covariant, pow is contravariant, but what is Set? Is >> it, hmm, a functor? Seems like it is not. >> Thanks, >> -Vlad
>> On Tue, May 31, 2011 at 12:12 AM, Luc Duponcheel < >> luc.duponch...@gmail.com> wrote:
>>> Hi,
>>> is the original question (replacing inheritance with implicits) >>> not somehow circumventing this variance issue in the first place?
>>> scala> implicit def toTrav[X](set: Set[X]): Traversable[X] = new >>> Traversable[X] { >>> | def foreach[U](f: X => U): Unit = set.foreach(f) >>> | } >>> toTrav: [X](set: Set[X])Traversable[X]
>>> maybe I'm plain wrong here
>>> I mean: variance issues will eventually pop up anyway >>> (and, if yes, then, maybe, it makes sense that type inference would be >>> less strict when implicits are involved than when inheritance is involved >>> (?))
>>> ... just a wild thought ...
>>> Luc
>>> On Mon, May 30, 2011 at 9:40 AM, Vlad Patryshev <vpatrys...@gmail.com>wrote:
>>>> While it is easy to turn an obviously invariant Set[A] to contravariant >>>> [A->Boolean], it might make sense to have something covariant... something >>>> like Iterable[+A].
>>>> What's interesting is how we can casually disambiguate (between) these >>>> two functors. And whether it is feasible to disambiguate in current >>>> programming practice. What we call "sets" in Scala are not sets in any >>>> scientific sense anyway, are they? What Set[A] means is a "powertype", >>>> right?
>>>> Thanks, >>>> -Vlad
>>>> On Sat, May 28, 2011 at 3:29 PM, Meredith Gregory < >>>> lgreg.mered...@gmail.com> wrote:
>>>>> Dear Scalarazzi,
>>>>> i was surprised by the following.
>>>>> Best wishes,
>>>>> --greg
>>>>> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server >>>>> VM, Java 1.6.0_24). >>>>> Type in expressions to have them evaluated. >>>>> Type :help for more information.
>>>>> scala> trait GCG[+A] { def left : List[Either[A,GCG[A]]]; def right : >>>>> List[Either[A,GCG[A]]] } >>>>> defined trait GCG
>>>>> scala> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>>> Set[Either[A,GCG[A]]] } >>>>> <console>:6: error: covariant type A occurs in invariant position in >>>>> type => Set[Either[A,GCG[A]]] of method left >>>>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>>> Set[Either[A,GCG[A]]] } >>>>> ^ >>>>> <console>:6: error: covariant type A occurs in invariant position in >>>>> type => Set[Either[A,GCG[A]]] of method right >>>>> trait GCG2[+A] { def left : Set[Either[A,GCG[A]]]; def right : >>>>> Set[Either[A,GCG[A]]] } >>>>> ^