Understanding "type arguments do not conform to type parameter bounds" errors in Scala
Asked Answered
S

2

6

Why don't the following work?

scala> abstract class Foo[B<:Foo[B]]
defined class Foo

scala> class Goo[B<:Foo[B]](x: B)
defined class Goo

scala> trait Hoo[B<:Foo[B]] { self: B => new Goo(self) }
<console>:9: error: inferred type arguments [Hoo[B] with B] do not conform to class Goo's type parameter bounds [B <: Foo[B]]
       trait Hoo[B<:Foo[B]] { self: B => new Goo(self) }
                                         ^

scala> trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) }
<console>:9: error: inferred type arguments [Hoo[B]] do not conform to class Goo's type parameter bounds [B <: Foo[B]]
       trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) }
                                             ^

In the first attempt, isn't Hoo[B] with B <: Foo[B]?

In the second attempt, isn't Hoo[B] <: Foo[B]?

To motivate this problem, there's a library with:

// "Foo"
abstract class Record[PK, R <: Record[PK, R]] extends Equals { this: R =>
  implicit def view(x: String) = new DefinitionHelper(x, this)
  ...
}
// "Hoo"
class DefinitionHelper[R <: Record[_, R]](name: String, record: R) {
  def TEXT = ...
  ...
}

// now you can write:
class MyRecord extends Record[Int, MyRecord] {
  val myfield = "myfield".TEXT
}

I'm trying to introduce a new extension method alongside TEXT called BYTEA, so that one can write:

class MyRecord extends XRecord[Int, MyRecord] {
  val myfield = "myfield".BYTEA // implicit active only inside this scope
}

My attempts:

class XDefinitionHelper[R <: Record[_, R]](name: String, record: R) {
  def BYTEA = ...
}

trait XRecord[PK, R <: Record[PK, R]] { self: R =>
  implicit def newView(x: String) = new XDefinitionHelper(x, self)
}

But this runs into the same problems as my smaller test case above.

Saki answered 27/7, 2011 at 7:11 Comment(0)
A
2

In the first attempt, you do have Hoo[B] with B <: Foo[B]. But for Goo[Hoo[B] with B] to exist, you need Hoo[B] with B <: Foo[Hoo[B] with B]. Similarly in the second case.

Alfi answered 27/7, 2011 at 8:30 Comment(3)
Thanks, I now see how to fix my second attempt (using extends Foo[Hoo[B]]), but how would one fix the first form (using the self-type)?Saki
Also having trouble taking this further. I need to define a class Ioo[B<:Ioo[B]] extends Hoo[B] { new Goo(this) } but that doesn't work. Nor does extends Hoo[Ioo[B]]. But class Ioo[B<:Foo[B]] extends Hoo[B] works, calling Goo on an instance of Ioo from within Hoo. Yet I can't do that from within Ioo.Saki
The above should actually be: I need to define a class Ioo extends Hoo[Ioo] { new Goo(this) } but that doesn't work. Nor does extends Hoo[Foo[Ioo]].Saki
H
0

This seems too simple to be true (ie.: to be a good practice), but this saved my day anyway, so where it is:

scala> trait MyTrait[T <: MyTrait[T]] { self: T => def hello = println("hello") }

scala> case class User(t: MyTrait[_])
<console>:8: error: type arguments [_$1] do not conform to trait MyTrait's type parameter bounds [T <: MyTrait[T]]
       case class User(t: MyTrait[_])

scala> case class User(t: () => MyTrait[_])
defined class User
Heshum answered 21/8, 2013 at 15:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.