0

私はFバウンドタイプを持っています:

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

そして、最初のタイプによってパラメータ化された 2 番目の 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]

しかし、コンパニオン パラメーター化 (最後の行) の BInst には型パラメーターが必要なため、これはコンパイルに失敗します。同様に

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

失敗します。コンパニオン オブジェクトの正しい型は何ですか?

4

2 に答える 2

1

私はあなたがここに書いたことをあなたの他の質問とマージしようとしました: scala: F-Bound パラメータで特性を参照する

これは、コンパイル可能な状態に保つことで、コードに近づけることができます。

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の は に置き換えられThis、引数の順序が入れ替わったため、標準コレクション ライブラリで行われているものとより類似しています。

一般的な意見。and /
に何を求めているのかよくわからないようです。あなたの質問の2つのバージョンは、まったく異なるタイプのようです。何が必要かよくわからない場合は、できるだけシンプルにすることをお勧めします。これらすべての F-Bound-GenericCompanionCanBuildFromFactories を正しく取得するのが難しいという逸話的な証拠があります。BInstBCompCompanion

于 2015-04-22T14:50:33.013 に答える
1

私が見る唯一の方法は、タイプの観点からでもオブジェクトのインスタンスが1つしかない可能性があるため、 Companion/のジェネリックパラメーターを放棄することです(1つのタイプのみ):BInstBInst.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/ -object内でタイプをキャストしない場合(クラスの/ -independent メソッドBInstのみを使用することをお勧めします)、ClassCastException を取得するリスクはありません。プロトタイプとして使用して、新しいタイプを作成 (クローン) するだけです。BBAABInst.asInstanceOf[Companion[BInst[BB, AA]]]BInst

于 2015-04-15T13:59:05.773 に答える