2016-04-16 35 views
2

我一直在寻找无形单例的细节,并遇到一个小例子,不能按预期方式工作。我认为,只要我们通过一个单类型的方法中,应该有一个隐含的Witness.Aux [_]在可用范围:编译器无法找到隐式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中的例子中,以是一样的(并用=:=检查它是否成功)。如果我添加一个隐含的见证人[Witness。手动将代码编译为'key .T]。

环境:斯卡拉2.11.8; Shapeless 2.3.0

回答

4

解释是Scala编译器会在推断左侧val的类型时在右侧扩展单例类型......您将在Scala的the relevant section中找到章节和章节语言规范。

下面是同一现象的独立于无形的例子,

scala> class Foo ; val foo = new Foo 
defined class Foo 
foo: Foo = [email protected] 

scala> val f1 = foo 
f1: Foo = [email protected] 

scala> val f2: foo.type = foo 
f2: foo.type = [email protected] 

正如你可以从f2定义Scala编译器知道该值foo有更精确的类型foo.type(即单身看但是,除非明确要求,否则不会推断出更精确的类型。相反,它会推断非单例(即加宽)类型Foo,正如您在f1的情况下所看到的那样。请参阅this related answer

相关问题