如何基于Cats库将Either列表转换为ValidatedNel?求实现方案
解决方法:用Cats的Traverse + ValidatedNel优雅实现
嘿,这个场景Cats早就帮咱们想好解决方案啦,完全不用手动写循环收集错误!咱们一步步理清楚怎么实现:
核心思路
咱们的目标拆解下来其实是这三步:
- 先确保输入的List不是空的(否则返回对应错误)
- 把每个
Either[String, T]转换成支持错误收集的ValidatedNel[String, T](ValidatedNel是Validated[NonEmptyList[String], T]的别名) - 遍历整个NonEmptyList,要么把所有Valid的T收集成NonEmptyList,要么把所有Invalid的错误合并成一个NonEmptyList
具体代码实现
首先得导入Cats的必要依赖和语法扩展:
import cats.data.{NonEmptyList, Validated, ValidatedNel} import cats.implicits._ // 自动导入所有必要的类型类实例和扩展方法
然后实现你的convert方法:
def convert[T](list: List[Either[String, T]]): Validated[NonEmptyList[String], NonEmptyList[T]] = { NonEmptyList.fromList(list) // 把Option转成ValidatedNel:空列表就返回Invalid(NonEmptyList("list is empty")) .toValidNel("list is empty") // 遍历NonEmptyList里的每个Either,转成ValidatedNel并收集结果 .flatMap(nel => nel.traverse(_.toValidatedNel)) }
代码逐行解释
NonEmptyList.fromList(list):把普通List转成Option[NonEmptyList[...]],空列表返回None,非空列表返回Some(NonEmptyList).toValidNel("list is empty"):Cats给Option提供的扩展方法,把None转成Invalid(NonEmptyList("list is empty")),Some(x)转成Valid(x),完美处理空列表的错误场景nel.traverse(_.toValidatedNel):_.toValidatedNel:把Either[String, T]转成ValidatedNel[String, T]——Left(err)变成Invalid(NonEmptyList(err)),Right(value)变成Valid(value)traverse是CatsTraverse类型类的核心方法,它会遍历NonEmptyList的每个元素,借助Validated的Applicative实例组合结果:- 若所有元素都是Valid,就把所有T打包成
NonEmptyList[T],返回Valid(NonEmptyList[T]) - 若存在Invalid元素,就把所有错误合并成
NonEmptyList[String],返回Invalid(NonEmptyList[String])
- 若所有元素都是Valid,就把所有T打包成
为什么不用手动实现?
Cats的Traverse类型类已经封装了“遍历容器并组合结果”的通用逻辑,而ValidatedNel的Applicative实例正好是错误收集式的(和Either的短路逻辑不同),完美匹配咱们需要收集所有错误的需求。手动实现不仅容易写出冗余代码,还不如现成工具简洁可靠。
内容的提问来源于stack exchange,提问作者Cheetah
相关产品推荐
相关产品推荐

