我希望创建一个包含任意数量定义的元组的异构映射:
A -> B
C -> D
E -> F
etc现在每种类型的B,D,F。在理论上,我可以为我的异构地图创建一个Monoid。
是否有一个优雅的方法来实现这一点呢?
发布于 2018-07-10 13:32:57
那得看情况。如果您只想合并映射,那么很简单:只需HMap.empty[YourType](hm1.underlying ++ hm2.underlying)
但是你提到的单面表示你想要在相应的地方合并值。
我要说的是,没有补充资料是不可能的。例如,在编译时就可以知道这些信息,您在HMap中输入的类型的协积。
HMap不为您跟踪它,因此您必须自己实现它,或者使用一些包装器/构建器来更新每次添加内容时返回的类型。
class Wrapper[R[_,_], Vs <: Coproduct](hmap: HMap[R] = HMap.empty[R]) {
def +[K,V](k: K, v: V): Wrapper[R, V :+: Vs] = new Wrapper(hmap + (k,v))
}
object Wrapper {
def apply[R[_,_]]: Wrapper[R, CNil] = new Wrapper()
}这个Coproduct将允许您构建一些更通用的单半群(我实现半群是为了简单起见):
// treat it as pseudocode, sth might not work here
trait CoproductSemigroup[A] { def combine(a1: Any, a2: Any): Any }
implicit val cnilCombine = new CoproductSemigroup[CNil] { def combine(a1: Any, a2: Any): Any = ??? }
implicit val coproductCombine[H : ClassTag : Semigroup,
T <: Coproduct : CoproductSemigroup] =
new CoproductSemigroup[H :+: T] {
def combine(a1: Any, a2: Any): Any = {
if (implicitly[ClassTag[H].runtimeClass.isInstance(a1) &&
implicitly[ClassTag[H].runtimeClass.isInstance(a2))
implicitly[Semogroup[H].combine(a1.asInstanceOf[H], a2.asInstanceOf[H])]
else
implicitly[CoproductSemigroup[T]].combine(a1, a2)
}
}这已经变得很难看了,然后您将不得不对每个组使用manually group values by the same key并应用这个函数。
最后,您必须从上面的代码中创建一个单样体。最有可能是包装器,因为它已经包含了您在这些实现中确实需要的类型信息。
也许有更好的方法来实现它,但我唯一能看到的是.又丑又不安全。
https://stackoverflow.com/questions/51248972
复制相似问题