在Fractional [T]方法中使用double值

时间:2016-02-11 15:12:02

标签: scala implicit-conversion implicit fractions

我有以下函数在2个边界之间生成Uniform分布值:

def Uniform(x: Bounded[Double], n: Int): Bounded[Double] = {
    val y: Double = (x.upper - x.lower) * scala.util.Random.nextDouble() + x.lower
    Bounded(y, x.bounds)
}

和Bounded的定义如下:

trait Bounded[T] {
  val underlying: T
  val bounds: (T, T)

  def lower: T = bounds._1
  def upper: T = bounds._2

  override def toString = underlying.toString + " <- [" + lower.toString + "," + upper.toString + "]"
}

object Bounded {
  def apply[T : Numeric](x: T, _bounds: (T, T)): Bounded[T] = new Bounded[T] {
    override val underlying: T = x
    override val bounds: (T, T) = _bounds
  }
}

但是,我希望Uniform处理所有Fractional[T]值,因此我想添加一个上下文绑定:

def Uniform[T : Fractional](x: Bounded[T], n: Int): Bounded[T] = {
    import Numeric.Implicits._
    val y: T = (x.upper - x.lower) * scala.util.Random.nextDouble().asInstanceOf[T] + x.lower
    Bounded(y, x.bounds)
}

这在执行Uniform[Double](x: Bounded[Double])时会起作用,但其他的是不可能的,并且在运行时获得ClassCastException,因为它们无法进行转换。有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:3)

我建议定义一个新类型类,它可以表示可以获得随机实例的类型:

otherclient(myclient, desipaddr, desport)

现在你可以像这样写import scala.util.Random trait GetRandom[A] { def next(): A } object GetRandom { def instance[A](a: => A): GetRandom[A] = new GetRandom[A] { def next(): A = a } implicit val doubleRandom: GetRandom[Double] = instance(Random.nextDouble()) implicit val floatRandom: GetRandom[Float] = instance(Random.nextFloat()) // Define any other instances here }

Uniform

并像这样使用它:

def Uniform[T: Fractional: GetRandom](x: Bounded[T], n: Int): Bounded[T] = {
  import Numeric.Implicits._
  val y: T = (x.upper - x.lower) * implicitly[GetRandom[T]].next() + x.lower
  Bounded(y, x.bounds)
}

rng这样的库可以为你提供类似的类型,但是它们往往专注于使用随机数字的纯函数方式,所以如果你想要更简单的东西你可能是最好的写你自己的。