0

我有一个for-comprehension来自 a 的生成器,Set[MyType]MyType有一个lazy val名为的变量factsPair,它返回一对集合:(Set[MyFact], Set[MyFact])。

我希望遍历所有这些并将事实统一为一对扁平的(Set [MyFact],Set [MyFact]),如下所示,但是我遇到了No implicit view available ...错误not enough arguments for flatten: implicit (asTraversable ...。(我对 Scala 有点陌生,所以仍在努力适应错误)。

lazy val allFacts  =
(for {
  mytype <- mytypeList
} yield mytype.factsPair).flatten

我需要指定什么来使其变平才能工作?

4

4 回答 4

3

Scala flatten 适用于相同的类型。你有一个 Seq[(Set[MyFact], Set[MyFact])],它不能被展平。

我建议学习该foldLeft功能,因为它非常通用且一旦掌握它就很容易使用:

lazy val allFacts = myTypeList.foldLeft((Set[MyFact](), Set[MyFact]())) {
  case (accumulator, next) =>
    val pairs1 = accumulator._1 ++ next.factsPair._1
    val pairs2 = accumulator._2 ++ next.factsPair._2
    (pairs1, pairs2)
}

第一个参数采用初始元素,它将附加其他元素。Tuple[Set[MyFact], Set[MyFact]]我们从一个像这样初始化的空开始: (Set[MyFact](), Set[MyFact]()).

接下来,我们必须指定接收累加器并将下一个元素附加到它并返回包含下一个元素的新累加器的函数。由于所有的元组,它看起来不太好,但有效。

于 2013-11-15T16:29:43.007 回答
1

您将无法使用flatten它,因为flatten在集合上返回一个集合,而元组不是一个集合。

当然,您可以拆分、展平并再次加入:

val pairs = for {
  mytype <- mytypeList
} yield mytype.factsPair
val (first, second) = pairs.unzip
val allFacts = (first.flatten, second.flatten)
于 2013-11-15T16:29:49.510 回答
0

元组是不可遍历的,所以你不能在它上面展平。您需要返回可以迭代的内容,例如 List,例如:

List((1,2), (3,4)).flatten          // bad
List(List(1,2), List(3,4)).flatten  // good
于 2013-11-15T16:25:48.527 回答
0

我想提供一个更代数的观点。使用monoids可以很好地解决您在这里所拥有的问题。对于每个幺半群,都有一个零元素和一个将两个元素组合为一个的操作。

在这种情况下,为一个幺半群集合:零元素是一个空集,操作是一个联合。如果我们有两个幺半群,它们的笛卡尔积也是一个幺半群,其中操作是成对定义的(参见Wikipedia 上的示例)。

Scalaz 为集合和元组定义了幺半群,所以我们不需要在那里做任何事情。我们只需要一个辅助函数,将多个幺半群元素组合为一个,使用折叠很容易实现:

def msum[A](ps: Iterable[A])(implicit m: Monoid[A]): A =
  ps.foldLeft(m.zero)(m.append(_, _))

(可能Scala里已经有这样的功能了,我没找到)。使用msum我们可以很容易地定义

def pairs(ps: Iterable[MyType]): (Set[MyFact], Set[MyFact]) =
  msum(ps.map(_.factsPair))

对元组和集合使用 Scalaz 的隐式幺半群。

于 2013-11-15T21:12:59.523 回答