在 Scalaz 中总结 OptionT[Future, BigDecimal] 列表

Summing a list of OptionT[Future, BigDecimal] in Scalaz

我有一个 List[Result[BigDecimal]] 类型的列表,我想对其求和。

type Result[A] = OptionT[Future, A]

规则是,如果有 Future(None),那么我们得到结果 Future(None)

我有函数[1]:

def sum[A: Monoid](as: List[A]): A = {
  val M = implicitly[Monoid[A]]
  as.foldLeft(M.zero)(M.append)
}

但是,我缺少 Result[BigDecimal]Monoid 实例。如何使用 Scalaz 定义它?

learning Scalaz - sum function

我不确定为什么 Scalaz 不提供这个实例——它确实提供了一个 Monoid[Future[A]],其中 A 有一个幺半群实例,并且范围内有一个隐式执行上下文。不过,您可以通过在 ResultFuture[Option[?]] 之间定义同构然后使用 IsomorphismMonoid 或 [这不会'通过直接定义一个实际上没有所需的语义]:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scalaz._, Scalaz._

type Result[A] = OptionT[Future, A]

implicit def resultMonoid[A: Monoid]: Monoid[Result[A]] = new Monoid[Result[A]] {
  def zero: Result[A] = Monoid[A].zero.point[Result]
  def append(f1: Result[A], f2: => Result[A]): Result[A] = (f1 |@| f2)(_ |+| _)
}

然后(使用 Scalaz 自己的 suml,但您的 sum 也可以):

scala> List(OptionT(Future(1.some)), OptionT(Future(2.some))).suml
res1: scalaz.OptionT[scala.concurrent.Future,Int] = OptionT(List())

scala> scala.concurrent.Await.result(res1.run, scala.concurrent.duration.Duration.Inf)
res2: Option[Int] = Some(3)

就其价值而言,Cats provides this instance,但是(就像 Scalaz 中的 Future[Option[?]] 实例一样)它具有 None 作为标识。