This page is no longer maintained — Please continue to the home page at www.scala-lang.org

why traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'

8 replies
linjie nie
Joined: 2009-06-17,
User offline. Last seen 42 years 45 weeks ago.
Hi list -
I am very new to scala
just have a error saying 'traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
Could you please let me know why we have this limitation?
Thanks a lot.


Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: why traits cannot have type parameters with context bounds
Context bounds + view bounds are really syntactic sugar.
def foo[X: T] = ...
is really
def foo[X](implicit $ev0: T[X])

And 
def foo[X <% T] = ...
is really
def foo[X](implicit $ev0: X => T) = ..

traits are not allowed to have value parameters, so any sort of "implicit" constraint is not allowed.   What you can do is:
trait Foo[A] {  implicit def myT: T[A]}
and then manually set the implicit value as needed, like so:
def newFoo[A : T] = new Foo[A] {    override val myT = implicitly}

Hope that helps!- Josh
On Sun, Nov 27, 2011 at 8:42 AM, linjie nie <nielinjie@gmail.com> wrote:
Hi list -
I am very new to scala
just have a error saying 'traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
Could you please let me know why we have this limitation?
Thanks a lot.



odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: why traits cannot have type parameters with context bounds
Josh explained it well: To support context bounds we would need traits that can take parameters. It's something we want to do eventually, but have not yet gotten around to specify and implement fully.
Best,
 -- Martin



On Sun, Nov 27, 2011 at 3:13 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
Context bounds + view bounds are really syntactic sugar.
def foo[X: T] = ...
is really
def foo[X](implicit $ev0: T[X])

And 
def foo[X <% T] = ...
is really
def foo[X](implicit $ev0: X => T) = ..

traits are not allowed to have value parameters, so any sort of "implicit" constraint is not allowed.   What you can do is:
trait Foo[A] {  implicit def myT: T[A]}
and then manually set the implicit value as needed, like so:
def newFoo[A : T] = new Foo[A] {    override val myT = implicitly}

Hope that helps!- Josh
On Sun, Nov 27, 2011 at 8:42 AM, linjie nie <nielinjie@gmail.com> wrote:
Hi list -
I am very new to scala
just have a error saying 'traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
Could you please let me know why we have this limitation?
Thanks a lot.






--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967

Jon Steelman
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: why traits cannot have type parameters with context bounds
When I say a parameter, I really mean for the self-type to be specified as any subclass of a particular type.

On Sun, Nov 27, 2011 at 11:47 AM, Jon Steelman <jon.steelman@gmail.com> wrote:
I take it that the self-type of a Trait can't be a parameter? For example, I'd like for the trait method to override a method of the self type and call the super's method within. When attempting it without being able to use a parameter, you get that the method doesn't exist in Any.

Thanks,
Jon
P.S. For self-type, is either self: or this: preferred? (Is one going to be eventually deprecated?)

On Sun, Nov 27, 2011 at 11:26 AM, martin odersky <martin.odersky@epfl.ch> wrote:
Josh explained it well: To support context bounds we would need traits that can take parameters. It's something we want to do eventually, but have not yet gotten around to specify and implement fully.
Best,
 -- Martin



On Sun, Nov 27, 2011 at 3:13 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
Context bounds + view bounds are really syntactic sugar.
def foo[X: T] = ...
is really
def foo[X](implicit $ev0: T[X])

And 
def foo[X <% T] = ...
is really
def foo[X](implicit $ev0: X => T) = ..

traits are not allowed to have value parameters, so any sort of "implicit" constraint is not allowed.   What you can do is:
trait Foo[A] {  implicit def myT: T[A]}
and then manually set the implicit value as needed, like so:
def newFoo[A : T] = new Foo[A] {    override val myT = implicitly}

Hope that helps!- Josh
On Sun, Nov 27, 2011 at 8:42 AM, linjie nie <nielinjie@gmail.com> wrote:
Hi list -
I am very new to scala
just have a error saying 'traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
Could you please let me know why we have this limitation?
Thanks a lot.






--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967



Jon Steelman
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: why traits cannot have type parameters with context bounds
I take it that the self-type of a Trait can't be a parameter? For example, I'd like for the trait method to override a method of the self type and call the super's method within. When attempting it without being able to use a parameter, you get that the method doesn't exist in Any.

Thanks,
Jon
P.S. For self-type, is either self: or this: preferred? (Is one going to be eventually deprecated?)

On Sun, Nov 27, 2011 at 11:26 AM, martin odersky <martin.odersky@epfl.ch> wrote:
Josh explained it well: To support context bounds we would need traits that can take parameters. It's something we want to do eventually, but have not yet gotten around to specify and implement fully.
Best,
 -- Martin



On Sun, Nov 27, 2011 at 3:13 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
Context bounds + view bounds are really syntactic sugar.
def foo[X: T] = ...
is really
def foo[X](implicit $ev0: T[X])

And 
def foo[X <% T] = ...
is really
def foo[X](implicit $ev0: X => T) = ..

traits are not allowed to have value parameters, so any sort of "implicit" constraint is not allowed.   What you can do is:
trait Foo[A] {  implicit def myT: T[A]}
and then manually set the implicit value as needed, like so:
def newFoo[A : T] = new Foo[A] {    override val myT = implicitly}

Hope that helps!- Josh
On Sun, Nov 27, 2011 at 8:42 AM, linjie nie <nielinjie@gmail.com> wrote:
Hi list -
I am very new to scala
just have a error saying 'traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
Could you please let me know why we have this limitation?
Thanks a lot.






--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967


odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: why traits cannot have type parameters with context bounds


On Sun, Nov 27, 2011 at 5:47 PM, Jon Steelman <jon.steelman@gmail.com> wrote:
I take it that the self-type of a Trait can't be a parameter? For example, I'd like for the trait method to override a method of the self type and call the super's method within. When attempting it without being able to use a parameter, you get that the method doesn't exist in Any.

Can you give an example? 

P.S. For self-type, is either self: or this: preferred? (Is one going to be eventually deprecated?)
Neither is preferred. self: has the advantage that it gives you a name for the other trait that you can access in inner classes. If you don't need that then I prefer this: because it does not spend an unneeded name.
Cheers
 -- Martin
Jon Steelman
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: why traits cannot have type parameters with context bounds
This attempt is in the sbt 0.7.x context:  trait unitTestReporting {    this: BasicScalaProject =>    abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)     def junitXmlListener: TestReportListener = new JUnitXmlTestsListener(outputPath.toString())  }
Here's the error, which makes perfect sense:  [error] /Users/jonsteelman/IdeaProjects/tsthotel/project/build/Project.scala:37: value testListeners is not a member of java.lang.Object with ScalaObject   [error]     abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)
If I could specify this: as any descendant of BasicScalaProject, then the super.testListeners would work.
Thanks,Jon

On Sun, Nov 27, 2011 at 1:04 PM, martin odersky <martin.odersky@epfl.ch> wrote:


On Sun, Nov 27, 2011 at 5:47 PM, Jon Steelman <jon.steelman@gmail.com> wrote:
I take it that the self-type of a Trait can't be a parameter? For example, I'd like for the trait method to override a method of the self type and call the super's method within. When attempting it without being able to use a parameter, you get that the method doesn't exist in Any.

Can you give an example? 

P.S. For self-type, is either self: or this: preferred? (Is one going to be eventually deprecated?)
Neither is preferred. self: has the advantage that it gives you a name for the other trait that you can access in inner classes. If you don't need that then I prefer this: because it does not spend an unneeded name.
Cheers
 -- Martin

adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: why traits cannot have type parameters with context bounds


On Sun, Nov 27, 2011 at 7:15 PM, Jon Steelman <jon.steelman@gmail.com> wrote:
This attempt is in the sbt 0.7.x context:  trait unitTestReporting {    this: BasicScalaProject =>    abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)     def junitXmlListener: TestReportListener = new JUnitXmlTestsListener(outputPath.toString())  }
Here's the error, which makes perfect sense:  [error] /Users/jonsteelman/IdeaProjects/tsthotel/project/build/Project.scala:37: value testListeners is not a member of java.lang.Object with ScalaObject   [error]     abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)
If I could specify this: as any descendant of BasicScalaProject, then the super.testListeners would work.
the semantics of a self-type is more limited than that: it only specifies the assumed (required) type of the this reference (whatever you call it -- me, self, or this)complementary to that, when you instantiate a type, the compiler ensures that those assumptions are valid (i.e., that the instantiated type is a subtype of the assumed self-type)
we experimented with taking self types into account for overriding, but, as far as I remember, that turned out to be quite problematicI think having them play a role in super calls would present a similar (if not bigger) challenge
cheersadriaan
Jon Steelman
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: why traits cannot have type parameters with context bounds
Appreciate the clarification. Good to know where the self-typing limits are along with the challenges posed by going richer. Would have been nice if self-type allowed a super call, but I found a work-around.
Thanks,Jon

On Sun, Nov 27, 2011 at 4:21 PM, Adriaan Moors <adriaan.moors@epfl.ch> wrote:


On Sun, Nov 27, 2011 at 7:15 PM, Jon Steelman <jon.steelman@gmail.com> wrote:
This attempt is in the sbt 0.7.x context:  trait unitTestReporting {    this: BasicScalaProject =>    abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)     def junitXmlListener: TestReportListener = new JUnitXmlTestsListener(outputPath.toString())  }
Here's the error, which makes perfect sense:  [error] /Users/jonsteelman/IdeaProjects/tsthotel/project/build/Project.scala:37: value testListeners is not a member of java.lang.Object with ScalaObject   [error]     abstract override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)
If I could specify this: as any descendant of BasicScalaProject, then the super.testListeners would work.
the semantics of a self-type is more limited than that: it only specifies the assumed (required) type of the this reference (whatever you call it -- me, self, or this)complementary to that, when you instantiate a type, the compiler ensures that those assumptions are valid (i.e., that the instantiated type is a subtype of the assumed self-type)
we experimented with taking self types into account for overriding, but, as far as I remember, that turned out to be quite problematicI think having them play a role in super calls would present a similar (if not bigger) challenge
cheersadriaan

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland