2016-01-16 4 views
3

В настоящее время я работаю над реализацией A * в Scala. Чтобы выполнить чистую структуру, я хотел бы использовать вложенную структуру классов case, которая реализует самоограниченный признак. Тем не менее, я испытываю некоторые проблемы при реализации этого в среде Scala IDE. Следующий код не скомпилируется:Scala вложенный класс класса самоограничивающегося наследования

trait A[T <: A[T]] 

class B { 

    case class C(int: Int) extends A[C] // A[this.C] won't work either 

    def make = C(5) 

} 

object D { 

    def foo[T <: A[T]](some: T) = {} 

    val c = new B().make 

    foo(c) // this does not compile 

} 

Есть ли способ, которым я могу заставить эту структуру работать?

+0

Приятная объяснение пути в зависимости от типов могут быть найдено по адресу http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types – manub

ответ

5

Не знаю, почему вы хотите, но вот почему она не будет работать как:

Тип D.c является B#C. Это зависимый от пути тип, где мы не знаем, к какому экземпляру принадлежит B. Однако C расширяет A[C], что уже совпадает с A[this.C] в этом контексте, который привязан к конкретному экземпляру B. foo видит параметр типа T как B#C, что не совпадает с b.C для некоторых b.

У вас есть два варианта компиляции.

Расслабьте ограничения A к B#C:

trait A[T <: A[T]] 

class B { 

    case class C(int: Int) extends A[B#C] 

    def make = C(5) 

} 

object D { 

    def foo[T <: A[T]](some: A[T]) = {} 

    val c = new B().make 

    foo(c) 

} 

Или обрабатывать пути в зависимости от типа, так что c имеет тип b.C:

trait A[T <: A[T]] 

class B { 

    case class C(int: Int) extends A[C] 

    def make = C(5) 

} 

object D { 

    def foo[T <: A[T]](some: A[T]) = {} 

    val b = new B 
    val c: b.C = b.make 

    foo(c) 

} 
+0

Спасибо! Это объясняло многое! – Y4sper

+0

Явный тип на 'c' в последнем примере на самом деле не нужен, я нашел. Мне хотелось бы объяснить, почему введение промежуточного значения val 'b' изменяет предполагаемый тип' c'. Я понимаю, что нет никакого имени для промежуточного значения без 'b', но не так, как это имеет значение для вывода. –

+0

Я не думаю, что есть спецификация для правил вывода типов, так что я в затруднении. Я просто не думаю, что тип inferencer достаточно умен в этом случае, чтобы сделать все это в одном утверждении - похожее на то, почему вам нужно карри аргументы, такие как 'def f (b: B) (c: b.C)' –

Смежные вопросы