txt*_*low 4 generics types scala scala-collections
我想写这样的东西:
trait Typed[T]
trait Test {
def testMap: Map[Typed[_], Int]
def test = testMap.flatMap {case (typed, size) => Seq.fill(size)(typed)}
}
Run Code Online (Sandbox Code Playgroud)
但是我收到以下错误:
error: no type parameters for method flatMap: (f: ((Typed[_], Int)) => Traversable[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Map[com.quarta.service.querybuilder.Typed[_],Int],B,That])That exist so that it can be applied to arguments (((Typed[_], Int)) => Seq[Typed[_0]] forSome { type _0 })
--- because ---
argument expression's type is not compatible with formal parameter type;
found : ((Typed[_], Int)) => Seq[Typed[_0]] forSome { type _0 }
required: ((Typed[_], Int)) => Traversable[?B]
def test = testMap.flatMap {case (typed, size) => Seq.fill(size)(typed)}
Run Code Online (Sandbox Code Playgroud)
如果将testMap类型更改为:此代码有效:
def testMap: Map[Typed[Any], Int]
Run Code Online (Sandbox Code Playgroud)
有什么区别以及如何解决我的问题?
如果我正确地理解了你的问题,答案是:如果Typed是协变的T,你可以这样做,即trait Typed[+T].
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Typed[+T: Manifest] {
override def toString = "Typed[" + implicitly[Manifest[T]].toString + "]"
}
trait Test {
def testMap: Map[Typed[_], Int]
def foo = testMap flatMap { case (t, s) => Seq.fill(s)(t) }
}
val bar = new Test {
def testMap = Map(new Typed[Double]() -> 3, new Typed[Int]() -> 5)
}
// Hit Ctrl-D
scala> bar.foo
res0: scala.collection.immutable.Iterable[Seq[Typed[Any]]] = List(Typed[Double], Typed[Double], Typed[Double], Typed[Int], Typed[Int], Typed[Int], Typed[Int], Typed[Int])
Run Code Online (Sandbox Code Playgroud)
请注意,我Typed在这个例子中创建了一个类以获得更好的输出.你当然可以坚持下去trait.
协方差基本上意味着如果那样的A <: B话X[A] <: X[B].所以,如果你被宣布testMap为Map[Typed[Any], Int]同时Typed是不变的,你不许例如通过Typed[Double]一个Typed[Any]即使Double <: Any.在这里,Scala编译器似乎取代_与Any在协变的情况下(见即兴的评论关于此的详细阐述).
有关下划线问题的解释,我会参考Luigi的答案.
| 归档时间: |
|
| 查看次数: |
1549 次 |
| 最近记录: |