一个Scala中最强大的模式是充实,我的图书馆*模式,它采用隐式转换为出现添加方法,以现有的类,而不需要动态方法解析.例如,如果我们希望所有字符串都有spaces
计算他们有多少个空格字符的方法,我们可以:
class SpaceCounter(s: String) {
def spaces = s.count(_.isWhitespace)
}
implicit def string_counts_spaces(s: String) = new SpaceCounter(s)
scala> "How many spaces do I have?".spaces
res1: Int = 5
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种模式在处理泛型集合时遇到了麻烦.例如,已经询问了许多关于按顺序对项目进行分组的问题.没有内置的东西可以一次性工作,所以这似乎是使用泛型集合C
和泛型元素类型的rich-my-library模式的理想候选者A
:
class SequentiallyGroupingCollection[A, C[A] <: Seq[A]](ca: C[A]) {
def groupIdentical: C[C[A]] = {
if (ca.isEmpty) C.empty[C[A]]
else {
val first = ca.head
val (same,rest) = ca.span(_ == first)
same +: (new SequentiallyGroupingCollection(rest)).groupIdentical
}
}
}
Run Code Online (Sandbox Code Playgroud)
当然,除了它不起作用.REPL告诉我们:
<console>:12: error: not found: …
Run Code Online (Sandbox Code Playgroud) 希望这将是一个关于图书馆拉皮条的简单问题(因为关于该主题的其他问题往往会产生超出我目前技能水平的答案).
我想要做的就是将集合的交叉产品映射到自身.
val distances = points.crossMap(_ distance _) // points: List[Point3d]
Run Code Online (Sandbox Code Playgroud)
所以我试图皮条客Traversable
:
implicit def toSelfCrossMappable[A](xs: Traversable[A]) = new {
def crossMap[B](f: (A, A) => B) = xs.flatMap(a => xs.map(f(a, _)))
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用(它没有进行隐式转换),我不明白为什么不(我对scala很新).我还尝试了使用一种方法在Enriching Scala集合中建议的方法:
implicit def toSelfCrossMappable[A, C[A]](xs: C[A])(implicit c: C[A] => Traversable[A]) = new SelfCrossable[A, C[A]](xs)(c)
class SelfCrossable[A, C](xs: C)(implicit c: C => Traversable[A]) {
def crossMap[B](f: (A, A) => B) = xs.flatMap(a => xs.map(f(a, _)))
}
Run Code Online (Sandbox Code Playgroud)
,但是抛出与我(看起来更简单)方式相同的错误.
我在这做错了什么?