考虑如下课程:
import scala.collection.mutable.{HashMap => MutableHashMap}
class CustomHashMap[K,V](hashMap: MutableHashMap[K,V], initVal: V) {
def addMaps(first: MutableHashMap[K, V], second: MutableHashMap[K, V]): MutableHashMap[K, V] = {
second.foreach(pair => { first += (pair._1 -> (first.getOrElse(pair._1, initVal) + pair._2)) } )
//The above line throws a compile time error
first
}
//Other functions
}
添加两个参数化类型后,会出现编译时错误
expected (K,V) recieved (K,String)
我想知道为什么scala会进行隐式转换?由于java中不允许运算符重载,这似乎是合乎逻辑的,但是在scala的情况下,V实际上可能是一个可以为它定义方法 +
的类 .
3 回答
这是一种如何手动实现这种事情的方法:
因为看起来你正试图定义一个幺半群,我会冒昧地将
initVal
从addMaps
移动到操作的定义 .这可以使用Scala中的常见类型类模式来完成,但您必须手动定义
+
对于您希望在 Map 中使用的每种类型的含义 .基本上你有一个特点
Monoid
:比为扩展该特征的每种类型定义隐式实现 . 你可以在中定义它们
Monoid
的伴侣对象,它将自动使用,类T的伴侣对象,它也会自动使用,
作为隐含的其他地方,但您必须手动导入它 .
以下是定义字符串和各种数字实现的
Monoid
伴随对象的示例:然后在你的
addMaps
函数请求中, Map 的元素应该是Monoid
,并使用元素上的monoid实现提供的操作:以下是测试工作原理:
我相信问题是因为你试图做
V + V
而Scala推断类型V
是一个字符串 . 这是我尝试向编译器指定V
将扩展一个支持V + V => V
的特征(称为Adder
) .上述解决方案将需要
V
来扩展Adder
. 如果我们想让用户更容易,我们可以使用隐式转换 . 为了添加自定义类型,您需要对范围进行隐式转换(类似于我们对Int,String和Double所做的操作) .只是为了添加marios的答案,你可能想要使用一个函数式编程库,它已经为你提供了类型类
Semigroup
(加法)或Monoid
(加法和空元素) .例如Cats:
去测试:
通常,如果将加法函数分离为类型类(此处为
Monoid
)而不是要求它成为值类型V <: Adder
的一部分,则会使代码更加模块化 .