7

Scala で f-bounded ポリモーフィズムを実現するには、抽象型を使用する必要があると述べている記事をいくつか読みました。これは主に、型推論の問題を軽減するためですが、再帰型を定義するときに型パラメーターが導入するように見える二次成長を取り除くためでもあります。

これらは次のように定義されています。

trait EventSourced[E] {
  self =>

  type FBound <: EventSourced[E] { type FBound <: self.FBound }

  def apply(event: E): FBound
}

ただし、これにより次の 2 つの問題が発生するようです。

1) ユーザーがこの型のオブジェクトを参照するたびに、FBound型パラメーターも参照する必要があります。これはコードの匂いのように感じます:

def mapToSomething[ES <: EventSourced[E], E](eventSourced: ES#FBound): Something[ES, E] = ...

2) コンパイラは、上記のようなメソッドの型パラメータを推測できなくなり、次のメッセージで失敗します。

Type mismatch, expected: NotInferredES#FBound, actual: MyImpl#FBound

f-bounded polymorphism の実装に成功し、コンパイラが型を推測できるようになった人はいますか?

4

3 に答える 3

5

それ以来、ほとんどの場合、f-bounded ポリモーフィズムは避けるべきであることに気付きました。むしろ、通常、選択すべき代替設計があります。それを回避する方法を理解するには、まず何が必要なのかを知る必要があります。

F-bounded ポリモーフィズムは、型が重要なインターフェイスの変更が派生型に導入されることを期待している場合に発生します。

これは、継承を介してそれらをサポートしようとするのではなく、予想される変更領域を構成することによって回避されます。これは、実際には Gang of Four の設計パターンに戻ります。

「クラス継承」よりも「オブジェクト合成」を優先する

-- (ギャング・オブ・フォー、1995)

例えば:

trait Vehicle[V <: Vehicle[V, W], W] {
    def replaceWheels(wheels: W): V
}

になります:

trait Vehicle[T, W] {
    val vehicleType: T
    def replaceWheels(wheels: W): Vehicle[T, W]
}

ここで、「予想される変更」は車両の種類 (例: BikeCarLorry) です。W前の例では、これが継承によって追加されることを前提としており、 Vehicle を使用する関数の推論を不可能にする f-bounded 型が必要です。コンポジションを使用する新しい方法では、この問題は発生しません。

参照: https://github.com/ljwagerfield/scala-type-in​​ference /blob/master/README.md#avoiding-f-bounded-polymorphism

于 2016-09-14T12:29:04.503 に答える
-1

Twitter の Scala School での F-bounded polymorphism の議論を参照してください。

于 2013-09-01T20:38:33.423 に答える