2015-04-16 3 views
2

У меня есть три F-Bound типы A, B & C, где B параметризовано A и C параметризовано B (и, следовательно, также A). Я могу создать экземпляр A и B, но когда я пытаюсь создать экземпляр C, компилятор не сможет вывести типы. Если я дам ему типы явно, все работает - но кажется глупым, что эти типы теряются (это из-за стирания типа?).Построение три уровня вложенности F-Bound типы

sealed trait A[AA <: A[AA]] { 
    self => 
    val data: String 
} 

case class AInst(data: String) extends A[AInst] 

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] { 
    self: BB => 
    val content: AA 
} 

case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA] 

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] { 
    self: CC => 
    val content: BB 
} 

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: BB) 
    extends C[CInst[BB, AA], BB, AA] 

val a1 = new AInst("A1") 
val b1 = BInst(a1) 
val c1 = CInst[BInst[AInst],AInst](b1) 

Есть работа вокруг, где я не должен указывать типы для CInst конкретно?

В настоящее время я использую параметризацию типа для реализации F-Bounds, но будет ли переход на абстрактный тип членов решить эту проблему? Как бы тогда выглядел класс?

+0

У меня был пример здесь: https://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics/10891994#10891994 – ayvango

ответ

1

Как об этом:

... //A,AInst,B,BInst without changes 

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] { 
    self: CC => 
    val content: B[BB, AA] //`B[BB, AA]` instead of `BB` 
} 

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: B[BB,AA]) extends C[CInst[BB, AA], BB, AA] 

Использование:

scala> val a1 = new AInst("A1") 
a1: AInst = AInst(A1) 

scala> val b1 = BInst(a1) 
b1: BInst[AInst] = BInst(AInst(A1)) 

scala> val c1 = CInst(b1) 
c1: CInst[BInst[AInst],AInst] = CInst(BInst(AInst(A1))) 

Он не работал до того, как компилятор видел BB, как BInst[AA <: A[AA]], так что мой B[BB,AA] просто поднял BB в B[BInst[AInst], AInst].

P.S. С членами типа вы все равно пытались передать типы вашим классам вещей так или иначе, поэтому никакой большой разницы.

+0

Отлично, спасибо! Я был так близок ... Определения типов становятся немного громоздкими, интересно, является ли это также формой запаха кода. – Karalga

+0

Это зависит от того, как вы их видите :) Я вижу их как время компиляции 'def' [как здесь] (http://stackoverflow.com/a/29470018/1809978). Но вывод типа compile'r может быть не таким ясным, и на самом деле это очень зависит от вашей логики домена, вам действительно не нужны они – dk14

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

  • Нет связанных вопросов^_^