加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

从Azavea Numeric获取隐式scala数字

发布时间:2020-12-16 08:57:47 所属栏目:安全 来源:网络整理
导读:我使用Azavea Numeric Sc??ala库进行通用数学运算.但是,我不能将它们与 Scala Collections API一起使用,因为它们需要一个scala Numeric,看起来好像两个Numerics是互斥的.有什么方法可以避免重新实现对Azavea Numeric的Scala Collections的所有数学运算,除了
我使用Azavea Numeric Sc??ala库进行通用数学运算.但是,我不能将它们与 Scala Collections API一起使用,因为它们需要一个scala Numeric,看起来好像两个Numerics是互斥的.有什么方法可以避免重新实现对Azavea Numeric的Scala Collections的所有数学运算,除了要求所有类型都有Numerics的上下文界限?

import Predef.{any2stringadd => _,_}

class Numeric {
  def addOne[T: com.azavea.math.Numeric](x: T) {
    import com.azavea.math.EasyImplicits._
    val y = x + 1 // Compiles

    val seq = Seq(x)
    val z = seq.sum // Could not find implicit value for parameter num: Numeric[T]
  }
}

Azavea数字定义为

trait Numeric[@scala.specialized A] extends java.lang.Object with 

com.azavea.math.ConvertableFrom[A] with com.azavea.math.ConvertableTo[A] with scala.ScalaObject {
   def abs(a:A):A
   ...remaining methods redacted...
}

object Numeric {
  implicit object IntIsNumeric extends IntIsNumeric
  implicit object LongIsNumeric extends LongIsNumeric
  implicit object FloatIsNumeric extends FloatIsNumeric
  implicit object DoubleIsNumeric extends DoubleIsNumeric
  implicit object BigIntIsNumeric extends BigIntIsNumeric
  implicit object BigDecimalIsNumeric extends BigDecimalIsNumeric

  def numeric[@specialized(Int,Long,Float,Double) A:Numeric]:Numeric[A] = implicitly[Numeric[A]]
}

解决方法

最通用的解决方案是编写一个包装com.azavea.math.Numeric的类,并根据它实现scala.math.Numeric:

class AzaveaNumericWrapper[T]( implicit val n: com.azavea.math.Numeric[T] ) extends scala.math.Numeric {
  def compare (x: T,y: T): Int = n.compare(x,y)
  def minus (x: T,y: T): T = n.minus(x,y)
  // and so on
}

然后实现隐式转换:

// NOTE: in scala 2.10,we could directly declare AzaveaNumericWrapper as an implicit class
implicit def toAzaveaNumericWrapper[T]( implicit n: com.azavea.math.Numeric[T] ) = new AzaveaNumericWrapper( n )

n本身是隐式的这一事实是关键:它允许自动使用类型为com.azavea.math.Numeric的隐式值,其中na隐含值为
输入scala.math.Numeric是预期的.
请注意,要完成,您可能也想要反向(编写一个ScalaNumericWrapper类,根据scala.math.Numeric实现com.azavea.math.Numeric).

现在,上述解决方案存在一个缺点:每次调用都会得到一个转换(因此就是一个实例)(对于一个上下文类型为scala.math.Numeric的方法,你只有一个com实例. azavea.math.Numeric在范围内).
因此,您实际上希望为每种数字类型定义AzaveaNumericWrapper的隐式单例实例.假设您有类型MyType和MyOtherType,您为其定义了com.azavea.math.Numeric的实例:

implicit object MyTypeIsNumeric extends AzaveaNumericWrapper[MyType]
implicit object MyOtherTypeIsNumeric extends AzaveaNumericWrapper[MyOtherType]
//...

另外,请记住,azavea的Numeric类的明显主要目的是大大提高执行速度(主要是由于类型参数专门化).
使用上面的包装器,你会失去专业化,从而失去它的速度.专业化必须一直使用,
一旦你调用一个非专业的泛型方法,你就进入非特殊泛型的世界(即使该方法然后回调一个专门的方法).
因此,在速度很重要的情况下,尝试直接使用azavea的Numeric而不是scala的Numeric(因为AzaveaNumericWrapper在内部使用它)
并不意味着你会得到任何速度增加,因为这里不会发生专业化).

你可能已经注意到我在我的例子中避免为Int,Long等类型定义AzaveaNumericWrapper的实例.这是因为对于这些类型,已经存在(在标准库中)scala.math.Numeric的隐式值.您可能想要隐藏它们(通过导入scala.math.Numeric.{ShortIsIntegral => _}之类的东西),以确保使用您自己的(azavea支持的)版本,但没有意义.我能想到的唯一原因是让它运行得更快,但如上所述,它不会.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读