【问题标题】:Can't make simple tagless final example无法制作简单的无标签最终示例
【发布时间】:2019-08-28 16:07:33
【问题描述】:

我读过关于无标签决赛的文章,我认为它很棒。我想构建我自己的这种模式的小例子,但遇到了问题。

这是我的代码:

  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】:

    添加物化器:

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

    最好将类型类Calculator[F[_]](如隐式futureCalculator)的实例放入同一个伴生对象Calculator,否则您将不得不import calculatorInstances._

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

    sum &lt;- Calculator[F].sum(a, b) 中的sumEither[Throwable,Int] 类型,但Calculator[F].minus(sum, b) 中的sum 应该是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
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 2014-06-20
      • 1970-01-01
      • 2020-10-07
      • 2023-04-10
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多