Discussion:
why traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
linjie nie
2011-11-27 13:42:24 UTC
Permalink
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.
Josh Suereth
2011-11-27 14:13:29 UTC
Permalink
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
Post by linjie nie
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
2011-11-27 16:26:10 UTC
Permalink
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
Post by Josh Suereth
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"
trait Foo[A] {
implicit def myT: T[A]
}
def newFoo[A : T] = new Foo[A] {
override val myT = implicitly
}
Hope that helps!
- Josh
Post by linjie nie
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 <http://www.epfl.ch> and Chairman, Typesafe<http://www.typesafe.com>
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Jon Steelman
2011-11-27 16:47:41 UTC
Permalink
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?)
Post by martin odersky
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
Post by Josh Suereth
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
trait Foo[A] {
implicit def myT: T[A]
}
def newFoo[A : T] = new Foo[A] {
override val myT = implicitly
}
Hope that helps!
- Josh
Post by linjie nie
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 <http://www.epfl.ch> and Chairman, Typesafe<http://www.typesafe.com>
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Jon Steelman
2011-11-27 16:48:50 UTC
Permalink
When I say a parameter, I really mean for the self-type to be specified as
any subclass of a particular type.
Post by Jon Steelman
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?)
Post by martin odersky
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
Post by Josh Suereth
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
trait Foo[A] {
implicit def myT: T[A]
}
def newFoo[A : T] = new Foo[A] {
override val myT = implicitly
}
Hope that helps!
- Josh
Post by linjie nie
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 <http://www.epfl.ch> and Chairman, Typesafe<http://www.typesafe.com>
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
martin odersky
2011-11-27 18:04:34 UTC
Permalink
Post by Jon Steelman
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?
Post by Jon Steelman
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
2011-11-27 18:15:32 UTC
Permalink
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
Post by martin odersky
Post by Jon Steelman
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?
Post by Jon Steelman
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
Adriaan Moors
2011-11-27 21:21:21 UTC
Permalink
Post by Jon Steelman
trait unitTestReporting {
this: BasicScalaProject =>
abstract override def testListeners: Seq[TestReportListener] =
super.testListeners ++ Seq(junitXmlListener)
def junitXmlListener: TestReportListener = new
JUnitXmlTestsListener(outputPath.toString())
}
[error]
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 problematic
I think having them play a role in super calls would present a similar (if
not bigger) challenge

cheers
adriaan
Jon Steelman
2011-11-27 22:54:36 UTC
Permalink
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
Post by Adriaan Moors
Post by Jon Steelman
trait unitTestReporting {
this: BasicScalaProject =>
abstract override def testListeners: Seq[TestReportListener] =
super.testListeners ++ Seq(junitXmlListener)
def junitXmlListener: TestReportListener = new
JUnitXmlTestsListener(outputPath.toString())
}
[error]
value testListeners is not a member of java.lang.Object with ScalaObject
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 problematic
I think having them play a role in super calls would present a similar (if
not bigger) challenge
cheers
adriaan
Loading...