无法解析路径依赖类型类证据,无需访问值类型

时间:2014-12-21 13:24:01

标签: scala implicit scalac path-dependent-type

我被困了一个小时才发现这个事实:

class Foo {
  trait TypeClass[X]
  object TypeClass {
    implicit val gimme = new TypeClass[Int]{}
  }

  def foo[X : TypeClass](p: X): Unit = println("yeah " + p)
}

    // compiles
val foo = new Foo()
foo.foo(4)

    //does not compile
new Foo().foo(4)

    could not find implicit value for evidence parameter of type _1.TypeClass[Int]
    [error]   new Foo().foo(4)
    [error]    

我无法弄清楚为什么会这样。我唯一能想到的是scalac在一个没有任何前缀可访问值类型的类型中找不到含义。它不能被引用。 Scalac显然需要访问Foo.this.foo以解决其中的隐含问题,在这种情况下它无法解决。

我觉得如果你结合类型类和路径依赖类型,你实际上是注定要失败。你最终会处理这类事情。我这样做是因为scalac不会在我的API方法中推断类型,用户必须明确声明它们。所以我选择了这种设计,以便在Foo[T]中构造类型,并且api方法使用现有类型,但是我遇到了几个非常难看的问题和这种类型的错误使我的应用程序看起来像一个过度设计的垃圾......

1 个答案:

答案 0 :(得分:4)

路径依赖类型可能只绑定到某些稳定的不可变值,因此更明显的例子也不起作用,因为不能保证不变性:

scala> var foo = new Foo()
foo: Foo = Foo@4bc814ba

scala> foo.foo(4)
<console>:17: error: could not find implicit value for evidence parameter of type    _37.TypeClass[Int]
          foo.foo(4)
                 ^

scala> def foo = new Foo()
foo: Foo

scala> foo.foo(4)
<console>:17: error: could not find implicit value for evidence parameter of type _39.TypeClass[Int]
          foo.foo(4)
                 ^

_37表示该类型未被推断。因此,scala似乎只是在将其分配给某些val后才推断出类型。它实际上与implicits无关,这将为您提供更清晰的解释:

scala> class C {type K = Int}
defined class C

scala> var z = new C
z: C = C@4d151931

scala> def aaa(a: z.K) = a
<console>:16: error: stable identifier required, but z found.
   def aaa(a: z.K) = a
              ^

scala> def z = new C
z: C

scala> def aaa(a: z.K) = a
<console>:16: error: stable identifier required, but z found.
   def aaa(a: z.K) = a
              ^

您的new Foo表达式与def newFoo = new Foo类似,因此被视为不稳定。