Michael Taylor
Michael Taylor

Reputation: 35

Implicit conversion to make generic type available

I am using a library which has a class that has a generic type that can be quite complicated. I need to write a method that takes a parameter with the generic type that a val of the library class has, and I would like to avoid having to write out the type in the method signature. I thought I might be able to create an implicit class which adds a type to the val that I could use in the method signature, kind of like:

// This comes from a library and can't be changed
case class LibraryClass[A](a: A)

//----------------------------------

object MyCode {
  val thing = LibraryClass(3)

  implicit class LibraryClassWithType[A](lc: LibraryClass[A]) {
    type TheType = A
  }

  def doStuff(something: thing.TheType): Unit = {
    println(something)
  }
}

This does not compile (TheType is not a member of LibraryClass). But if I wrap it in the class myself, it works

  val thingWithType = LibraryClassWithType(thing)
  def doStuff(something: thingWithType.TheType): Unit = {
    println(something)
  }

Is there something I am missing that will make this work, or is this kind of implicit conversion not valid Scala?

Upvotes: 2

Views: 98

Answers (2)

experquisite
experquisite

Reputation: 879

I haven't been able to do this sort of thing with implicits, but I have had to do something similar where I just instantiated these sorts of type holders:

case class LibraryClass[A](a: A)

object MyCode {
  val thing = LibraryClass(3)

  class HigherTypeHolder[A,F[A]](a: F[A]) {
    type AT = A
  }
  val th = new HigherTypeHolder(thing)

  def doStuff(something: th.AT): Unit = {
    println(something)
  }
}

Upvotes: 0

Dima
Dima

Reputation: 40500

You can do what (I think) you want like this:

implicit val thing = LibraryClass(3)
def doStuff[A](something: A)(implicit lc: LibraryClass[A])

What I don't understand is why this needs to be so complicated. Why not for example stick with your second approach, without implicits, that works, or why not just do def doStuff[A](something: A) to begin with?

Upvotes: 0

Related Questions