【问题标题】:Unable to resolve path dependent type class evidence w/o having value type accessible无法解析路径相关的类型类证据,而没有可访问的值类型
【发布时间】:2014-12-21 13:24:01
【问题描述】:

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

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 方法使用现有的类型,但是我遇到了几个非常丑陋的问题和错误,让我的应用看起来像一个过度设计的废话......

【问题讨论】:

    标签: scala implicit scalac path-dependent-type


    【解决方案1】:

    依赖路径的类型可能只绑定到一些稳定的不可变值,所以更明显的例子也行不通,因为不能保证不变性:

    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 后才简单地推断类型。它实际上与隐式无关,这将为您提供更清晰的解释:

    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,因此它被认为是不稳定的。

    【讨论】:

    • 所以我的最后一个 sn-p 有一个不稳定的标识符,因为它在方法范围内,所以它也不起作用? ` def method() = { // 如果它在方法范围内,也不会编译 val foo = new Foo() foo.foo[Int](4) }'
    • 实际上最后一个 sn-p 对我有用 - Scala REPL 2.11.2
    • 我还在对象内部声明了它(请参阅我的答案中的更新)并使用 scala/scalac 运行/编译 - 它可以工作
    • 但是在这里您在类本身中声明了隐式 val - 隐式不能以这种方式工作(它们应该在伴随对象中定义),请参阅docs.scala-lang.org/tutorials/FAQ/finding-implicits.html。或者只是import foo._
    • UPS,我玩的时候把它给忘记了,对不起...谢谢dk14,你明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    相关资源
    最近更新 更多