简体   繁体   English

Scala中依赖类型的隐式解析

[英]Implicit resolution of dependent types in Scala

Consider the following piece of code: 考虑以下代码:

trait Foo {
  type T
  def value: T
}

object Foo {
  def apply[A](v: A): Foo = new Foo {
    override type T = A
    override def value = v
  }
}

trait Decode[A] {
  def apply(x: A): String
}

object Decode {
  def apply[A](f: A => String): Decode[A] = new Decode[A] {
    override def apply(x: A) = f(x)
  }

  implicit val decodeStr: Decode[String] = Decode(identity)
}

class Sandbox {
  def decodeFoo(foo: Foo)(implicit decoder: Decode[foo.T]): String =
    decoder(foo.value)

  val foo = Foo("hello")
  println(decodeFoo(foo))
}

The above code should work fine and print hello but instead it fails to compile: 上面的代码应该工作正常并打印hello但它无法编译:

could not find implicit value for parameter decoder: Decode[Sandbox.this.foo.T]
[error]   println(decodeFoo(foo))

Even when I explicitly pass in the implicit param: 即使我明确传入隐式参数:

println(decodeFoo(foo = foo)(decoder = Decode.decodeStr))

I still get this error now: 我现在仍然收到此错误:

type mismatch;
[error]  found   : Decode[String]
[error]  required: Decode[Sandbox.this.foo.T]
[error]   println(decodeFoo(foo = foo)(decoder = Decode.decodeStr))
[error]                                                 ^

Ofcourse, I can make Foo a Foo[T] and define decoders for it but that's not the point of this question - I want to understand why the above code fails to compile. 当然,我可以让Foo成为Foo[T]并为它定义解码器,但这不是这个问题的重点 - 我想理解为什么上面的代码无法编译。

The problem exists here: 这里存在的问题是:

object Foo {
  def apply[A](v: A): Foo = new Foo {
    override type T = A
    override def value = v
  }
}

There, you've established that you will return a Foo but not, specifically, which Foo . 在那里,你已经确定你将返回一个Foo但不是,特别是,哪个Foo Hence, that function only knows that it can return a Foo for any type T . 因此,该函数只知道它可以返回任何类型TFoo You need an Aux pattern to recapture the type which is lost when establishing your new Foo (yes, yes...) 你需要一个Aux模式来重新获得在建立新Foo时丢失的类型(是的,是的......)

object Foo {
  type Aux[A] = Foo{ type T = A }

  def apply[A](v: A): Aux[A] = new Foo {
    type T = A
    def value = v
  }
}

which then says that for a given A produce the Foo which has it's T dependent type set to A . 然后说对于给定的A产生Foo ,它的T依赖类型设置为A

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

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