2014-12-21 3 views
4

я застрял на как час, чтобы обнаружить этот факт:Невозможно разрешить класс доказательств зависит путь типа ж/о, имеющий тип значения доступной

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 не находит implicits в типе, у которого нет типа значения, доступного на любом префиксе. На него нельзя ссылаться. Очевидно, Scalac должен получить доступ к этому Foo.this.foo, чтобы разрешить имплициты в нем, чего в этом случае он не может.

Я чувствую, что если вы комбинируете классы типов и типы, зависящие от пути, вы эффективно обречены. В конечном итоге вы столкнетесь с такими вещами. Я сделал это, потому что scalac не мог бы вызывать типы в моих API-методах, и пользователь должен был бы объявить их явно. Таким образом, я выбрал такой дизайн, чтобы типы были построены в Foo[T], а методы api используют существующий тип, но я ударил несколько действительно уродливых проблем и ошибок такого типа, что сделало мое приложение похожим на overengineered дерьмо ...

ответ

4

зависимые типы Пути может быть связаны только с некоторыми устойчивыми неизменными значениями, так что более очевидный пример также не будет работать, потому что неизменность не гарантируются:

scala> var foo = new Foo() 
foo: Foo = [email protected] 

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 = [email protected] 

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, поэтому он рассматривается как нестабильная.

+0

, так что у моего последнего фрагмента есть неизменный идентификатор, который нестабилен, потому что он находится в области метода, так что это тоже не работает? 'def method() = {// это не скомпилируется, если оно находится в пределах области метода val foo = new Foo() foo.foo [Int] (4) } ' – lisak

+0

Фактически последний фрагмент работает для меня - Scala REPL 2.11.2 – dk14

+0

Я также объявил его внутри объекта (см. Обновление в своем ответе) и запускал/скомпилировал с помощью scala/scalac - и он работает – dk14