我有一个类型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 定义它?
答案 0 :(得分:2)
我不确定为什么Scalaz不提供此实例 - 它确实提供Monoid[Future[A]]
A
有一个monoid实例,并且范围内有隐式执行上下文。但是,您可以通过在Result
和Future[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
作为标识。