简体   繁体   English

抽象类型成员的评估

[英]evaluation of an abstract type member

Why this code won't compile?为什么这段代码不能编译? Tested on Scala 2.13.6.在 Scala 2.13.6 上测试。 Is there a way to let scalac know that SizeOfType[Unit]#Size is actually Short ?有没有办法让 scalac 知道SizeOfType[Unit]#Size实际上是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当使用类型成员而不是类型参数进行参数化时,您必须在要求类型 class 实例时提供类型细化,否则您只要求 Scala

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)通常你会创建依赖类型的方法,然后你可以避免方法定义中的类型细化(但它仍然需要定义类型 class 实例)

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我建议通过underscoreio/shapeless-guide的“第 4 章,使用类型和隐含”进行学习,特别是其中提到的部分

...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. ...如果我们将返回类型定义为Second[L] ,则Out类型成员将从返回类型中删除,并且类型 class 将无法正常工作。

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 .想想如果你用另一个定义type Size = IntSizeOfType[Unit]类型的隐式值调用test会发生什么。

Or said differently, the method test can only infer types based on the trait definition of SizeOfType , not on one actual implicit value content.或者换一种说法,方法test只能根据SizeOfType的 trait 定义来推断类型,而不是根据一个实际的隐含值内容。

You could however define test as returning the type ev.Size .但是,您可以将test定义为返回类型ev.Size

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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