【发布时间】:2021-11-17 15:52:09
【问题描述】:
假设,只要类型 A 可以表示一个不太精确的物理值测量,我就会有一个 Imprecise[A] 的实例。
trait Imprecise[A]:
type Precision
val ord: Ordering[Precision]
def precision(a: A): Precision
例如,这个Bounds 类型在它的伴生对象中有一个给定的实例:
case class Bounds[N: Numeric](min: N, max: N):
if summon[Ordering[N]].compare(min, max) > 1 then
throw new IllegalArgumentException
object Bounds:
import scala.math.Numeric.Implicits.infixNumericOps
import scala.math.Ordering.Implicits.infixOrderingOps
given [N: Numeric]: Imprecise[Bounds[N]] with
type Precision = N
val ord = summon[Ordering[N]]
def precision(rng: Bounds[N]) = rng.max - rng.min
现在我的程序可以开始处理需要观察的物理特征了:
trait Feature[A: Imprecise]:
type Observation = A
val imprecise = summon[Imprecise[A]]
type Precision = imprecise.Precision
def within(bound: Precision) = new RequiredFeature(this, bound)
class RequiredFeature(val feature: Feature[_], val min_precision: feature.Precision)
case class Temperature(chamber_id: Int) extends Feature[Bounds[Double]]
case class Pressure(chamber_id: Int) extends Feature[Bounds[Float]]
但是,当我最终尝试制作所需的功能时:
val rf = Temperature(3).within(7.0)
编译器抱怨
Found: (7.0d : Double)
Required: ?1.Precision
where: ?1 is an unknown value of type exp.Temperature
val rf = Temperature(3).within(7.0)
如果我放弃任何依赖于路径的类型并将精度作为常规泛型类型参数到处传递,那么到目前为止编写的代码可以编译。但是如果我不想这样做呢?是否有类似 Aux 模式的策略可以帮助编译器看到这是对 within 的有效调用?
【问题讨论】:
-
应该
summon[Ordering[N]].compare(min, max) > 1是= 1吗? (或> 0?) -
class RequiredFeature没有泛型,但您在def within(bound: Precision) = new RequiredFeature[A](this, bound)中使用它就好像它有一样。 -
@DmytroMitin 这可能是我在将代码复制到 Stackoverflow 时错误地调整了代码。我将对其进行编辑以确保唯一的错误是我要询问的那个。
-
@DmytroMitin 我认为this 显示了问题的根源,由于某种原因,编译器不知道 Precision 的正确类型,不确定是否需要这样做,或者是错误还是错误在代码中。
-
@DmytroMitin 是的
compare(min, max) > 1应该是compare(min, max) > 0,但这与此处的类型推断无关。
标签: scala type-inference scala-3 path-dependent-type