Last active
May 25, 2021 13:50
-
-
Save lrytz/9e1f120c3e93ef50c93ed78b301d72fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Scala2 { | |
type Service[K <: Common.AbstractServiceKey[_]] = K#Protocol // error in 3: "K is not a legal path since it is not a concrete type" | |
} | |
// object Scala3 { | |
// type Service[K <: Common.AbstractServiceKey[_]] = K match { | |
// case Common.AbstractServiceKey[t] => t | |
// } | |
// } | |
object Common { | |
abstract class AbstractServiceKey[P] { | |
type Protocol = P | |
} | |
type Service[K <: AbstractServiceKey[_]] = Scala2.Service[K] | |
// type Service[K <: AbstractServiceKey[_]] = Scala3.Service[K] | |
val m = TypedMultiMap.empty[AbstractServiceKey[_], Service] | |
} | |
class TypedMultiMap[T <: AnyRef, K[_ <: T]] private (private val map: Map[T, Set[Any]]) { | |
def keySet: Set[T] = map.keySet | |
def inserted(key: T)(value: K[key.type]): TypedMultiMap[T, K] = { | |
val set = map.get(key) match { | |
case Some(s) => s | |
case None => Set.empty[Any] | |
} | |
new TypedMultiMap[T, K](map.updated(key, set + value)) | |
} | |
def get(key: T): Set[K[key.type]] = | |
map.get(key) match { | |
case Some(s) => s.asInstanceOf[Set[K[key.type]]] | |
case None => Set.empty | |
} | |
def valueRemoved(value: Any): TypedMultiMap[T, K] = { | |
val s = Set(value) | |
val m = map.collect { | |
case (k, set) if set != s => (k, set - value) | |
} | |
new TypedMultiMap[T, K](m) | |
} | |
def keyRemoved(key: T): TypedMultiMap[T, K] = new TypedMultiMap[T, K](map - key) | |
def removed(key: T)(value: K[key.type]): TypedMultiMap[T, K] = { | |
map.get(key) match { | |
case None => this | |
case Some(set) => | |
if (set(value)) { | |
val newset = set - value | |
val newmap = if (newset.isEmpty) map - key else map.updated(key, newset) | |
new TypedMultiMap[T, K](newmap) | |
} else this | |
} | |
} | |
def setAll(key: T)(values: Set[K[key.type]]): TypedMultiMap[T, K] = | |
new TypedMultiMap[T, K](map.updated(key, values.asInstanceOf[Set[Any]])) | |
def ++(other: TypedMultiMap[T, K]): TypedMultiMap[T, K] = | |
new TypedMultiMap[T, K](map ++ other.map) | |
override def toString: String = s"TypedMultiMap($map)" | |
override def equals(other: Any) = other match { | |
case o: TypedMultiMap[_, _] => map == o.map | |
case _ => false | |
} | |
override def hashCode: Int = map.hashCode | |
} | |
object TypedMultiMap { | |
private val _empty = new TypedMultiMap[Nothing, Nothing](Map.empty) | |
def empty[T <: AnyRef, K[_ <: T]]: TypedMultiMap[T, K] = _empty.asInstanceOf[TypedMultiMap[T, K]] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment