Scala中Monoids的隐含的简单组合

时间:2017-11-19 17:57:57

标签: scala monoids

我有以下特点:

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)))
}

现在我想列出mapper for R = String,它会产生类似以下[mapped_string1, mapped_string2]或类似内容的内容 $%%""mapped_string1, mapped_string2""%%$

问题是以下幺半群实现不起作用:

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 ,不带尖括号

这种情况的解决方案是什么?也许只是monoids确实非常符合我的需求。也许我需要另一层次的抽象。

我的意思是如何在foldLeft完成后通常添加一些额外的操作来调用?没有耦合到String或任何特定类型。

1 个答案:

答案 0 :(得分:2)

package.json

表示如果您拥有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  ", "
  }