3
\$\begingroup\$

With the help of SO I got my code working, but I think it still could be improved, in particular I do not like using asInstanceOf. Is there some way how to avoid it?

  trait UpdatedTrait[A, K, T] {
    def upd(k: K, t: T): A
  }

  trait UpdatedFunctor[A, K, T] {
    def upd(a: A, k: K, t: T): A
  }

  implicit class UpdatedMap[M[KT, TT] <: Map[KT, TT], K, T](a: M[K, T])(implicit f: UpdatedFunctor[M[K, T], K, T]) {
    def upd(k: K, t: T) = {
      f.upd(a, k, t)
    }
  }

  implicit def mapUpdatedFunctor[M[KT, TT] <: Map[KT, TT], K, T] = new UpdatedFunctor[M[K, T], K, T] {
    override def upd(a: M[K, T], k: K, t: T): M[K, T] = {
      a.updated(k, t).asInstanceOf[M[K, T]]
    }
  }

  val m = Map("A" -> "1")
  val sm = collection.immutable.SortedMap("A" -> "1")

  val mt = m.upd("A", "2")
  val smt: collection.immutable.SortedMap[String, String] = sm.upd("A", "2")

  println(mt)
  println(smt)
\$\endgroup\$
1
\$\begingroup\$

Using CanBuildFrom will help you here. What you need is an implicit CanBuildFrom[M[K, T], (K, T), M[K, T]] in scope, which will be provided by the standard library if it is possible to construct instances of the correct types.

import scala.collection.generic.CanBuildFrom

implicit def mapUpdatedFunctor[M[KT, TT] <: Map[KT, TT], K, T]
  (implicit cbf: CanBuildFrom[M[K, T], (K, T), M[K, T]]) = {
  new UpdatedFunctor[M[K, T], K, T] {
    override def upd(a: M[K, T], k: K, t: T): M[K, T] = {
      val builder = cbf()
      builder ++= a.updated(k, t)
      builder.result()
    }
  }
}

scala> m.upd("A", "2")
res1: scala.collection.immutable.Map[String,String] = Map(A -> 2)

scala> sm.upd("A", "2")
res3: scala.collection.immutable.SortedMap[String,String] = Map(A -> 2)

I actually answered a similar question recently using Maps and updated on SO.

\$\endgroup\$
  • 1
    \$\begingroup\$ I have tried what you suggested and while it compiles and works and it really gets rid of the asInstanceOf, the performance of such solution is really bad - hash map updated is guaranteed constant time. \$\endgroup\$ – Suma Feb 21 '16 at 20:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.