我已经阅读了有关无标签决赛的内容,我认为这很棒。我想建立自己的这种模式的小例子并解决问题。
这是我的代码:
trait Calculator[F[_]] {
def sum(a: Int, b: Int): F[Either[Throwable, Int]]
def minus(a: Int, b: Int): F[Either[Throwable, Int]]
}
object calculatorInstances {
implicit val futureCalculator: Calculator[Future] = new Calculator[Future] {
override def sum(a: Int, b: Int) =
Future {
Try(a + b).toEither
}
override def minus(a: Int, b: Int) =
Future {
Try(a - b).toEither
}
}
}
import calculatorInstances.futureCalculator
def getPlusAndMinus[F[_]: Monad: Calculator](a: Int, b: Int): F[Either[String, Int]] = {
for {
sum <- Calculator[F].sum(a, b)
res <- Calculator[F].minus(sum, b)
} yield res
}
由于not found: value Calculator
错误,此代码不起作用。我该怎么做呢?
答案 0 :(得分:4)
添加物化器:
object Calculator {
def apply[F[_]: Calculator]: Calculator[F] = implicitly
}
最好将类型为Calculator[F[_]]
的实例(如隐式futureCalculator
)放在同一个伴随对象Calculator
上,否则必须import calculatorInstances._
。
别忘了import cats.syntax.flatMap._
和import cats.syntax.functor._
。
sum
中的 sum <- Calculator[F].sum(a, b)
类型为Either[Throwable,Int]
,但是sum
中的Calculator[F].minus(sum, b)
应该是Int
。
也许返回的getPlusAndMinus
类型应该是F[Either[Throwable, Int]]
而不是F[Either[String, Int]]
。
也许修复for
理解的最简单方法是使用monad转换器:
def getPlusAndMinus[F[_] : Monad: Calculator](a: Int, b: Int): F[Either[Throwable, Int]] = {
(for {
sum <- EitherT(Calculator[F].sum(a, b))
res <- EitherT(Calculator[F].minus(sum, b))
} yield res).value
}
以防万一,整个代码:
import cats.data.EitherT
import cats.Monad
//import cats.syntax.flatMap._ // not necessary if we use EitherT
//import cats.syntax.functor._
import scala.concurrent.Future
import scala.language.higherKinds
import scala.util.Try
import scala.concurrent.ExecutionContext.Implicits.global
object App {
trait Calculator[F[_]] {
def sum(a: Int, b: Int): F[Either[Throwable, Int]]
def minus(a: Int, b: Int): F[Either[Throwable, Int]]
}
object Calculator {
def apply[F[_]: Calculator]: Calculator[F] = implicitly
implicit val futureCalculator: Calculator[Future] = new Calculator[Future] {
override def sum(a: Int, b: Int) =
Future {
Try(a + b).toEither
}
override def minus(a: Int, b: Int) =
Future {
Try(a - b).toEither
}
}
}
def getPlusAndMinus[F[_] : Monad: Calculator](a: Int, b: Int): F[Either[Throwable, Int]] = {
(for {
sum <- EitherT(Calculator[F].sum(a, b))
res <- EitherT(Calculator[F].minus(sum, b))
} yield res).value
}
}