类型以对双精度施加所需的约束
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 在构建后的任何时候将概率视为 Double
。 For 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]]
我想要一个 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 在构建后的任何时候将概率视为 Double
。 For 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]]