减少/折叠幺半群列表但减少 returns 要么
Reduce / fold over list of monoid but reducer returns Either
我发现自己遇到过几次这样的情况,我有一个减速器/组合 fn,就像这样:
def combiner(a: String, b: String): Either[String, String] = {
(a + b).asRight[String]
}
它是一个虚拟实现,但 fn 可能会失败,所以它 returns 要么。然后我有一个值列表,我想通过 reduce / fold 传递它。我能想到的最好的(假设列表的类型是幺半群)是这样的:
def combine(items: Vector[String]) = {
items.foldLeft(Monoid[String].empty.asRight[String]) { case (acc, value) =>
acc.flatMap( accStr => combiner(accStr, value))
}
}
它有点笨拙,而且由于它是一个相当通用的模式,我怀疑有更好的方法使用猫来完成它。
您可能想看看 foldM。您的代码将大致如下所示:
Foldable[Vector].foldM(items, "")(combiner)
foldM
方法具有签名
def foldM[G[_], A, B](fa: F[A], z: B)(f: (B, A) ⇒ G[B])(implicit G: Monad[G]): G[B]
因此在您的情况下,类型(-构造函数)参数将统一如下:
G[X] = Either[String, ?]
A = String
B = String
F[X] = Vector[X]
这样 f: (A, B) => G[B]
就变成了 f: (String, String) => Either[String, String]
,这正是 combiner
转换为函数时的类型。
我发现自己遇到过几次这样的情况,我有一个减速器/组合 fn,就像这样:
def combiner(a: String, b: String): Either[String, String] = {
(a + b).asRight[String]
}
它是一个虚拟实现,但 fn 可能会失败,所以它 returns 要么。然后我有一个值列表,我想通过 reduce / fold 传递它。我能想到的最好的(假设列表的类型是幺半群)是这样的:
def combine(items: Vector[String]) = {
items.foldLeft(Monoid[String].empty.asRight[String]) { case (acc, value) =>
acc.flatMap( accStr => combiner(accStr, value))
}
}
它有点笨拙,而且由于它是一个相当通用的模式,我怀疑有更好的方法使用猫来完成它。
您可能想看看 foldM。您的代码将大致如下所示:
Foldable[Vector].foldM(items, "")(combiner)
foldM
方法具有签名
def foldM[G[_], A, B](fa: F[A], z: B)(f: (B, A) ⇒ G[B])(implicit G: Monad[G]): G[B]
因此在您的情况下,类型(-构造函数)参数将统一如下:
G[X] = Either[String, ?]
A = String
B = String
F[X] = Vector[X]
这样 f: (A, B) => G[B]
就变成了 f: (String, String) => Either[String, String]
,这正是 combiner
转换为函数时的类型。