2011-07-27 10 views
6

Dlaczego następujące czynności nie działają?Zrozumienie "argumentów typu nie jest zgodne z błędami parametru typu" w Scali

scala> abstract class Foo[B<:Foo[B]] 
defined class Foo 

scala> class Goo[B<:Foo[B]](x: B) 
defined class Goo 

scala> trait Hoo[B<:Foo[B]] { self: B => new Goo(self) } 
<console>:9: error: inferred type arguments [Hoo[B] with B] do not conform to class Goo's type parameter bounds [B <: Foo[B]] 
     trait Hoo[B<:Foo[B]] { self: B => new Goo(self) } 
             ^

scala> trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) } 
<console>:9: error: inferred type arguments [Hoo[B]] do not conform to class Goo's type parameter bounds [B <: Foo[B]] 
     trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) } 
              ^

Przy pierwszej próbie nie jest to Hoo[B] with B <: Foo[B]?

Przy drugiej próbie nie jest to Hoo[B] <: Foo[B]?

Aby zmotywować ten problem, jest biblioteka z:

// "Foo" 
abstract class Record[PK, R <: Record[PK, R]] extends Equals { this: R => 
    implicit def view(x: String) = new DefinitionHelper(x, this) 
    ... 
} 
// "Hoo" 
class DefinitionHelper[R <: Record[_, R]](name: String, record: R) { 
    def TEXT = ... 
    ... 
} 

// now you can write: 
class MyRecord extends Record[Int, MyRecord] { 
    val myfield = "myfield".TEXT 
} 

próbuję wprowadzić nową metodę rozszerzenia obok tekstowy o nazwie bytea, tak, że można napisać:

class MyRecord extends XRecord[Int, MyRecord] { 
    val myfield = "myfield".BYTEA // implicit active only inside this scope 
} 

My Próby:

class XDefinitionHelper[R <: Record[_, R]](name: String, record: R) { 
    def BYTEA = ... 
} 

trait XRecord[PK, R <: Record[PK, R]] { self: R => 
    implicit def newView(x: String) = new XDefinitionHelper(x, self) 
} 

Ale to prowadzi do tych samych problemów, co mój mniejszy przypadek testowy powyżej.

Odpowiedz

2

Przy pierwszej próbie masz Hoo[B] with B <: Foo[B]. Ale aby Goo[Hoo[B] with B] istniał, potrzebujesz Hoo[B] with B <: Foo[Hoo[B] with B]. Podobnie w drugim przypadku.

+0

Dzięki, teraz widzę, jak rozwiązać mój drugi próba (użycie 'extends Foo [Hoo [B]]'), ale jak naprawić jedną formę (używając self-type)? – Yang

+0

Masz również problem z kontynuowaniem tego. Muszę zdefiniować 'class Ioo [B <: Ioo [B]] rozszerza Hoo [B] {new Goo (this)}, ale to nie działa. "Nie rozszerza także Hoo [Ioo [B]]". Ale 'class Ioo [B <: Foo [B]] rozszerza Hoo [B]' działa, nazywając 'Goo' na instancji' Ioo' od wewnątrz 'Hoo'. Jednak nie mogę tego zrobić z poziomu 'Ioo'. – Yang

+0

Powyższe powinno być w rzeczywistości: muszę zdefiniować 'class Ioo extends Hoo [Ioo] {new Goo (this)}, ale to nie działa. Ani 'nie rozszerza Hoo [Foo [Ioo]]'. – Yang

0

To wydaje się zbyt proste, aby mogło być prawdziwe (tzn .: być dobrą praktyką), ale to i tak uratował mój dzień, więc gdzie to jest:

scala> trait MyTrait[T <: MyTrait[T]] { self: T => def hello = println("hello") } 

scala> case class User(t: MyTrait[_]) 
<console>:8: error: type arguments [_$1] do not conform to trait MyTrait's type parameter bounds [T <: MyTrait[T]] 
     case class User(t: MyTrait[_]) 

scala> case class User(t:() => MyTrait[_]) 
defined class User 
Powiązane problemy