无法做出简单的无标签最终示例

问题描述 投票:0回答:1

我读过关于无标签的决赛,我认为这很棒。我想建立我自己的这个模式的小例子,并得到了问题。

这是我的代码:

  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错误,此代码不起作用。我怎么能正确地做到这一点?

scala functional-programming scala-cats tagless-final
1个回答
5
投票

添加材质:

object Calculator {
  def apply[F[_]: Calculator]: Calculator[F] = implicitly
}

最好将类型为Calculator[F[_]]的类(如隐式futureCalculator)放到同一个伴侣对象Calculator中,否则你将不得不使用import calculatorInstances._

别忘了import cats.syntax.flatMap._import cats.syntax.functor._

sumsum <- Calculator[F].sum(a, b)Either[Throwable,Int]类型,但sumCalculator[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
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.