编译器无法为单例符号找到隐式Witness.Aux [_]

时间:2016-04-16 23:04:00

标签: scala shapeless

我一直在研究无形单体的细节,并遇到了一个不能按预期工作的小例子。我认为只要我们将单例类型传递给方法,就应该有一个隐含的Witness.Aux [_]在范围内可用:

import shapeless._
import syntax.singleton._

object SingletonTest extends App {

  def check[K](a: K)(implicit witness: Witness.Aux[K]): Unit = {
    println(witness.value)
  }

  val b = 'key.narrow
  val c: Witness.`'key`.T = b

  check(c) // Works!
  check(b) /* Fails: shapeless.this.Witness.apply is not a valid implicit value                  for shapeless.Witness.Aux[Symbol with  shapeless.tag.Tagged[String("key")]]    because:
                 hasMatchingSymbol reported error: Type argument Symbol with shapeless.tag.Tagged[String("key")] is not a singleton type */
}

我希望示例中的b和c的类型相同(并使用=:= success)进行检查。如果我手动将隐式Witness [Witness。'key。T]添加到范围中,代码就会编译。

环境:Scala 2.11.8;无形2.3.0

1 个答案:

答案 0 :(得分:4)

解释是,在推断左侧val的类型时,Scala编译器将在右侧扩展单例类型...您将在Scala语言的the relevant section中找到章节和经文说明书

这是一个独立于无形状的相同现象的例子,

scala> class Foo ; val foo = new Foo
defined class Foo
foo: Foo = Foo@8bd1b6a

scala> val f1 = foo
f1: Foo = Foo@8bd1b6a

scala> val f2: foo.type = foo
f2: foo.type = Foo@8bd1b6a

f2的定义可以看出,Scala编译器知道值foo具有更精确的类型foo.type(即val foo的单例类型但是,除非明确要求,否则不会推断出更精确的类型。相反,它可以推断非单例(即加宽)类型Foo,如f1中所示。

另见this related answer