Search code examples
scalascala-cats

Scala, for comprehensions and EitherT


My technology stack is

  • Play Framework 2.6
  • Scala 2.12.6
  • Play-Slick 3.0.0
  • Cats 1.4.0

I am trying to achieve this function to update a row in the database

def update(userId: Long, user: User) = {
  (for {
    _ <- EitherT(updateUser(userId, user))
    user: User <- EitherT(findById(userId))
    userProfile: userProfile <- EitherT(userProfileRepository.findById(user.userProfileId))
  } yield (user, userProfile).map {
    case (user: User, userProfile: UserProfile) =>
      val response = new UserResponse(user, userProfile)
      Right(response)
    case error =>
      val str = s"update failure: $error"
      Left(str)
  }
}

but when I try to compile this code with EitherT I am getting

value withFilter is not a member of cats.data.EitherT


Solution

  • You're trying to pattern-match inside the for-comprehension (although it looks only as innocent type declaration). But for pattern-matching inside a for-comprehension withFilter implementation is required (think of what should happen if pattern-matching fails?). So remove matching over types and it should work:

    def update(userId: Long, user: User) = {
      (for {
        _ <- EitherT(updateUser(userId, user))
        user <- EitherT(findById(userId))
        userProfile <- EitherT(userProfileRepository.findById(user.userProfileId))
      } yield (user, userProfile).map {
        case (user: User, userProfile: UserProfile) =>
          val response = new UserResponse(user, userProfile)
          Right(response)
        case error =>
          val str = s"update failure: $error"
          Left(str)
      }
    }