不能证明单位<:< (T,U)

时间:2013-10-10 18:07:13

标签: scala

尝试从列表中删除所有Unit - ()时,我尝试拨打toMap

scala> List((), ()).filter(_ != ()).toMap
<console>:8: error: Cannot prove that Unit <:< (T, U).
              List((), ()).filter(_ != ()).toMap
                                           ^

这个错误是什么意思?

对于List,我想为非Unit元素创建所有元组(String, String)的映射,但有些值可能为null。

scala> val x = List((), (), (3,4)).filter(_ != ()).toMap
<console>:7: error: Cannot prove that Any <:< (T, U).
       val x = List((), (), (3,4)).filter(_ != ()).toMap
                                                   ^

scala> val x = List((), (), (3,4)).filter(_ != ())
x: List[Any] = List((3,4))

scala> x.toMap
<console>:9: error: Cannot prove that Any <:< (T, U).
              x.toMap
                ^

3 个答案:

答案 0 :(得分:4)

啊!现在your other question更有意义了。仍然不确定您在制作此混合Unit / Tuple2列表时所做的工作。

这应该有效:

List((), (), (3,4)).collect { case t@(_: Int, _: Int) => t }.toMap

请注意,我在这里使用variable binding(将匹配绑定到t)以返回我们匹配的相同Tuple2实例,而不是创建新实例。

使用collect,您可以将列表类型从List[Any]转换为List[(Int, Int)],这是toMap想要的,因为它需要一些List[(A,B)]。< / p>


注意:虽然这个答案对您有用,但我仍然认为您的设计存在缺陷。你最好修复底层设计缺陷,而不是像这样处理这些症状。

看起来这非常适合使用Scala's Option type。在这种情况下,您的样本列表将变为List(None, None, Some((3,4))),或者您可以将其写为List(None, None, Some(3->4))以提高可读性(嵌套括号可能会让人感到困惑)。

如果您使用Option,那么您的列表类型将变为List[Option[(Int, Int)]],这应该比List[Any]更好。要删除None条目并获得所需的List[(Int,Int)],您只需致电flatten

List(None, None, Some(3->4)).flatten
// res0: List[(Int, Int)] = List((3,4))
List(None, None, Some(3->4)).flatten.toMap
// res1: scala.collection.immutable.Map[Int,Int] = Map(3 -> 4)

但是,如果您可以避免首先在列表中放入None条目,那么 甚至更好 。如果您使用Scala生成此列表以进行理解,则可以use a guard in your for expression从输出中删除无效元素。

答案 1 :(得分:2)

这意味着列表中元素的类型不能被视为构建Map所需的元组。从某种意义上说,Map是元组的集合(以及更多)。

插图:

scala> List(1).toMap
<console>:8: error: Cannot prove that Int <:< (T, U).
          List(1).toMap
                  ^
scala> List(1 -> 2).toMap
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)

我可以从元组列表构建一个映射,但不能从单个基数元素列表构建。

也许您的意思是说.map而不是.toMap? ;)

答案 2 :(得分:1)

一气呵成:

scala> val l2 = List(1 -> 3, (), 4 -> 4, (), 9 -> 4, (), 16 -> 7)
l2: List[Any] = List((1,3), (), (4,4), (), (9,4), (), (16,7))

scala> (l2 collect { case (a, b) => (a, b) }).toMap
res4: scala.collection.immutable.Map[Any,Any] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)

更好的打字:

scala> (l2 collect { case (i: Int, j: Int) => (i, j) }).toMap
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)