Scala如何用Cats Semigroupal合并不同值类型的Map无需手动创建实例
问题原因
Semigroupal要求传入的类型是单参数类型构造器(即形如F[_],比如Option、List这类仅需一个类型参数的类型),而Map是双参数类型构造器Map[K, V],必须先固定键的类型K得到单参数构造器Map[K, *],才能适配Semigroupal的要求,因此直接写Semigroupal[Map]无法匹配到隐式实例。
解决方案
所有方案都需要提前导入Cats的Map实例依赖:
import cats.instances.map._
方案1:显式指定参数化类型调用Semigroupal
直接给Semigroupal传入固定了键类型的Map即可,无需手动创建实例:
- 若项目已安装
Kind Projector插件(Scala常用类型级编程插件),可以用简化语法:
import cats.Semigroupal val m1 = Map("a" -> "a") val m2 = Map("a" -> 1) val res = Semigroupal[Map[String, *]].product(m1, m2) // 输出结果:Map(a -> (a,1))
- 若未安装插件,用Scala原生类型投影写法:
val res = Semigroupal[({ type L[V] = Map[String, V] })#L].product(m1, m2)
方案2:用语法扩展实现最简调用
导入Semigroupal语法扩展后可以直接在Map实例上调用product方法,完全不需要手动操作Semigroupal实例:
import cats.syntax.semigroupal._ val m1 = Map("a" -> "a") val m2 = Map("a" -> 1) val res = m1.product(m2) // 输出结果:Map(a -> (a,1))
注意事项
当前Map的Semigroupal实例默认仅保留两个Map的交集键,仅交集键的值会被组合为元组,仅在单个Map中存在的键会被丢弃。如果需要保留所有键、给缺失值填充默认值,可以自定义Semigroup实例实现。
内容的提问来源于stack exchange,提问作者slovvic
相关产品推荐
相关产品推荐

