这是另一个提到Problems with Scala Numeric[T]的问题。
今天我改变了一些代码,以支持牛顿估计下一个最好的种子。一切都很好,除了现在(?)无法A.fromDouble(v)
真正杀死的事实。
这是一个很长的样本,但最好放在这里。
import scala.annotation.tailrec
import math.{signum => sign}
import math.Fractional.Implicits._
import Ordering.Implicits._
/*
* 'f' is a "strictly increasing function" (derivative > 0).
* The sweep gives the value at which it gives 'goal' (within '+-bEps' margins).
*/
object NewtonianSweep {
def apply[A: Fractional, B: Fractional](
f: A => B,
fDerivate: A => Double,
goal: B,
bEps: B,
initialSeed: A,
aMin: A,
aMax: A
): A = {
assert( initialSeed >= aMin && initialSeed <= aMax )
// 'goal' is supposed to exist within the range (this also checks that
// the function is increasing - though doesn't (cannot) check "strict increasing",
// we'll just trust the caller.
//
assert( f(aMin) <= goal )
assert( f(aMax) >= goal )
@tailrec
def sweep( _seed: A ): A = {
val seed= _seed.max(aMin).min(aMax) // keep 'seed' within range
val bDiff= goal-f(seed) // >0 for heading higher, <0 for heading lower
if (bDiff.abs < bEps) {
seed // done (within margins)
} else {
val d= fDerivate(seed) // slope at the particular position (dy/dx)
assert( d>0.0 )
// TBD: How to get the calculated 'Double' to be added to 'seed: A'?
//
val aType= implicitly[Fractional[A]]
sweep( aType.plus( seed, aType.fromDouble( d*(bDiff.toDouble) ) ))
}
}
sweep( initialSeed )
}
}
我有两个Fractional
类型A
和B
的原因是它们在概念上是不同的。 A
通常是时间。 B
可以是任何东西。如果我对他们使用相同的类型,我也可以说他们是Double
的。
在我这样做之前,我想检查是否有人为这个问题找到了缺失的部分。
答案 0 :(得分:0)
我不确定我理解您在A
和B
之间的区别。但是既然你有f: A => B
,我认为它们可以以某种方式相互转换?然后查看代码,我的印象是A
是主要类型,那么为什么不将所有B
类型的内容转换为A
而不是相反?
然后你可以将任何转换都留给Double
,这似乎不是一个好主意。
/*
* 'f' is a "strictly increasing function" (derivative > 0).
* The sweep gives the value at which it gives 'goal' (within '+-bEps' margins).
*/
object NewtonianSweep {
def apply[A: Fractional, B: Fractional](
// f: A => B,
fDerivate: A => A,
goal: B,
bEps: B,
initialSeed: A,
aMin: A,
aMax: A
)(f: B => A) : A = {
assert( initialSeed >= aMin && initialSeed <= aMax )
// 'goal' is supposed to exist within the range (this also checks that
// the function is increasing - though doesn't (cannot) check "strict increasing",
// we'll just trust the caller.
//
val aGoal = f(goal)
val aEps = f(bEps)
assert(aMin <= aGoal)
assert(aMax >= aGoal)
val aType = implicitly[Fractional[A]]
@tailrec
def sweep(_seed: A): A = {
val seed = _seed.max(aMin).min(aMax) // keep 'seed' within range
val aDiff = aGoal - seed // >0 for heading higher, <0 for heading lower
if (aDiff.abs < aEps) {
seed // done (within margins)
} else {
val d = fDerivate(seed) // slope at the particular position (dy/dx)
assert(d > aType.zero)
val prod = d * aDiff
sweep(seed + prod)
}
}
sweep(initialSeed)
}
}