Reduce / fold over list of monoid but reducer returns Either

☆樱花仙子☆ 提交于 2019-12-07 06:49:29

问题


Ive found myself in the situation a couple of times where i have a reducer / combine fn like so:

  def combiner(a: String, b: String): Either[String, String] = {
    (a + b).asRight[String]
  }

Its a dummy implementation but the fn can fail so it returns an either. I then I have a list of values I want to pass through this with reduce / fold. The best I can come up with (assuming the List's type is a monoid) is this:

  def combine(items: Vector[String]) = {

    items.foldLeft(Monoid[String].empty.asRight[String]) { case (acc, value) =>
      acc.flatMap( accStr => combiner(accStr, value))
    }
  }

Its a bit clumsy and as its a fairly generic pattern I suspect there's a better way to do it using cats.


回答1:


You might want to take a look at foldM. Your code would then look approximately like this:

Foldable[Vector].foldM(items, "")(combiner)

The foldM method has the signature

def foldM[G[_], A, B](fa: F[A], z: B)(f: (B, A) ⇒ G[B])(implicit G: Monad[G]): G[B]

so in your case, the type(-constructor) parameters would unify as follows:

  • G[X] = Either[String, ?]
  • A = String
  • B = String
  • F[X] = Vector[X]

so that f: (A, B) => G[B] would become f: (String, String) => Either[String, String], which is exactly the type of combiner when it's converted into a function.



来源:https://stackoverflow.com/questions/56451987/reduce-fold-over-list-of-monoid-but-reducer-returns-either

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!