@@ -21,52 +21,60 @@ import cats.arrow.FunctionK
2121import cats .data .Tuple2K
2222import cats .{ Monoid , SemigroupK , ~> }
2323
24- class MapK [K [_ ], V [_ ]] private [MapK ](val untyped : Map [K [_ ], V [_ ]]) { self =>
24+ class MapK [K [* ], V [* ]] private [MapK ](val untyped : Map [K [Any ], V [Any ]]) { self =>
2525 type Entry [x] = (K [x], V [x])
2626 type Combiner [x] = (V [x], V [x]) => V [x]
2727
28- def contains (key : K [_]): Boolean = untyped.contains(key)
29- def get [T ](key : K [T ]): Option [V [T ]] = untyped.get(key).map(_.asInstanceOf [V [T ]])
30- def apply [T ](key : K [T ]): V [T ] = untyped(key).asInstanceOf [V [T ]]
31- def + [T ](key : K [T ], value : V [T ]): MapK [K , V ] = new MapK [K , V ](untyped + (key -> value))
28+ override def equals (obj : Any ): Boolean = obj match {
29+ case that : MapK [? , ? ] => this .untyped == that.untyped
30+ case _ => false
31+ }
32+ override def hashCode (): Int = untyped.hashCode()
33+
34+ @ inline private def asAny [X [_], A ](x : X [A ]): X [Any ] = x.asInstanceOf [X [Any ]]
35+
36+ def contains [A ](key : K [A ]): Boolean = untyped.contains(asAny(key))
37+ def get [T ](key : K [T ]): Option [V [T ]] = untyped.get(asAny(key)).map(_.asInstanceOf [V [T ]])
38+ def apply [T ](key : K [T ]): V [T ] = untyped(asAny(key)).asInstanceOf [V [T ]]
39+ def + [T ](key : K [T ], value : V [T ]): MapK [K , V ] = new MapK [K , V ](untyped + (asAny(key) -> asAny(value)))
3240 def updated [T ](key : K [T ], value : V [T ]): MapK [K , V ] = this .+ (key, value)
3341 def ++ (that : MapK [K , V ]): MapK [K , V ] = {
34- val out = Map .newBuilder[K [_ ], V [_ ]]
35- val add = new FunctionK [Entry , Lambda [x => Unit ] ] {
36- def apply [A ](fa : (K [A ], V [A ])): Unit = out += fa
42+ val out = Map .newBuilder[K [Any ], V [Any ]]
43+ val add = new FunctionK [Entry , ({ type U [x] = Unit }) # U ] {
44+ def apply [A ](fa : (K [A ], V [A ])): Unit = out += (asAny(fa._1) -> asAny(fa._2))
3745 }
3846 this .foreach(add)
3947 that.foreach(add)
4048 new MapK [K , V ](out.result())
4149 }
42- def foreach (f : Entry ~> Lambda [x => Unit ]): Unit = {
43- for ((key, value) <- untyped) {
44- val t = MapK .tuple(key, value)
45- f(t)
46- }
50+ def foreach (f : Entry ~> ({ type U [x] = Unit })# U ): Unit = {
51+ def handleKv [A ](kv : (K [Any ], V [Any ])) = f(MapK .tuple(kv._1.asInstanceOf [K [A ]], kv._2.asInstanceOf [V [A ]]))
52+ for (kv <- untyped) handleKv(kv)
4753 }
4854 def mapValues [V2 [_]](f : V ~> V2 ): MapK [K , V2 ] = {
49- val mapped = Map .newBuilder[K [_], V2 [_]]
50- for ((k, v) <- untyped) mapped += (k -> f(v))
55+ val mapped = Map .newBuilder[K [Any ], V2 [Any ]]
56+ def handleKv [A ](kv : (K [Any ], V [Any ])): Unit = mapped += (kv._1.asInstanceOf [K [Any ]] -> asAny(f(kv._2.asInstanceOf [V [A ]])))
57+ for (kv <- untyped) handleKv(kv)
5158 MapK .coerce[K , V2 ](mapped.result())
5259 }
5360 def map [V2 [_]](f : Entry ~> V2 ): MapK [K , V2 ] = {
54- val mapped = Map .newBuilder[K [_], V2 [_]]
55- for ((k, v) <- untyped) mapped += (k -> f(MapK .tuple(k, v)))
61+ val mapped = Map .newBuilder[K [Any ], V2 [Any ]]
62+ def handleKv [A ](kv : (K [Any ], V [Any ])) = mapped += (kv._1.asInstanceOf [K [Any ]] -> f(MapK .tuple[K , V , A ](kv._1.asInstanceOf [K [A ]], kv._2.asInstanceOf [V [A ]])).asInstanceOf [V2 [Any ]])
63+ for (kv <- untyped) handleKv(kv)
5664 MapK .coerce[K , V2 ](mapped.result())
5765 }
58- def keys : Iterable [K [_ ]] = untyped.keys
66+ def keys : Iterable [K [Any ]] = untyped.keys
5967
6068 def merge (that : MapK [K , V ], combiner : K ~> Combiner ): MapK [K , V ] = {
6169 var out : MapK [K , V ] = self
62- that.foreach(new FunctionK [that.Entry , Lambda [x => Unit ] ] {
70+ that.foreach(new FunctionK [that.Entry , ({ type U [x] = Unit }) # U ] {
6371 def apply [A ](kv : (K [A ], V [A ])): Unit = {
6472 val (k, newValue) = kv
6573 val v2 = self.get(k) match {
6674 case Some (oldValue) => combiner(k)(oldValue, newValue)
6775 case None => newValue
6876 }
69- out += (k, v2)
77+ out = out + (k, v2)
7078 }
7179 })
7280 out
@@ -79,7 +87,7 @@ class MapK[K[_], V[_]] private[MapK](val untyped: Map[K[_], V[_]]) { self =>
7987 override def toString () = {
8088 val sb = new StringBuilder ()
8189 sb append " TypedMap {\n "
82- foreach(new FunctionK [Entry , Lambda [x => Unit ] ] {
90+ foreach(new FunctionK [Entry , ({ type U [x] = Unit }) # U ] {
8391 def apply [A ](entry : Entry [A ]): Unit = {
8492 sb append " " append entry._1.toString append " : " append entry._2.toString append " \n "
8593 }
@@ -93,12 +101,14 @@ object MapK {
93101
94102 private [util] def tuple [K [_], V [_], T ](key : K [T ], value : Any ): (K [T ], V [T ]) = (key, value.asInstanceOf [V [T ]])
95103
96- def coerce [K [_], V [_]](map : Map [K [_ ], V [_ ]]): MapK [K , V ] = new MapK [K , V ](map)
104+ def coerce [K [_], V [_]](map : Map [K [Any ], V [Any ]]): MapK [K , V ] = new MapK [K , V ](map)
97105
98106 def empty [K [_], V [_]]: MapK [K , V ] = new MapK [K , V ](Map .empty)
99107
100- def apply [K [_], V [_]](entries : Tuple2K [K , V , _]* ): MapK [K , V ] = coerce[K , V ] {
101- entries.view.map { t => (t.first, t.second) }.toMap
108+ def apply [K [_], V [_]](entries : Tuple2K [K , V , ? ]* ): MapK [K , V ] = coerce[K , V ] {
109+ val mb = Map .newBuilder[K [Any ], V [Any ]]
110+ for (t <- entries) mb += (t.first.asInstanceOf [K [Any ]] -> t.second.asInstanceOf [V [Any ]])
111+ mb.result()
102112 }
103113
104114 implicit def catsMonoidForMapK [K [_], V [_]](implicit V : SemigroupK [V ]): Monoid [MapK [K , V ]] = new Monoid [MapK [K , V ]] {
@@ -110,4 +120,13 @@ object MapK {
110120 x.merge(y, getCombiner)
111121 }
112122 }
123+
124+ /** Convenience syntax for constructing `Tuple2K` instances to use with `MapK.apply`
125+ */
126+ object entrySyntax {
127+ implicit class RichKey [K [_], A ](key : K [A ]) {
128+ def ~> [V [_]](value : V [A ]) = Tuple2K [K , V , A ](key, value)
129+ def ~>> (value : A ) = Tuple2K [K , cats.Id , A ](key, value)
130+ }
131+ }
113132}
0 commit comments