Scala одноэлементных объектов и неявное разрешение - PullRequest
0 голосов
/ 04 августа 2020

Как лучше всего заставить неявное разрешение в scala работать с одноэлементными объектами? Это особенно характерно для Either и настраиваемых объектов ошибок.

В приведенном ниже примере кода метод возвращает специфичную для приложения c ошибку, заключенную в IO. Ошибка представлена ​​одноэлементным объектом, расширяющим Throwable. Этот код не компилируется, потому что scala ищет неявное выражение для AppSpecificError.type вместо Throwable.

Можно поместить все в переменные с указанным типом, но это выглядит странно. Это довольно распространенный случай, как лучше всего его решить?

import cats.data.EitherT
import cats.effect.IO
import cats.implicits._

import scala.util.Random

object EitherTest {

  case object AppSpecificError extends Throwable

  def random: IO[Boolean] = {
    IO(Random.nextBoolean())
  }

  def appMethod(flag: Boolean): EitherT[IO, Throwable, Int] = {
    for {
      flag <- EitherT.right(random)
      result <- if (flag) {
        EitherT.left[Int](AppSpecificError.pure[IO]) // compilation error here
      } else {
        EitherT.right[Throwable](10.pure[IO])
      }
      // can be more computations here
    } yield result
  }

  def main(args: Array[String]): Unit = {
    appMethod(true).value.unsafeRunSync() match {
      case Right(s) => println("Success")
      case Left(error) => println(error)
    }
  }
}



Error:(18, 14) type mismatch;
 found   : cats.data.EitherT[cats.effect.IO,_1,Int] where type _1 >: EitherTest.AppSpecificError.type <: Throwable
 required: cats.data.EitherT[cats.effect.IO,Throwable,Int]
Note: _1 <: Throwable, but class EitherT is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
      result <- if (flag) {

1 Ответ

4 голосов
/ 04 августа 2020

Попробуйте указать параметры типа явно

EitherT.left[Int][IO, Throwable](AppSpecificError.pure[IO])

или используйте описание типа

EitherT.left[Int]((AppSpecificError: Throwable).pure[IO])
...