注意到我的代码基本上迭代了列表并更新了Map中的值,我首先创建了一个简单的辅助方法,该方法采用了一个函数来转换map值并返回一个更新的map.随着程序的发展,它获得了一些其他Map转换函数,因此很自然地将它转换为一个隐式值类,可以添加方法scala.collection.immutable.Map[A, B].该版本运行正常.
但是,没有任何关于需要特定地图实现的方法,它们似乎适用于scala.collection.Map[A, B]甚至是MapLike.所以我希望它在地图类型以及键和值类型中是通用的.这就是梨形的地方.
我当前的迭代看起来像这样:
implicit class RichMap[A, B, MapType[A, B] <: collection.Map[A, B]](
val self: MapType[A, B]
) extends AnyVal {
def updatedWith(k: A, f: B => B): MapType[A, B] =
self updated (k, f(self(k)))
}
Run Code Online (Sandbox Code Playgroud)
此代码无法编译,因为self updated (k, f(self(k)))isa scala.collection.Map[A, B],它不是MapType[A, B].换句话说,返回类型self.updated就好像self's类型是上层类型绑定而不是实际声明类型.
我可以通过向下转换"修复"代码:
def updatedWith(k: A, f: B => B): MapType[A, B] =
self.updated(k, f(self(k))).asInstanceOf[MapType[A, B]]
Run Code Online (Sandbox Code Playgroud)
这种感觉并不令人满意,因为向下转换是一种代码气味并且表明对类型系统的误用.在这种特殊情况下,似乎值始终是强制转换类型,并且整个程序编译并正确运行此向下转换支持此视图,但它仍然有气味.
那么,是否有更好的方法来编写此代码以使scalac在不使用向下转换的情况下正确推断类型,或者这是编译器限制并且需要向下转换?
[已编辑添加以下内容.]
我使用这种方法的代码有点复杂和混乱,因为我仍在探索一些想法,但最小的例子是将频率分布计算为副作用,代码大致如下:
var …Run Code Online (Sandbox Code Playgroud) scala ×1