2016-05-25 18 views
2
trait Account[T <: Account[T]] 

case class BrokerAccount(total:BigDecimal) extends Account[BrokerAccount] 
case class SavingsAccount(total:BigDecimal) extends Account[SavingsAccount] 

以下の関数の宣言と呼び出しはうまくいきます。スカラF結合型多型

def foo1(xs: Array[T forSome { type T <: Account[T] }]):Array[T forSome { type T <: Account[T] }] = xs 
foo1(Array(BrokerAccount(100),SavingsAccount(50))) 

ただし、以下の呼び出しでコンパイルエラーが発生します。

def foo2(xs: List[T forSome { type T <: Account[T] }]):List[T forSome { type T <: Account[T] }] = xs 
foo2(List(BrokerAccount(100),SavingsAccount(50))) 

エラー

Main.scala:14: error: type mismatch;
found : List[Product with Serializable with Main.Account[_ >: Main.SavingsAccount with Main.BrokerAccount <: Product with Serializable with Main.Account[_ >: Main.SavingsAccount with Main.BrokerAccount <: Product with Serializable]]]
required: List[T forSome { type T <: Main.Account[T] }] foo2(List(BrokerAccount(100),SavingsAccount(50)))

コンパイルエラーが後の場合に起こり、なぜ誰かが私に説明していただけますか?

答えて

3

問題の鍵は分散です。共変位置(反復型)の反復値を返そうとしています。 Listにもかかわらず、型はその引数(trait List[+A])で共変である、これは基本的に(スーパータイプのリストに割り当てることができます)、その値が反変であることを意味します:

val listOfSupers: List[_ >: Account[_]] = List(BrokerAccount(100), SavingsAccount(50)) 

あなたが機能foo2から復帰しようとしている何をされます完全な逆 - List[_ <: Account[_]]、したがってコンパイラのエラーです。

Listの代わりにArrayのようなタイプパラメータで不変のSetを使用すると、すべて正常に動作します。

+0

どのように下の行をコンパイルできますか? foo2(List [T forSome {Type T <:Account [T]}](BrokerAccount(100)、SavingsAccount(50))) –

+0

詳細はこちら:http://stackoverflow.com/questions/6684493/why-are-配列 - 不変量 - しかしリスト - 共変量 –

+1

感謝セルゲイ。 –