我发现自己想写这个:
def allAsAndFs(node: Node): PairOfSeqs[Action, Factor] =
node.regularNames.flatMap { name => regularAsAndFs(name) } ++
node.specialNames.flatMap { name => specialAsAndFs(name) }
其中:
def regularNames: Seq[String]
def specialNames: Seq[String]
def regularAsAndFs(name: String): PairOfSeqs[Action, Factor]
def specialAsAndFs(name: String): PairOfSeqs[Action, Factor]
和
class PairOfSeqs[A, B](as: Seq[A], bs: Seq[B]) {
def ++(that: PairOfSeqs[A, B]): PairOfSeqs[A, B] =
PairOfSeqs(as ++ that.as, bs ++ that.bs)
. . .
}
我需要做些什么才能使flatMap
合并PairsOfSeqs
调用适当的++
方法?
看起来PairOfSeqs
应该扩展GenTraversableOnce
,但是
GenTraversableOnce
有一个相当惊人的47个抽象方法来覆盖。
这是一种惯用的Scalastic方法吗?
答案 0 :(得分:3)
您使用的是flatMap
的一些非标准概念。正常类型签名是
class C[A] {
def flatMap[B](f: A => C[B]): C[B] = ???
}
但是你想要(类似于 - 这不会编译):
def foo[D <: { def ++(d: D): D }](f: A => D): D
更像fold
而不是flatMap
。
一种可能性是使PairOfSeqs
成为一个完整的集合。这将是艰难的,因为类型真的不排队那么好,因为扩展集合很困难。 (奖励/努力比率可能很好,因为即使努力很大,奖励也是巨大,如果你真的需要它。)
也许最好的可能性就是在Seq
上有一个扩展方法。
case class PairOfSeqs[A, B](as: Seq[A], bs: Seq[B]) {
def ++(that: PairOfSeqs[A, B]): PairOfSeqs[A,B] =
PairOfSeqs(as ++ that.as, bs ++ that.bs)
}
implicit class SeqCanPairMap[A](val underlying: Seq[A]) extends AnyVal {
def flatPair[B,C](f: A => PairOfSeqs[B,C]): PairOfSeqs[B,C] = {
val ps = underlying.map(f)
PairOfSeqs(ps.map(_.as).fold(Seq[B]())(_ ++ _), ps.map(_.bs).fold(Seq[C]())(_ ++ _))
}
}
Seq("fish", "fowl").flatPair(s => new PairOfSeqs(s.map(_.toChar), s.map(_.toInt)))
还有其他各种选项(例如,在flatMap
上定义更传统的PairOfSeqs
,以及从常规seqs到具有空第二个插槽的PairOfSeqs的转换,但这可能涵盖您的使用情况不错。
最后,要制作课程flatMappable
,您只需要定义flatMap
即可。特别是,理解可以使用它。 (但是你也需要一个map
,否则它对于理解不会有用。)