创建一个封装在斯卡拉地图()的正确类型的隐函数:不为微弱的心脏处(Creating an impli

2019-10-19 03:45发布

我想实现的隐函数mapMetered一个封装map在返回正确类型的术语和功能完全一样。 我尝试这样做:

implicit class MeteredGenTraversablePimp[T, C[T] <: GenTraversable[T]](trav: C[T]) {
  def foreachMetered(m: Meter)(f: T => Unit) =
    m.foreach(trav)(f)

  def mapMetered[B, That](m: Meter)(f: (T) => B)(
    implicit bf: CanBuildFrom[C[T], B, That]
  ): That = {
    m.start()
    try {
      trav.map { x =>
        val z = f(x)
        m.item_processed()
        z
      } (bf)
    } finally { m.finish() }
  }
}

但是,当我尝试这个,我得到一个错误:

[info] Compiling 1 Scala source to /Users/benwing/devel/textgrounder/target/classes...
[error] /Users/benwing/devel/textgrounder/src/main/scala/opennlp/textgrounder/util/metering.scala:223: type mismatch;
[error]  found   : scala.collection.generic.CanBuildFrom[C[T],B,That]
[error]  required: scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[T],B,That]
[error]         } (bf)
[error]            ^
[error] one error found

类似的还有堆栈溢出的问题,其中包括一个从丹尼尔索布拉尔谁写建议(trav: C[T] with GenTraversableLike[T])但这并没有解决问题。

Answer 1:

Repr的参数CanBuildFrom并在*Like集合类型已经存在代表最精确的集合的类型。 您的问题的解决方案是包装一个GenTraversableLike[A,Repr]代替C[T] 编译器会推断出确切类型为Repr ,一切都将完美的工作:

implicit class MeteredGenTraversablePimp[A, Repr](trav: GenTraversableLike[A,Repr]) {
  def foreachMetered(m: Meter)(f: A => Unit) = {
    m.start()
    try {
      trav.foreach{ e => f( e ); m.item_processed() }
    } finally {
      m.finish()
    }
  }

  def mapMetered[B, That](m: Meter)(f: A => B)(
    implicit bf: CanBuildFrom[Repr, B, That]
  ): That = {
    m.start()
    trav.map { x: A =>
      try {
        val z: B = f(x)
        m.item_processed()
        z
      } finally { m.finish() }
    }(bf)
  }
}


文章来源: Creating an implicit function that wraps map() in Scala with the right type: Not for the faint at heart