Scala中具有Monoid的隐含体的简单组合



我有以下特点:

import scalaz.Monoid
trait Mapper[M, R] {
def map(m: M): R
}
object Mapper {
@inline implicit def listMapper[M, R]
(implicit mapper: Mapper[M, R], s: Monoid[R]): Mapper[List[M], R] =
(xs: List[M]) => xs. foldLeft(s.zero)((r, m) => s.append(r, mapper.map(m)))
}

现在,我想列出具有R = String的映射器,该映射器生成类似于以下[mapped_string1, mapped_string2]$%%""mapped_string1, mapped_string2""%%$

问题是以下monoid实现将不起作用:

implicit val myStringMonoid: Monoid[String] = new Monoid[String] {
override def zero = ""
override def append(f1: String, f2: => String) =
if (f1.isEmpty) f2
else if(f2.isEmpty) f1
else f1 + ", " + f2
}

所以下面的行

println(implicitly[Mapper[List[String], String]].map(List("mapped_string1", "mapped_string2")))

打印不带尖括号的mapped_string1, mapped_string2

这种情况的解决方案是什么?也许单体很适合我的需求。也许我需要另一个抽象层次。

我的意思是,在foldLeft完成后,通常如何添加一些要调用的附加操作?而不耦合到CCD_ 6或任何特定类型。

implicit def listMapper[M, R]
(implicit mapper: Mapper[M, R], s: Monoid[R]): Mapper[List[M], R] = ???

意味着如果你有Mapper[M, R],那么你就有Mapper[List[M], R]。但要使这项工作发挥作用,您应该有一些初始Mapper[M, R]

因此,如果你想拥有Mapper[List[String], String],你应该添加例如

implicit def stringMapper: Mapper[String, String] = s => s

然后这就产生

println(implicitly[Mapper[List[String], String]].map(List("mapped_string1", "mapped_string2"))) 
//mapped_string1, mapped_string2
def addBrackets(s: String, openBracket: String, closingBracket: String) = 
openBracket + s + closingBracket
val s = implicitly[Mapper[List[String], String]].map(List("mapped_string1", "mapped_string2"))
println(addBrackets(s, "[", "]"))
//[mapped_string1, mapped_string2]

否则,您可以更改

implicit val myStringMonoid: Monoid[String] = new Monoid[String] {
override def zero = ""
override def append(f1: String, f2: => String): String =
if (f1.isEmpty) f2
else if(f2.isEmpty) f1
else f1 + f2 // without  ", "
}

然后

val l = "[" ::
List("mapped_string1", "mapped_string2")
.flatMap(s => List(", ", s))
.tail ::: List("]")
println(implicitly[Mapper[List[String], String]].map(l))
//[mapped_string1, mapped_string2]

最新更新