Scalaz 自动类型类解析
Scalaz automatic typeclass resolution
我有几个 Map[String, String]
并且想合并它们以使值保持不变。默认情况下,Map semigroup 将连接字符串,所以我使用 Tags.LastVal
。
目前我正在做以下事情:
m1.mapValues(Tags.LastVal) |+| m2.mapValues(Tags.LastVal)
这个映射看起来冗长乏味。
我能以某种方式告诉编译器在范围内使用特定的 Semigroup,例如 Semigroup[Map[K, V @@ LastVal]
而不是默认的吗?
是的,您可以使您想要的实例隐含在您需要的范围内,编译器将找到它:
import scalaz._, Scalaz._
def mergeWithReplace(m1: Map[String, String], m2: Map[String, String]) = {
implicit val stringInstance: Semigroup[String] = Semigroup.lastSemigroup
m1 |+| m2
}
然后:
scala> mergeWithReplace(Map("a" -> "foo", "b" -> "qux"), Map("a" -> "bar"))
res0: Map[String,String] = Map(a -> bar, b -> qux)
即使不考虑连贯性的理论论证,这也是烦人和脆弱的。例如,隐式的名称必须是 stringInstance
以隐藏从 scalaz.std.string
导入的隐式,因为它具有更具体的类型,即使您没有要求更多具体类型。我不记得这种优先行为是否有某种借口,我真的不想关心,所以我倾向于避免使用这样的本地实例。
在这种情况下,恰好有更好的解决方案。 Scalaz 为地图提供 Plus
个实例,而 Plus
不知道值类型,因此它通过选择最后一个来组合值。这意味着您可以使用 Plus
:
中的 <+>
运算符获得您想要的内容
def mergeWithReplace(m1: Map[String, String], m2: Map[String, String]) =
m1 <+> m2
然后:
scala> mergeWithReplace(Map("a" -> "foo", "b" -> "qux"), Map("a" -> "bar"))
res0: scala.collection.immutable.Map[String,String] = Map(a -> bar, b -> qux)
不过,您通常不会那么幸运。
我有几个 Map[String, String]
并且想合并它们以使值保持不变。默认情况下,Map semigroup 将连接字符串,所以我使用 Tags.LastVal
。
目前我正在做以下事情:
m1.mapValues(Tags.LastVal) |+| m2.mapValues(Tags.LastVal)
这个映射看起来冗长乏味。
我能以某种方式告诉编译器在范围内使用特定的 Semigroup,例如 Semigroup[Map[K, V @@ LastVal]
而不是默认的吗?
是的,您可以使您想要的实例隐含在您需要的范围内,编译器将找到它:
import scalaz._, Scalaz._
def mergeWithReplace(m1: Map[String, String], m2: Map[String, String]) = {
implicit val stringInstance: Semigroup[String] = Semigroup.lastSemigroup
m1 |+| m2
}
然后:
scala> mergeWithReplace(Map("a" -> "foo", "b" -> "qux"), Map("a" -> "bar"))
res0: Map[String,String] = Map(a -> bar, b -> qux)
即使不考虑连贯性的理论论证,这也是烦人和脆弱的。例如,隐式的名称必须是 stringInstance
以隐藏从 scalaz.std.string
导入的隐式,因为它具有更具体的类型,即使您没有要求更多具体类型。我不记得这种优先行为是否有某种借口,我真的不想关心,所以我倾向于避免使用这样的本地实例。
在这种情况下,恰好有更好的解决方案。 Scalaz 为地图提供 Plus
个实例,而 Plus
不知道值类型,因此它通过选择最后一个来组合值。这意味着您可以使用 Plus
:
<+>
运算符获得您想要的内容
def mergeWithReplace(m1: Map[String, String], m2: Map[String, String]) =
m1 <+> m2
然后:
scala> mergeWithReplace(Map("a" -> "foo", "b" -> "qux"), Map("a" -> "bar"))
res0: scala.collection.immutable.Map[String,String] = Map(a -> bar, b -> qux)
不过,您通常不会那么幸运。