简体   繁体   中英

evaluation of an abstract type member

Why this code won't compile? Tested on Scala 2.13.6. Is there a way to let scalac know that SizeOfType[Unit]#Size is actually Short ?

trait SizeOfType[T] {
  type Size
  def getSize(): Size
}

object SizeOfType {
  implicit def unit: SizeOfType[Unit] = new SizeOfType[Unit] {
    type Size = Short
    def getSize(): Short = 0
  }

  def test(implicit ev: SizeOfType[Unit]): Short = ev.getSize()
}
[error] type mismatch;
[error]  found   : ev.Size
[error]  required: Short
[error]   def test(implicit ev: SizeOfType[Unit]): Short = ev.getSize()

When parameterising with type members instead of type parameters you have to provide type refinement when asking for type class instance, otherwise you are only asking Scala for

SizeOfType[Unit]

and not the intended

SizeOfType[Unit] { type Size = Short }

so something like

implicit val unit: SizeOfType[Unit] { type Size = Short } =
  new SizeOfType[Unit] {
    type Size = Short
    def getSize(): Short = 0
  }

def test(implicit ev: SizeOfType[Unit] { type Size = Short }): Short = ev.getSize()
val x: Short = test // ok

Usually you would create dependently typed method and then you can avoid type refinement in the method definition (but it is still needed for definition of type class instance)

implicit val unit: SizeOfType[Unit] { type Size = Short } = ???
def test(implicit ev: SizeOfType[Unit]): ev.Size = ev.getSize()
val x: Short = test // ok

I would suggested studying through "Chapter 4, Working with types and implicits" of underscoreio/shapeless-guide , in particular section which mentions

...If we define the return type as Second[L] , the Out type member will be erased from the return type and the type class will not work correctly.

No, there is no way.

Think about what would happen if you call test with another implicit value of type SizeOfType[Unit] which defines type Size = Int .

Or said differently, the method test can only infer types based on the trait definition of SizeOfType , not on one actual implicit value content.

You could however define test as returning the type ev.Size .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM