Search code examples
scalascala-catseither

List[EitherT[Future, String, CustomObj]] => EitherT[Future, String, List[CustomObj]]


How to use sequence function for List[EitherT[Future, String, CustomObj]] with custom class CustomObj ? I want something like that :

import scala.language.postfixOps
import cats.instances.list._
import cats.syntax.traverse._
import cats.data.EitherT
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

case class CustomObj(int: Int)

private val fst: EitherT[Future, String, CustomObj] =
  EitherT.pure[Future, String](CustomObj(1))
private val snd: EitherT[Future, String, CustomObj] =
  EitherT.pure[Future, String](CustomObj(2))

val source: List[EitherT[Future, String, CustomObj]] = fst :: snd :: Nil

val result: EitherT[Future, String, List[CustomObj]] = source.sequence

import scala.concurrent.duration._
val res = scala.concurrent.Await.result(result.value, 1 second)
println(res) // Right(List(CustomObj(1), CustomObj(2)))

Every time during compile I get

 error: Cannot prove that EitherT[Future,String,CustomObj] <:< G[A].

What does it mean <:< G[A] ?


Solution

  • This is an edited version, code @ https://scastie.scala-lang.org/Yaneeve/Jro89ZHwS3G23Aveanxc5A:

    import scala.language.postfixOps
    import cats.implicits._
    import cats.data.EitherT
    import scala.concurrent.Future
    import scala.concurrent.ExecutionContext.Implicits.global
    
    case class CustomObj(int: Int)
    
    private val fst: EitherT[Future, String, CustomObj] =
      EitherT.pure[Future, String](CustomObj(1))
    private val snd: EitherT[Future, String, CustomObj] =
      EitherT.pure[Future, String](CustomObj(2))
    
    val source: List[EitherT[Future, String, CustomObj]] = fst :: snd :: Nil
    
    val result: EitherT[Future, String, List[CustomObj]] = source.sequence
    
    import scala.concurrent.duration._
    val res = scala.concurrent.Await.result(result.value, 1 second)
    println(res) // Right(List(CustomObj(1), CustomObj(2)))
    

    Initially I wrote:

    Notice please that it didn't compile and produced odd compile messages until I added import scala.concurrent.ExecutionContext.Implicits.global

    And that holds true, BUT your trouble did not lie there. When I went to reproduce again, I got the error you had specified. The thing that was missing is an SBT/scalac flag: scalacOptions += "-Ypartial-unification"