Hi,
I am struggling with a similar problem; I'm trying to build an
immutable Bag[K,E] by extending Map and MapLike to include a
Map(K,Set[E]).
This is my attempt after some head scratching:
---
class Bag[K, E]( val mapToSets: scala.collection.immutable.Map[K,
Set[E]])
extends scala.collection.immutable.Map[K, Set[E]]
with scala.collection.immutable.MapLike[K, Set[E], Bag[K, E]] {
def get(key: K):Option[Set[E]] = mapToSets.get(key)
override def empty = new Bag[K, E](Map.empty)
def +[B1 >: E](kv: (K, B1)): Bag[K, B1] = {
val (k, e) = (kv._1, kv._2)
val es = if (!mapToSets.isDefinedAt(k)) Set(e) else mapToSets(k)
++ Set(e)
new Bag[K, B1](mapToSets + (k, es))
}
def -(k: K) = new Bag(mapToSets - k)
def iterator:Iterator[(K, Set[E])] = mapToSets.iterator
override def stringPrefix = "Bag"
}
object Bag extends {
import scala.collection.mutable.{Builder, MapBuilder}
import scala.collection.generic.CanBuildFrom
def empty[K, E] = new Bag[K, E](Map.empty)
def apply[K, E](kvs: (K, E)*): Bag[K, E] = {
var a : Bag[K, E] = empty
for (kv <- kvs) a = a + kv
a
}
def newBuilder[K, E]: Builder[(K, E), Bag[K, E]] =
new MapBuilder[K, E, Bag[K, E]](empty)
implicit def canBuildFrom[K, E]
: CanBuildFrom[Bag[_, _], (K, E), Bag[K, E]] =
new CanBuildFrom[Bag[_, _], (K, E), Bag[K, E]] {
def apply(from: Bag[_,_]) = newBuilder[K, E]
def apply() = newBuilder[K, E]
}
}
---
error: type mismatch;
found :
scala.collection.immutable.Map[K,scala.collection.immutable.Set[_ >: E
<: B1]]
required: scala.collection.immutable.Map[K,Set[B1]]
new Bag[K, B1](mapToSets + (k, es))
---
Any ideas of how to solve this or perhaps an explanation of why I'm
doing it the wrong way?
/Bjorn Regnell
On 25 Juni, 18:59, Daniel Sobral <
dcsob...@gmail.com> wrote:
> On Mon, Jun 25, 2012 at 11:20 AM, Bruno Woltzenlogel Paleo
>
> <
bruno...@gmail.com> wrote:
>
> > Somehow, it is harder for me to extend immutable map, because the method "+"
> > seems a bit more complicated to implement than the corresponding mutable
> > method "+=". Right now, I make it work with a dynamic casting (see the
> > commented line in the code snippet below, if you have time/interest). But is
> > there a more elegant/correct way to do this?
>
> Yes. Remove the casting.
>
> > Also, it is not as clear to me how to implement the companion object methods
> > "newBuilder" and "canBuildFrom" (Should I implement them? Why? Could you
> > point me a good reference to learn more about this?). In the mutable case
>
> Yes, you should, because that's how all collections work.
>
> > class Substitution(override protected val m: Map[Var, E])
> > extends AbstractSubstitution with Map[Var, E] with MapLike[Var, E,
> > Substitution] {
> > def get(key: Var) = m.get(key)
> > def iterator: Iterator[(Var, E)] = m.iterator
> > def + [B >: E](kv: (Var, B)) = new Substitution(m +
> > kv.asInstanceOf[(Var,E)]) // Is there a more elegant/correct way to do this?
>
> Remove the casting. The method + should return Map[Var, B], not Map[Var, E].
>
> I suggest you look at Scala libraries as example. See, for instance,
> that object HashMap
> (
http://www.scala-lang.org/archives/downloads/distrib/files/nightly/do...)