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

时间:2016-12-27 18:17:12

标签: scala sum 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)
}

但是,我错过了Monoid的{​​{1}}个实例。如何使用 Scalaz 定义它?

learning Scalaz - sum function

1 个答案:

答案 0 :(得分:2)

我不确定为什么Scalaz不提供此实例 - 它确实提供Monoid[Future[A]] A有一个monoid实例,并且范围内有隐式执行上下文。但是,您可以通过在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作为标识。