类型以对双精度施加所需的约束

Type to impose required constrains on a double

我想要一个 run time check on a Double,而不必在我的代码中分散检查。 我以为定义一个implicit class would do the job,就行了:

  implicit class Probability(val x: Double) {
    require(x >= 0.0 && x <= 1.0, "Probs are defined btw 0.0 and 1.0")
  }

缺少的部分是告诉 Scala 在构建后的任何时候将概率视为 DoubleFor this I suppose it is necessary to require a double side conversion.

object Foo {

  implicit class Probability(val x: Double) {
    require(x >= 0.0 && x <= 1.0, "Probs are defined btw 0.0 and 1.0")
  }

  implicit def asDouble(e: Probability): Double = e.x

  implicit def asProb(d: Double): Probability = new Probability(d)

  def max_(s: Seq[Double]): Double = {
    s.max
  }

  def max(s: Seq[Probability]): Double = {
    s.max
  }
}

val r1 = Foo.max_(List(2.0, 3.0, 5.0))
val r2 = Foo.max(List[Probability]=(2.0, 3.0, 5.0))

编辑

这可能已经成功了。 不确定引擎盖下发生了什么。

trait RangeBound
type Probability = Double with RangeBound
implicit def makeProb(p: Double): Probability = {
  assert (p >= 0.0 && p <= 1.0)
  p.asInstanceOf[Probability]
}

val p = List[Probability](0.1, 0.3, 0.2)
val r = p filter (_ > 0.1)

因为这行不通:

trait RangeBound
type Probability = Double with RangeBound
implicit def makeProb(p: Double): Probability = {
  assert (p >= 0.0 && p <= 1.0)
  p.asInstanceOf[Probability]
}

val p = List[Probability](0.1, 0.3, 0.2)
val r2 = p.max

错误:

Error:(10, 18) No implicit Ordering defined for Double with A$A288.this.RangeBound.
lazy val r2 = p.max;}
                ^

我不明白你想要什么。

但是,以防万一,这里有一个小建议给你。

  class Probability(val x: Double) extends AnyVal {
    override def toString = s"${x * 100} %"
    def PerCent = x * 100
  }

  object Probability {
    def apply(x: Double) = {
      if (x <= 1.0 && x >= 0.0)
        Some(new Probability(x))
      else
        None
    }
  }

  implicit def asProb(d: Double): Probability = Probability(d).get

只有在使用方法或值时才应调用隐式转换,例如我示例中的 PerCent :

scala> 0.3
res0: Double = 0.3

scala> 0.3.PerCent
res1: Double = 30.0

scala> 1.5
res2: Double = 1.5

scala> 1.5.PerCent
java.util.NoSuchElementException: None.get
  at scala.None$.get(Option.scala:347)
  at scala.None$.get(Option.scala:345)
  at .asProb(<console>:21)
  ... 43 elided

这启用了基本 运行 时间检查:

trait RangeBound
type Probability = Double with RangeBound

  implicit def makeProb(p: Double): Probability = {
    assert (p >= 0.0 && p <= 1.0)
    p.asInstanceOf[Probability]
  }

  implicit val probabilityOrdering = Ordering.Double.asInstanceOf[Ordering[Probability]]