1

I can't seem to understand why my program needs explicit parameter types for this case. Using the following method:

trait DistTraversableLike[+T, +Repr]
  extends DistTraversable[T] {
  self: Repr =>
...
  def scan1lD[T1 >: T, That](assOp: (T1, T1) => T1)(implicit bf: CanBuildFrom[Repr, T1, That]): That = {
    val b = bf(this)
    for (x <- group.prefixSumSeq(part, assOp))
      b += x
    b.result
  }
}

I try to use it on a specific implementation like so:

val x:DistSeq[Int] = DistSeq((0 until worldSize): _*)
val scan = x.scan1lD(_+_)

Which yields the following error message:

Multiple markers at this line
    - missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus{<null>}(x$2{<null>}){<null>})
     {<null>}
    - missing parameter type for expanded function ((x$1, x$2) => x$1.$plus{<null>}(x$2{<null>}){<null>}){<null>}
    - missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
    - missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))

group is a mixed trait using a method from FooParOps-trait (prototype implementation):

  def prefixSumSeq[T](part: Seq[T], combiner: (T, T) => T): Seq[T] = {
    implicit val srlz = getSerializerFor(part)
    var result = part.head
    var msg = part.reduce(combiner)
    for (i <- 0 until log2i(size)) {
      val partner = localRank ^ math.pow(2, i).toInt
      send(partner, msg)
      val number: T = rcv(partner)
      msg = combiner(msg, number)
      if (partner < localRank) result = combiner(number, result)
    }
    return (part.tail).scanLeft(result)(combiner)
  }

part is from DistTraversable[+T] and defined as def part: Seq[T]

I don't quite see why explicit parameters are needed here? Please tell me if more information is needed. The program is quite complex right now.

4

1 回答 1

0

我唯一能想到的是非常丑陋(但可能是可以接受的):

implicit class Scan1lDable[T, Repr](v: DistTraversableLike[T, Repr]) {
  def scan1lD[That](op: (T,T) => T) // Note: no T1
                   (implicit bf: CanBuildFrom[Repr, T, That]): That = {
    // snip
  }
}

现在,您的示例将起作用,但以下将不起作用:

class A
class B extends A

def op(x: A, y: B) = x

val x: DistTraversableLike[B, ...] = ...
x.scan1lD(op _)

但这将:

(x: DistTraversableLike[A, ...]).scan1lD(op _)

所以我们添加一个方便的方法DistTraversableLike

trait DistTraversableLike[+T, +Repr]
  extends DistTraversable[T] {
  self: Repr =>

  def lower[S >: T]: DistTraversableLike[S, Repr] = this

}

现在可以调用:

x.lower[A].scan1lD(op _)

诚然,它确实很难看,但可能比必须指定方法类型更容易接受。

于 2013-05-21T16:55:52.567 回答