博客
关于我
Scalaz(20)-Monad: Validation-Applicative版本的Either
阅读量:463 次
发布时间:2019-03-06

本文共 3567 字,大约阅读时间需要 11 分钟。

Scalaz中的Validation:深入理解其功能与应用

Scalaz中的Validation是一个强大的功能,用于处理数据验证和错误处理。它在很多方面与 Scala的标准库/(即Either)有相似之处,但又有显著的区别。Validation不仅提供了基本的验证功能,还通过其Applicative特性,允许同时处理多个Validation,并返回多个异常信息。以下将深入探讨Validation的核心功能、与/的区别以及其实际应用场景。

Validation的核心概念

Validation在Scalaz中定义为:

sealed abstract class Validation[+E, +A] extends Product with Serializable {  // 其他定义已省略...  def isSuccess: Boolean = this match {    case Success(_) => true    case Failure(_) => false  }  // 其他方法已省略...}

Validation有两个状态:Success和Failure。Success表示验证成功,返回一个值;Failure表示验证失败,返回一个异常信息。与/(Either)相比,Validation的主要特点在于它支持多个异常信息的返回。

Validation与/的区别

虽然Validation和/在某些方面非常相似,但它们在处理多个异常信息时有显著差异。与/不同之处在于,Validation通过其Applicative特性,可以在同一个操作中处理多个Validation,并返回多个异常信息。

操作符API

Validation提供了丰富的操作符API,包括:

  • orElse:如果当前Validation是成功,则返回当前Validation;如果失败,则返回另一个Validation。
  • swap:交换Validation的状态,即将Success转换为Failure,反之亦然。
  • ap:应用函数在当前Validation的成功路径上,同时处理可能的错误。

这些操作符使得Validation在处理复杂的验证逻辑时非常灵活。

Validation的状态定义

Validation的两个状态定义如下:

final case class Success[A](a: A) extends Validation[Nothing, A]final case class Failure[E](e: E) extends Validation[E, Nothing]
  • Success表示验证成功,携带一个值。
  • Failure表示验证失败,携带一个异常值。

这些状态定义使得Validation能够方便地处理成功和失败两种情况。

Validation的Monad特性

Validation是一个Monad,它支持在for-comprehension中实现 Failure立即退出的功能。例如:

for {  a <- Success(3)  b <- Success(2)} yield a + b

上述代码返回一个Success(5)的Validation。

如果其中任何一个步骤返回Failure,则整个Validation也会返回Failure。

注入方法

Scalaz为Validation提供了丰富的注入方法,例如:

  • success:创建一个成功的Validation。
  • failure:创建一个失败的Validation。
  • successNel:创建一个携带NonEmptyList的成功Validation。
  • failureNel:创建一个携带NonEmptyList的失败Validation。

这些方法使得开发者能够更方便地构建Validation实例。

例子:同时处理多个Validation

假设我们需要同时验证几个值,并返回所有异常信息,可以使用Validation的组合操作符|@|

((3.success : Validation[String, Int]) |@| ("oh, error1! ".failure : Validation[String, Int]) |@| (2.success : Validation[String, Int]) |@| ("oh, error2 again!".failure : Validation[String, Int])) {_ + _ + _ + _}

上述代码将返回一个Failure,携带所有异常信息。例如:

Failure("oh, error1! oh, error2 again!")

如果需要将异常信息存储在NonEmptyList中,可以使用failureNel方法:

((3.successNel : ValidationNel[String, Int]) |@| ("oh, error1! ".failureNel : ValidationNel[String, Int]) |@| (2.successNel : ValidationNel[String, Int]) |@| ("oh, error2 again!".failureNel : ValidationNel[String, Int])) {_ + _ + _ + _}

上述代码将返回一个Failure,携带所有异常信息:

Failure(NonEmptyList("oh, error1!", "oh, error2 again!"))

NonEmptyList的使用

NonEmptyList是Scalaz中用于表示不为空列表的数据结构。它可以与Validation结合使用,方便地将异常信息存储和处理。

例如:

val nel = 2 :@: 4 :@: 3.wrapNel

上述代码将返回一个NonEmptyList,包含元素2、4和3。

如果需要将其转换为标准的List,可以使用list方法:

nel.list

这将返回一个标准的List[2, 4, 3]。

Validation的flatMap方法

尽管Validation支持flatMap方法,但它已经被弃用。用户被鼓励使用Scalaz的标准库/或直接使用Validation的其他方法。例如,可以使用ap方法来处理多个Validation。

deprecated警告

@deprecated("flatMap does not accumulate errors, use `scalaz.\/` or `import scalaz.Validation.FlatMap._` instead", "7.1")@inline implicit def ValidationFlatMapDeprecated[E, A](d: Validation[E, A]): ValidationFlatMap[E, A] = new ValidationFlatMap(d)

用户被建议使用Scalaz的标准库/来处理错误积累问题。

Validation的Applicative特性

Validation实现了Applicative功能,通过ap方法可以在成功路径上应用函数,并处理失败路径上的异常。例如:

def ap[EE: Semigroup[EE], B](x: => Validation[EE, A => B])(implicit E: Semigroup[EE]): Validation[EE, B] = (this, x) match {  case (Success(a), Success(f)) => Success(f(a))  case (e @ Failure(_), Success(_)) => e  case (Success(_), e @ Failure(_)) => e  case (Failure(e1), Failure(e2)) => Failure(E.append(e2, e1))}

上述方法允许开发者在Validation的成功路径上应用函数,并将多个异常信息合并到一个Failure中。

总结

Validation是Scalaz中处理数据验证和错误处理的强大工具。它通过其Applicative特性,支持同时处理多个Validation,并返回多个异常信息。与/相比,Validation的主要优势在于其更灵活的错误处理能力。通过合理使用Validation及其注入方法,开发者可以构建更高效、更健壮的错误处理逻辑。

转载地址:http://wfefz.baihongyu.com/

你可能感兴趣的文章
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
mysql replace用法
查看>>
Mysql Row_Format 参数讲解
查看>>
mysql select, from ,join ,on ,where groupby,having ,order by limit的执行顺序和书写顺序
查看>>
MySQL Server 5.5安装记录
查看>>
mysql server has gone away
查看>>
mysql slave 停了_slave 停止。求解决方法
查看>>
MySQL SQL 优化指南:主键、ORDER BY、GROUP BY 和 UPDATE 优化详解
查看>>
MYSQL sql语句针对数据记录时间范围查询的效率对比
查看>>
mysql sum 没返回,如果没有找到任何值,我如何在MySQL中获得SUM函数以返回'0'?
查看>>
mysql Timestamp时间隔了8小时
查看>>
Mysql tinyint(1)与tinyint(4)的区别
查看>>
mysql union orderby 无效
查看>>
mysql v$session_Oracle 进程查看v$session
查看>>
mysql where中如何判断不为空
查看>>
MySQL Workbench 使用手册:从入门到精通
查看>>
mysql workbench6.3.5_MySQL Workbench
查看>>
MySQL Workbench安装教程以及菜单汉化
查看>>
MySQL Xtrabackup 安装、备份、恢复
查看>>
mysql [Err] 1436 - Thread stack overrun: 129464 bytes used of a 286720 byte stack, and 160000 bytes
查看>>