Scala 保留元素类型A和表示类型Repr的集合扩展方法
作为我的后续工作,我能否设计一个隐式类来处理两种类型的Scala 保留元素类型A和表示类型Repr的集合扩展方法,scala,collections,implicit-conversion,Scala,Collections,Implicit Conversion,作为我的后续工作,我能否设计一个隐式类来处理两种类型的SeqLike扩展: import collection.SeqLike import collection.generic.CanBuildFrom implicit class Test[A, Repr](val sq: SeqLike[A, Repr]) extends AnyVal { // no constraints on Repr def foo[B](f: A => B)(implicit ord: Order
SeqLike
扩展:
import collection.SeqLike
import collection.generic.CanBuildFrom
implicit class Test[A, Repr](val sq: SeqLike[A, Repr]) extends AnyVal {
// no constraints on Repr
def foo[B](f: A => B)(implicit ord: Ordering[B]): Repr = sq.sortBy(f)
// constraint that actually sq is Repr
def bar[B, To](fun: (A, A) => B)(implicit cbf: CanBuildFrom[Repr, B, To]): To = {
val b = cbf(sq) // NO!
// ...
b.result
}
}
bar
方法无法编译,因为我们缺少typeOf(sq)=Repr
的约束。正如其他人所指出的,如果我将构造函数更改为sq:Repr
,我们将失去与类型A
的连接
现在,Repr
已断开连接。例如:
// in Test:
def isSortedBy[B](fun: A => B)(implicit ord: Ordering[B]): Boolean =
sq.sliding(2, 1).forall {
case a +: b +: _ => ord.lteq(fun(a), fun(b))
case _ => true // happens when it size == 1
}
[error] Test.scala: inferred type arguments [T,Equals] do not conform to method
unapply's type parameter bounds
[T,Coll <: scala.collection.SeqLike[T,Coll]]
[error] case a +: b +: _ => ord.lteq(fun(a), fun(b))
[error] ^
//测试中:
def-isSortedBy[B](fun:A=>B)(隐式order:Ordering[B]):布尔值=
平方滑动(2,1)。用于所有{
案例a+:b+:=>ord.lteq(fun(a),fun(b))
case=>true//在大小==1时发生
}
[错误]Test.scala:推断的类型参数[T,Equals]不符合方法
取消应用的类型参数边界
[T,Coll ord.lteq(乐趣(a),乐趣(b))
[错误]^
如果我正确理解了问题
- 如果将类参数
设置为sq
,则会丢失类型Repr
(不再有任何推断)a
- 但是如果您将它设置为
,那么您就失去了它也是SeqLike[a,Repr]
的事实,因此Repr
不再编译cbf(sq)
implicit class Test[A, Repr](val sq: Repr with SeqLike[A, Repr]) extends AnyVal {
...
}
这个版本编译得很好,我可以在一个简单的列表(1,2,3)
上调用foo
和bar
编辑:如果要将
Repr
类型的值而不是sq
作为集合进行操作,还需要类型绑定的Repr,您可以像在其他问题中一样,使用Repr
并将sq
的类型更改为SeqLike
,而不是Repr
。
但与我以前的解决方案不同,您可以将上限类型绑定到Repr
(Repr B)(隐式cbf:CanBuildFrom[Repr,B,to]):to={
val b=cbf(sq.repr)//否!
var x=平方水头
sq.tail.foreach{y=>
b+=乐趣(x,y)
x=y
}
b、 结果
}
def-isSortedBy[B](fun:A=>B)(隐式order:Ordering[B]):布尔值=
平方滑动(2,1)。用于所有{
案例a+:b+:=>ord.lteq(fun(a),fun(b))
case=>true//在大小==1时发生
}
}
我认为self.slideing
应该是sq.slideing
对吗?@stew-是的,很抱歉这是复制+粘贴的错误
implicit class Test[A, Repr<:SeqLike[A,Repr]](val sq: SeqLike[A, Repr]) extends AnyVal {
// no constraints on Repr
def foo[B](f: A => B)(implicit ord: Ordering[B]): Repr = sq.sortBy(f)
// constraint that actually sq is Repr
def bar[B, To](fun: (A, A) => B)(implicit cbf: CanBuildFrom[Repr, B, To]): To = {
val b = cbf(sq.repr) // NO!
var x = sq.head
sq.tail.foreach { y =>
b+=fun(x,y)
x = y
}
b.result
}
def isSortedBy[B](fun: A => B)(implicit ord: Ordering[B]): Boolean =
sq.sliding(2, 1).forall {
case a +: b +: _ => ord.lteq(fun(a), fun(b))
case _ => true // happens when it size == 1
}
}