2015-04-15 1 views
0

У меня есть тип F-Bound:Scala: Companion объекты для двукратно типов F-Bounded полиморфных

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

И второй F-Bound типа, который параметризованный первый типа.

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

Я могу счастливо писать классы случая, что делает использование этих типов:

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

Теперь я хотел бы иметь объект компаньона для случая класса, который я могу ссылаться через черт B, что-то вроде:

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

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

case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA) 
    extends B[BInst[BB, AA], AA] { 
    def companion: Companion[BInst[BB, AA]] = BInst 
} 

sealed trait Companion[+BB <: B[_, _]] 
object BInst extends Companion[BInst] 

Но это не удается скомпилировать как Бинст в сопутствующем параметризации (последняя строка) требует параметры типа. Аналогичным образом

sealed trait Companion[BB[X, Y] <: B[X, Y]] 

не работает. Каков правильный тип для объекта-компаньона?

ответ

1

Единственный способ, которым я вижу отказаться общие параметры для Companion/BInst, как там может быть только один экземпляр объекта даже от типа точки зрения (только один BInst.type типа):

scala> sealed trait A[AA <: A[AA]] { self: AA => } 

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

case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA) 
    extends B[BInst[BB, AA], AA] { 
    def companion = BInst 
} 

sealed trait Companion[+BB <: B[_, _]] 
object BInst extends Companion[BInst[_, _]] 

defined trait A 
defined trait B 
defined class BInst 
defined trait Companion 
defined module BInst 

После того, что вы можете на самом деле Отдайте свой BInst (в случае класса):

def companion: Companion[BInst[BB, AA]] = 
    BInst.asInstanceOf[Companion[BInst[BB, AA]] 

Если вы не отбрасывают типов внутри вашего Companion -trait/BInst -объект (лучше использовать только BB/AA -независимые методы класса BInst) нет никакого риска получить ClassCastException, .asInstanceOf[Companion[BInst[BB, AA]]] будет просто создавать (клонировать) новый тип для вас, используя BInst в качестве прототипа.

+0

В чем преимущество литья? – Karalga

+0

В вашем первоначальном фрагменте вы просите «def companion: Companion [BInst [BB, AA]]' - так что если вы в порядке с 'def companion: Companion [_]', тогда нет преимуществ :) – dk14

1

Я пытался объединить то, что вы написали здесь с другим вопросом: scala: Referencing Trait with F-Bound Parameters

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

import scala.language.higherKinds 

trait A[AA <: A[AA]] { self: AA => } 

trait B[ 
    X <: A[X], 
    This[Y <: A[Y]] <: B[Y, This] 
] { 
    self: This[X] => 
    def content: X 
    def companion: Companion[This] 
} 

trait Companion[Coll[X <: A[X]] <: B[X, Coll]] 

case class BInst[X <: A[X]](content: X) 
extends B[X, BInst] { 
    def companion: Companion[BInst] = BInst 
} 

object BInst extends Companion[BInst] 

Ваш BB s были заменены на This, порядок аргументов был заменен так, что он больше похож на то, что делается в стандартной библиотеке коллекции.

A общее примечание.
Вы, кажется, не совсем уверены в том, что хотите от своих BInst и BComp/Companion. Это две версии ваших вопросов, похоже, они имеют совершенно разные типы. Если вы не совсем уверены в том, чего хотите, может быть целесообразно просто держать его как можно проще. Существует неопровержимое доказательство того, что all these F-Bound-GenericCompanionCanBuildFromFactories can be difficult to get right.

+0

Спасибо! Параметризация «B» с параметризованными типами на самом деле является решением, а не только этой проблемой! Спасибо за ссылку на разговор Павла, у него есть точка. – Karalga

+0

На всякий случай, что я испортил вашу веру, предоставив ссылку на беседу: в другой версии https://www.youtube.com/watch?v=4jh94gowim0 все остальные существующие в настоящее время языки также уничтожены, и в общем, первая версия этой беседы кажется несколько более оптимистичной (> 58:00). Кроме того, это просто потрясающая развлекательная работа, которую нужно рассматривать как искусство самостоятельно. –

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