【问题标题】:Missing parameter type for generic scan通用扫描缺少参数类型
【发布时间】:2013-05-15 12:34:56
【问题描述】:

我似乎无法理解为什么我的程序在这种情况下需要显式参数类型。使用以下方法:

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
  }
}

我尝试在这样的特定实现中使用它:

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

这会产生以下错误消息:

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 是使用 FooParOps-trait(原型实现)中的方法的混合 trait:

  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 来自DistTraversable[+T] 并定义为def part: Seq[T]

我不太明白为什么这里需要显式参数?请告诉我是否需要更多信息。程序现在相当复杂。

【问题讨论】:

  • scan1lD中for循环中的变量grouppart是什么?
  • 我添加了更详尽的解释
  • 我试着简化你的问题,但我最终做了很多改变,只是为了得到一些可以编译的东西......如果你更明确,你会得到同样的编译错误吗? x.scan1lD((x:Int,y:Int) =&gt; x + y)?问题可能是因为它不知道That 的类型,所以它不能隐式解析正确的CanBuildFrom
  • val scan = x.scan1lD( (a:Int,b:Int) =&gt; a+b) 按预期编译和工作。对我来说,似乎应该很清楚我们需要一个类型为:CanBuildFrom[DistSeq[Int], Int, DistSeq[Int]] 的构建器,因为 (+) 必须是 (Int,Int) =&gt; Int
  • 好吧,我认为它可以接受任何定义了 + 方法并返回相同类型的参数。例如带有def +(MyType):MyType 方法的MyType

标签: scala generics traits


【解决方案1】:

我唯一能想到的就是很丑(但可能可以接受):

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 _)

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

【讨论】:

    猜你喜欢
    • 2023-02-01
    • 2016-06-13
    • 1970-01-01
    • 2011-12-29
    • 2017-10-30
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多