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

Scala中如何优雅扁平化两侧类型相同的F[Either[T, T]]结构

更简洁的实现方案

Scala标准库和Cats都提供了专门的语法糖处理这种Either[T, T]合并的场景,比手动写fold(identity, identity)语义更清晰:

  1. Scala 2.13+ 标准库原生支持
    标准库的Either从2.13版本开始内置了merge方法,作用就是当左右两侧类型相同时,直接提取包裹的值,不需要手动写fold逻辑。你的方法可以简化为:
def foo[F[_]: Functor, T](eitherF: F[Either[T, T]]): F[T] = eitherF.map(_.merge)
  1. Cats库跨版本兼容实现
    如果你的项目Scala版本低于2.13,只要引入Cats的either语法扩展,就可以使用同样的merge方法:
import cats.syntax.either._ // 导入Either扩展方法

语义和标准库的merge完全一致,不需要修改核心逻辑。

优化后的完整可运行示例:

import cats.Functor
import cats.syntax.functor._

import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.duration.DurationInt
import scala.language.higherKinds

def foo[F[_]: Functor, T](eitherF: F[Either[T, T]]): F[T] =
  eitherF.map(_.merge)

val flattenProcess = foo[Future, String](Future(Left[String, String]("left")))
  .flatMap{ prev =>
      println(prev)
      foo[Future, String](Future(Right[String, String]("right")))
  }
println(Await.result(flattenProcess, 10.seconds))
// 输出: 
// left
// right

设计合理性判断

这种场景是否属于Either的不合理使用,取决于你的业务逻辑:

  • 如果你在生成Either[T, T]的上游逻辑中,确实需要区分左右分支做不同的处理,只是到当前阶段不需要再区分分支属性,那这种用法完全合理,属于正常的业务流程分支收敛。
  • 如果你上游逻辑也不需要区分左右分支,从一开始就能直接得到T类型的值,那确实属于过度使用Either,完全可以去掉不必要的Either包装,简化整个链路的类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:48:03