Reputation: 753
Why this is allowed:
class Foo[O: Option](s: String)
new Foo[Any]("foo")(None)
while this is not:
class Foo[O: Option](s: String) {
def this() = this("foo")(None)
}
compiler message:
Foo[O] does not take parameters
Is there any way to provide context bound explicitly in a constructor?
Upvotes: 2
Views: 403
Reputation: 39577
The Good Book says that the context bound is equivalent to the implicit evidence.
As @gabriele-petronella noted:
class Foo[O](s: String)(implicit o: Option[O]) {
def this() = this("foo")(None)
}
But in the presence of a context bound, the parser automatically appends the evidence parameter:
class Foo[O] extends scala.AnyRef {
<paramaccessor> private[this] val s: String = _;
implicit <synthetic> <paramaccessor> private[this] val evidence$1: Option[O] = _;
def <init>(s: String)(implicit evidence$1: Option[O]) = {
super.<init>();
()
};
def <init>()(implicit evidence$2: Option[O]) = {
<init>("foo")(None)(evidence$2);
()
}
}
So the error is due to the appended arg.
It's also true that you can't do anything in a secondary constructor to force a type parameter, that is, to instantiate it to a particular type arg. (See here.)
The reason the workaround works is that None <:< Option[Nothing] <:< Option[O]
for any type param.
As @gabriele-petronella also noted, in the companion you can do whatever:
object Foo { def apply() = new Foo[Int]("five")(Some(5)) }
Arguably, the compiler could wait to decide which constructor you mean to invoke and then whether an implicit is required, and ignore the implicit to your secondary ctor in that case. But constructors are intentionally simple in Scala.
Upvotes: 3