gpt4 book ai didi

Scala:抽象隐式参数中的路径相关类型

转载 作者:行者123 更新时间:2023-12-02 09:20:01 24 4
gpt4 key购买 nike

假设我有一个类:

abstract class NumericCombine[A:Numeric,B:Numeric]{
type AB <: AnyVal
}

我想定义一个返回 NumericCombine[A,B].AB 类型值的函数。例如:

def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B].AB

但是编译器不允许我在 plus 中引用 .AB

仅供引用,this是这个问题的上下文。

我想提供:

implicit object IntFloat extends NumericCombine[Int,Float]{override type AB = Float}
implicit object FloatInt extends NumericCombine[Float,Int]{override type AB = Float}

及其其他 44 个 friend (7*6-2),以便我可以如下定义我的 plus:

def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B].AB =
{
type AB = Numeric[NumericCombine[A,B].AB]
implicitly[AB].plus(x.asInstanceOf[AB],y.asInstanceOf[AB])
}

plus(1f,2)//=3f
plus(1,2f)//=3f

我知道 Scala 中的值转换允许我定义这一事实

def plus[T](a: T, b: T)(implicit ev:Numeric[T]): T = ev.plus(a,b)

并按照建议实现上述行为 here ,但由于我想将此函数用作更大函数的一部分(在作为此问题的上下文提到的链接中进行了描述),因此我需要使用 A 来参数化该函数>B.

更新:

我在这方面取得了一些良好的进展。

我的 NumericCombine 现在看起来像这样:

abstract class NumericCombine[A: Numeric, B: Numeric] {
type AB <: AnyVal

def fromA(x: A): AB
def fromB(y: B): AB

val numeric: Numeric[AB]

def plus(x: A, y: B): AB = numeric.plus(fromA(x), fromB(y))
def minus(x: A, y: B): AB = numeric.minus(fromA(x), fromB(y))
def times(x: A, y: B): AB = numeric.times(fromA(x), fromB(y))
}

我的 plus 函数如下所示:

def plus[A: Numeric, B: Numeric](x: A, y: B)(implicit ev:NumericCombine[A,B])
: ev.AB = ev.plus(x, y)

需要plus的加权平均函数最终变得有点复杂:

def accumulateWeightedValue[A: Numeric,B: Numeric]
(accum: (A, NumericCombine[A, B]#AB), ValueWithWeight: (A, B))
(implicit combine: NumericCombine[A, B], timesNumeric: Numeric[NumericCombine[A, B]#AB])
:(A,NumericCombine[A, B]#AB)=

这是一个接受(A,AB),(A,B)并返回(A,AB)的函数。我在 weightedSum 内部使用它,它只是聚合:

def weightedSum[A: Numeric,B: Numeric](weightedValues: GenTraversable[(A, B)])
(implicit numericCombine: NumericCombine[A, B], plusNumeric: Numeric[NumericCombine[A, B]#AB])
: (A, NumericCombine[A, B]#AB)

现在,编译得很好。第二个隐式参数似乎确实有问题。即 Numeric[AB] 当我使用隐式值运行它时,例如 NumericCombine[Int,Float] 存在。它给了我:

could not find implicit value for parameter plusNumeric: Numeric[NumericCombine[Int,Float]#AB]

请注意,在 NumericCombine 中,我有一个 Numeric[AB],它应该可用于隐式查找。将其存储在本地,在 [Int,Float] 的情况下:

val lst: Seq[(Int, Float)] =List((1,3f),(1,4f))
implicit val num: Numeric[Float] = IntFloat.numeric //IntFloat extends NumericCombine[Int,Float]
weightedSum(lst)

在调用需要它的函数之前在局部变量中似乎没有任何影响。那么为什么它会被隐式系统拾取呢。

最佳答案

只需使用

def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B]#AB

请注意 #(哈希)而不是 .(点)。这称为“类型投影”。点表示法称为“路径相关类型”。我告诉你这些名字,以便你可以轻松地谷歌搜索更多信息。简单地说,# 用于访问类/特征中的类型,而 .用于从对象/值访问类型。

示例:

trait Foo {
type T
}

val fooObj: Foo = new Foo {
type T = Int
}

type t1 = fooObj.T
type t2 = Foo#T

关于Scala:抽象隐式参数中的路径相关类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43392597/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com