【问题标题】:Why am I getting an error on this simple Scala code?为什么我在这个简单的 Scala 代码上遇到错误?
【发布时间】:2014-06-19 01:59:16
【问题描述】:

这是我的代码:

object Triple {
  object Num extends Enumeration {
    type Num = Value
    val one, two, three, four, five, six, seven, eight, nine = Value
  }
  val triples = for {
    first <- Num.values
    second <- Num.values
    third <- Num.values
    if (first != second)
    if (first != third)
    if (second != third)
  } yield Set(first, second, third)
}

第三行出现错误。它说:

Multiple markers at this line
    - not enough arguments for method map: (implicit bf: 
         scala.collection.generic.CanBuildFrom[sudoku.Triple.Num.ValueSet,scala.collection.immutable.Se    t[sudoku.Triple.Num.Value],That])That. Unspecified 
 value parameter bf.
- diverging implicit expansion for type 
 scala.collection.generic.CanBuildFrom[sudoku.Triple.Num.ValueSet,scala.collection.immutable.Set[sudoku.Triple.Num.Value],That] starting with 
 method newCanBuildFrom in object SortedSet
- not enough arguments for method map: (implicit bf: 
 scala.collection.generic.CanBuildFrom[sudoku.Triple.Num.ValueSet,scala.collection.immutable.Set[sudoku.Triple.Num.Value],That])That. Unspecified 
 value parameter bf.
- diverging implicit expansion for type 
 scala.collection.generic.CanBuildFrom[sudoku.Triple.Num.ValueSet,scala.collection.immutable.Set[sudoku.Triple.Num.Value],That] starting with 
 method newCanBuildFrom in object SortedSet

更新:Aleksey Izmailov 给出了很好的答案。该函数的一个稍微好一点的实现是 val triples=Num.values.subset(3).toSet

【问题讨论】:

标签: scala


【解决方案1】:

看起来你正在尝试做的是这样的:

scala> object Num extends Enumeration {
     |     type Num = Value
     |     val one, two, three, four, five, six, seven, eight, nine = Value
     |   }
defined module Num

scala>   val triples = Num.values.toList.combinations(3)
triples: Iterator[List[Num.Value]] = non-empty iterator

scala> triples.toList
res0: List[List[Num.Value]] = List(List(one, two, three), List(one, two, four), List(one, two, five), List(one, two, six), List(one, two, seven), List(one, two, eight), List(one, two, nine), List(one, three, four), List(one, three, five), List(one, three, six), List(one, three, seven), List(one, three, eight), List(one, three, nine), List(one, four, five), List(one, four, six), List(one, four, seven), List(one, four, eight), List(one, four, nine), List(one, five, six), List(one, five, seven), List(one, five, eight), List(one, five, nine), List(one, six, seven), List(one, six, eight), List(one, six, nine), List(one, seven, eight), List(one, seven, nine), List(one, eight, nine), List(two, three, four), List(two, three, five), List(two, three, six), List(two, three, seven), List(two, three...
scala> 

如果你这样做,那么它会起作用:

scala> object Triple {
     |   object Num extends Enumeration {
     |     type Num = Value
     |     val one, two, three, four, five, six, seven, eight, nine = Value
     |   }
     |   val triples = for {
     |     first <- Num.values
     |     second <- Num.values
     |     third <- Num.values
     |     if (first != second)
     |     if (first != third)
     |     if (second != third)
     |   } yield (first, second, third)
     | }
defined module Triple

scala> Triple.triples
res1: scala.collection.immutable.SortedSet[(Triple.Num.Value, Triple.Num.Value, Triple.Num.Value)] = TreeSet((one,two,three), (one,two,four), (one,two,five), (one,two,six), (one,two,seven), (one,two,eight), (one,two,nine), (one,three,two), (one,three,four), (one,three,five), (one,three,six), (one,three,seven), (one,three,eight), (one,three,nine), (one,four,two), (one,four,three), (one,four,five), (one,four,six), (one,four,seven), (one,four,eight), (one,four,nine), (one,five,two), (one,five,three), (one,five,four), (one,five,six), (one,five,seven), (one,five,eight), (one,five,nine), (one,six,two), (one,six,three), (one,six,four), (one,six,five), (one,six,seven), (one,six,eight), (one,six,nine), (one,seven,two), (one,seven,three), (one,seven,four), (one,seven,five), (one,seven,six), (one,...
scala> 

请注意,生成的集合的结果是SortedSet。该结果由 Num.values 定义 - 您可以将 for 理解转换为 mapflatMapfilter 以检查类型是如何产生的。

问题是您可以将可以排序的内容放入SortedSet,例如:

scala> scala.collection.immutable.SortedSet(1, 2)
res6: scala.collection.immutable.SortedSet[Int] = TreeSet(1, 2)

但是,您不能将未定义排序的内容放入SortedSet,因为SortedSet 保证这些内容已排序并且应该知道排序是如何完成的(通过隐式排序):

scala> scala.collection.immutable.SortedSet(Set(1, 2), Set(3, 4))
<console>:8: error: No implicit Ordering defined for scala.collection.immutable.Set[Int].
              scala.collection.immutable.SortedSet(Set(1, 2), Set(3, 4))

Scala 查找要在作用域中定义的隐式Ordering,但没有找到您正在使用的Set 或我的示例中的Set[Int]

现在让我们“修复”它:

scala> implicit val dummyOrdering: Ordering[Set[Int]] = Ordering.by(_.size)
dummyOrdering: Ordering[Set[Int]] = scala.math.Ordering$$anon$9@6f00d9a7

scala> scala.collection.immutable.SortedSet(Set(1, 2), Set(3, 4))
res8: scala.collection.immutable.SortedSet[scala.collection.immutable.Set[Int]] = TreeSet(Set(3, 4))

显然,这是一个糟糕的解决方案,真正的问题是,在您的情况下,类型选择不当。首先,您不需要为每个组合使用Set,因为您已经比较了事物以避免重复。只需使用Tuple3。其次,如果你坚持使用Set,那么在for理解中将Num.values转换为List

scala> object Triple {
     |   object Num extends Enumeration {
     |     type Num = Value
     |     val one, two, three, four, five, six, seven, eight, nine = Value
     |   }
     |   val triples = for {
     |     first <- Num.values.toList
     |     second <- Num.values.toList
     |     third <- Num.values.toList
     |     if (first != second)
     |     if (first != third)
     |     if (second != third)
     |   } yield Set(first, second, third)
     | }
defined module Triple

希望这说明清楚。基本上问题在于选择了错误的类型。

【讨论】:

  • 这在 2.11 中不起作用。不过,这是对它应该如何工作的一个很好的描述。
  • 哪个部分在 2.11 @wingedsubmariner 中不起作用?我在 2.10.3 REPL 中尝试过。
  • Set(first, second, third) 替换为(first, second, third) 不会改变2.11 中产生的错误。我可以确认它确实消除了 2.10.3 中的错误。
  • 非常有趣。应该是回归。奇怪... :)
  • 感谢您的精彩回答!看起来我的错误是写“设置(第一,第二,第三)”而不是“(第一,第二,第三”。我真的不明白为什么这是一个错误。我也不明白为什么会这样'不返回列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多