Реализуйте коллекцию scala, чтобы карта, фильтр и т. Д. Создавали правильный тип

Я пытаюсь реализовать карту со значениями по умолчанию , и мне бы хотелось, чтобы фильтры, карты и т. Д. Вместо DefaultingMap были также по возможности создайте DefaultingMap . Вот моя первоначальная реализация:

class DefaultingMap[K, V](defaultValue: => V)
extends mutable.HashMap[K, V]
with mutable.MapLike[K, V, DefaultingMap[K, V]] {

  override def empty = new DefaultingMap[K, V](defaultValue)

  override def default(key: K): V = {                 
    val result = this.defaultValue
    this(key) = result
    result                                            
  }
}

Я получаю объекты типа DefaultingMap , когда использую фильтр , но не когда использую map :

scala> val counter = new DefaultingMap[Char, Int](0)
counter: DefaultingMap[Char,Int] = Map()

scala> for (c <- "ababcbbb") counter(c) += 1

scala> counter.filter{case (k, v) => v > 1}
res1: DefaultingMap[Char,Int] = Map((a,2), (b,5))

scala> counter.map{case (k, v) => (k, v * 2)}
res2: scala.collection.mutable.HashMap[Char,Int] = Map((a,4), (c,2), (b,10))

Разница между похоже, что эти два метода заключаются в том, что map принимает неявный CanBuildFrom . Итак, я понял, что мне нужно где-то иметь неявное def , чтобы предоставить CanBuildFrom . Моя первая интуиция заключалась в том, чтобы сделать то, что сделано в HashMap:

object DefaultingMap extends generic.MutableMapFactory[DefaultingMap] {

  def empty[K, V]: DefaultingMap[K, V] = // Not possible!

  implicit def canBuildFrom[K, V]:
    generic.CanBuildFrom[Coll, (K, V), DefaultingMap[K, V]] = 
      new MapCanBuildFrom[K, V]
}

Я считаю, что это заставит его скомпилировать, но этот подход не сработает, потому что невозможно определить метод пустой - вам нужно знать, что defaultValue должно быть. Если бы я мог определить CanBuildFrom в самом классе вместо сопутствующего объекта, я был бы в порядке, потому что там доступно defaultValue .

Как мне заставить это работать ?

5
задан Community 23 May 2017 в 11:44
поделиться