You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cats.sequence转换List[Either[String,Int]]时遇类型证明错误

How to convert List[Either[String, Int]] to Either[String, List[Int]] using Cats sequence?

Ah, I’ve run into this exact type inference snag with Cats’ sequence method before! Let’s break down what’s going wrong and how to fix it.

The Problem

You’re trying to turn a List[Either[String, Int]] into an Either[String, List[Int]] — a common operation to "flip" the structure so that if any element is a Left, you get that error immediately, otherwise you get a Right with all the values. But your code is throwing that confusing Cannot prove that Either[String,Int] <:< G[A] error. Here’s your code again for reference:

/* for ammonite users interp.load.ivy("org.typelevel" %% "cats-core" % "1.0.1") @ */
import cats.instances.list._
import cats.instances.either._
import cats.syntax.traverse._

val seqCorrect: List[Either[String, Int]] = List(Right(1), Right(2), Right(3))
val result1 = seqCorrect.sequence

Why This Happens

The core issue is that Either is a binary type constructor — it takes two types (the error type and the success type), but sequence expects a unary type constructor (like Option or List, which only take one type parameter). The compiler can’t automatically figure out that we want to "fix" the left type of Either to String and treat Either[String, _] as the single-parameter G it needs.

Fixes You Can Try

Here are a few straightforward ways to get this working:

1. Give the result an explicit type annotation

Sometimes all the compiler needs is a little hint about what you expect the final type to be. Adding this annotation will help it infer the right type parameters for sequence:

val result1: Either[String, List[Int]] = seqCorrect.sequence

2. Explicitly specify the type parameters for sequence

If the annotation doesn’t do the trick, you can tell the compiler exactly what G should be. In Scala 2, without plugins, you’ll need a type lambda:

val result1 = seqCorrect.sequence[({type L[x] = Either[String, x]})#L, Int]

If you have the Kind Projector plugin enabled (super common in Cats projects, since it cleans up kind-related syntax), you can write this more neatly:

val result1 = seqCorrect.sequence[Either[String, *], Int]

3. Use traverse(identity) instead

Since sequence is just a shortcut for traverse(identity), using this longer form can sometimes help the compiler infer types better:

val result1 = seqCorrect.traverse(identity)

Example Working Code

After applying any of these fixes, your code should compile and behave as expected. Here’s the full working version with the type annotation:

/* for ammonite users interp.load.ivy("org.typelevel" %% "cats-core" % "1.0.1") @ */
import cats.instances.list._
import cats.instances.either._
import cats.syntax.traverse._

val seqCorrect: List[Either[String, Int]] = List(Right(1), Right(2), Right(3))
val result1: Either[String, List[Int]] = seqCorrect.sequence
// result1 will be Right(List(1, 2, 3))

// And if you have an error in the list:
val seqWithError: List[Either[String, Int]] = List(Right(1), Left("Oops!"), Right(3))
val result2: Either[String, List[Int]] = seqWithError.sequence
// result2 will be Left("Oops!")

Just to confirm: your imports are all correct — you have the Traverse instance for List, the Applicative instance for Either, and the syntax to access sequence. The only issue was the compiler struggling to infer the right kind for Either.

内容的提问来源于stack exchange,提问作者Moebius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:07:21