How to define that an abstract type is going to be a case class with a limitation on members' type?

I have an abstract class TSData which has abstract type T, T is going to be implemented as a case class. So I defined it this way:

      abstract case class A()
      type T<:A

I wanted to create a concrete method in TSData which uses method from another library, but I get this error:

Error:(23, 53) Type info for type ‘TSData.this.T’ not available. Make sure it is a (nested) case class with [Double or Int or Boolean or Seq[Double]] members only.

As I understood from this error, my type T isn’t limited to have the members of only certain types mentioned above. Right? How can I make such constraints? Should I use Manifest here somehow?

Oh, I thought it was a standard error, I just found it in the library I use, it is triggered by @implicitNotFound.

So I guess it has nothing to do with the type constraints, it just appeared since it couldn’t find the type…

I guess also that Manifest couldn’t help there?

Then the only thing you can do is make sure that the relevant implicit is in scope for type T.

Thanks, I understood that there is nothing I can do, I will have to define it in each concrete class. I just didn’t understand the words you used:

What does mean being in scope for a type? I understood the problem as that @implicitNotFound will not accept an abstract type, and it is put there by the reason cos a function has to do some tests on that type’s properties. I didn’t see this as a scope problem, can you explain?

I don’t know which library or classes we are talking about, so I’ll assume there is something like this somewhere:

@implicitNotFound("Type info for type ‘${A}’ not available. Make sure it is a (nested) case class with [Double or Int or Boolean or Seq[Double]] members only.")
trait Foo[A]

Then there is some method which requires an implicit Foo:

def foo[A](implicit foo: Foo[A]) = ???

This library probably has some implicit macros that generate an implicit Foo[X] for every X which is a case class with the right kind of members.

You have something like this:

abstract case class A()
trait Bar {
  type T <: A
  def bar() = println(foo[T])
}

This fails because that macro does not know whether or not the abstract type T conforms to its requirements. So at the point where you call foo[T] there is no implicit Foo[T] in scope. To fix that you have to make sure there is one in scope. Usually you do this by adding an implicit parameter to the method where you need that implicit ( def bar()(implicit fooT: Foo[T]) = println(foo[T]) ). Although in this case T is not a type parameter of method bar so you could also do this:

trait Bar {
  type T <: A
  implicit def fooT: Foo[T]
  def bar() = println(foo[T])
}
// and then
class Baz extends Bar {
  type T = MyCaseClass
  implicit val fooT: Foo[MyCaseClass] = {
    def fooT = ??? // shadow fooT, required to avoid implicitly finding itself
    implicitly[Foo[MyCaseClass]]
  }
}
1 Like

Wow, that is a whole lot an answer! Situation is exactly as you described…

I will have to spend some time there to understand each of the parts.

Thank You!