스칼라 무료 확인

[정보 자세히 알아 스칼라 자유의 구현 모나드의 검증을.

때문에 비즈니스 데이터의 복잡성, 우리는 데이터 유효성 검사에 많은 에너지를 소비했다. 에서는 스칼라 ,이 프로그램을 사용하여 인증하는 방법을 제안하고, 널리 효과적인 방법으로 간주된다. 응용 프로그램 인증 및 무료함으로써 모나드 영감 아이디어, 본 논문에서, 우리는 소개 모나드 검증 프레임 워크가 "무료"건물의 검증을. 더 나아가서 우리는이 방법을 논의하고 샘플 코드로 구현하는 방법을 보여줍니다. 그런 것들의 정교한 구조를 탈피 - 우수한 날카로운 교훈을


에서 스칼라 검증

에러가 검출 될 때, 검증은 다양한 형태로 발견 될 수있다. 첫 번째 오류가 발생 (또는 예외) 때, 검증은 즉시 반환 할 수 있습니다, 검증 결과 또는 유효성 검사 오류 또는 예외 메시지를 포함하거나 포함하지 않을 수있다. 확인에 실패 할 때 모든 비즈니스 규칙과는 제로 또는 메시지로 돌아가 상기 인증이 확인되지 않으며, 첫 번째 오류는 과정을 단축, 빠른라고합니다. 오류가 더 축적이 완료 검증 할 수 없습니다되지 않습니다 있기 때문에 인증이 간단한 형태는 때때로 부적절한 것으로 간주됩니다. 사실, 널리 응용 프로그램 개발에 사용된다. 스칼라 에서 단항의 엔티티 (예를 들어 옵션 - , 은 try 중 하나 ) 사용이 매우 편리합니다.


모든 비즈니스 규칙 및 오류와 실패의 검증 급속한 축적이 매우 다르다는 것을 확인합니다. 효과적으로 축적 문제를 해결 애플리케이션 펑을 제안 하였다. 인기있는 스칼라 같은 라이브러리, scalaz 고양이 , 애플리케이션 검증 지원을 제공합니다. 독자는 참조 할 수 있습니다 scalaz.Validation의 API cats.data.Validated의 API 자세한 내용은.


그러나 여러 가지 이유로, 함께 스칼라 많은 프로젝트가 작성된 이러한 라이브러리 중 하나 사용하지 않고, 스칼라 언어는 이해의 응용 프로그램에 대한 네이티브 지원하지 않습니다. 따라서, 하나는 로컬 인증 방법은 매우 매력적입니다 타사 라이브러리에 의존하지 않습니다.

검증 문제와 무료 모나드의 문제는 매우 유사 해결 될 수있다 - 검증 모델링 워크 플로우의 일련의 이해와 인터프리터를 구현하기 위해. 무료 모나드는 프로그램이 암시 적으로 승진 할 수 있는지 확인 할 수있는 강력한 방법을 제공합니다 모나드 (무료)에 있습니다. 따라서, 우리는 오류 또는 예외의 경우에 계속 모델로 재 문제가 우리의 인터프리터입니다 해결해야합니다. 인터프리터는 발리의 각각의 이행을 확인하고 모든 메시지가 호출 스테이션에 반환해야 확인할 수 있어야한다.


검사기 무료 모나드

우리의 방법에있어서, 조합 목록 검증은 검증 부에 의해 수행되며, 검증 비즈니스 규칙 검증 각각의 각 담당자가, 조성물로 이해했다. 이것은 무료 모나드 캔 도움 장소 - 확인 암시 "무료"로 승격 될 수 모나드 . 그것은 우리의 검증이 무료로 즐길 수 있습니다 모나드 무료 스택과 자연의 전환 - 제공 할 수있는 모든 혜택을.


첫째, 우리는 검증 프레임 워크와 신속한 장애의 한계를 논의한다.


우리는 사람의 이름과 나이를 확인하고 데이터베이스에 사람을 저장해야합니다 가정 :

경우 클래스 사람 (이름 : 문자열, 연령 : INT) {
  데프 validateName는 = 만약 다른 (name.isEmpty) 없음 일부 ( "성공")
  데프 validateAge이 = 경우 (나이 <18) 다른 없음 일부 ( "성공")
}
부울 = {: DEF (: 사람 사람) 저장
  에 println (들 "나이 $에서 $ {person.name} 저장 {인 person.age}")
  참된
}
발 사람이 사람을 = ( "마이클", 20)
에 대한 {
  _ <- person.validateName
  _ <- person.validateAge
저장} 수율 (사람)


 

위의 두 가지 코딩 제한 :

1. 이 오류가 더 리턴 발생하지 않을 때 확인합니다 유효성 검사 오류는 사이트를 호출 촬영되지 않습니다

2. 아무 것도 중지됩니다 확인하십시오. 위의 코드는 병합 이해하기 flatMap의 체인, 다음 지도 :

person.validateName
.flatMap((_: String) =>person.validateAge.map((_: String) => save(person)))


 

如果名称为空,validateName返回None,该过程将短暂停止,并且validateAge将不会执行——这是快速失败的验证。


在我们的方法中,我们对验证器进行建模以使其符合简单特征:

sealed trait Validator[A] {
  def validate: Option[Error]
  def unbox: A
}


 

每个验证器都实现自己的验证规则:

case class NameValidator(name: String) extends Validator[String] {
  def validate = if (name.isEmpty) Option(NameError) else None
  def unbox: String = name
}
case class AgeValidator(age: Int) extends Validator[Int] {
  def validate = if (age >= 18) None else Some(AgeError)
  def unbox: Int = age
}



请注意此实现中的以下内容:

  • 验证器是要验证的数据及其验证规则的容器。提供了“取消装箱”功能,以允许从验证器获取数据,这在稍后将讨论的实现中很重要;

  • 我们的验证器不会在错误时返回None,而在错误时返回Some [Error],而没有错误则返回None。这使我们能够将错误消息传送回呼叫站点。
            

验证程序隐式提升为monad,就像在自由monad中一样:

implicit def liftF[F[_], A](fa: F[A]): Free[F, A] = FlatMap(fa, Return.apply)


 

免费的monad是以下形式的标准:

sealed trait Free[F[_], A] {
    def flatMap[B](f: A => Free[F, B]): Free[F, B] = this match {
      case Return(a) => f(a)
      case FlatMap(sub, cont) => FlatMap(sub, cont andThen (_ flatMap f))
    }
    def map[B](f: A => B): Free[F, B] = flatMap(a => Return(f(a)))
}
final case class Return[F[_], A](a: A) extends Free[F, A]
case class FlatMap[F[_], I, A](sub: F[I], cont: I => Free[F, A]) extends Free[F, A]


 

解释器相应地执行验证器:

val interpreter = new Executor[Validator] {
  override def exec[A](fa: Validator[A]) = fa.validate
  override def unbox[A](fa: Validator[A]) = fa.unbox
}
def validate[F[_], A](prg: Free[F, A], interpreter: Executor[F]): List[Error] = {
  def go(errorList: List[Option[Error]], prg: Free[F, A]): List[Option[Error]]=
prg match {
       case Return(a) => errorList
       case FlatMap(sub, cont) => go(interpreter.exec(sub) :: errorList,
cont(interpreter.unbox(sub)))
  }
  go(List.empty[Option[Error]], prg).flatten
}


 

解释器是数据,错误,数据验证器和自由单子之间的粘合剂。请注意,此解释器与免费monad中的解释器之间的三个重要的详细区别是:

  • 解释器提供拆箱功能;它用于“no-error”情况。返回None类型时,unbox用于以类型安全的方式查找正在验证的数据。为了继续验证过程,反装箱又使用验证器提供的拆箱功能来获取正在验证的数据。

  • 与免费monad中的解释器不同,该过程的继续是通过monadic操作完成的,可能会缩短为None

executor.exec(sub).flatMap(x => validateAndRun(cont(x), executor))


 

在我们的验证解释器中,通过遵循验证器直到执行最后一个验证器来保证过程的继续,因为顺序执行是从flatMap中取出的,但是仍然保持了尾递归位置,因此验证过程是堆栈——自由。

  • 返回一个列表,其中包含来自每个验证器的验证错误消息(如果存在)。


验证组成

正如工作流是在免费monad中建模一样,验证流程也是通过理解建模的。例如,如果名称验证和年龄验证全部通过,我们将调用save(person)。否则,我们将打印出累积的错误:

val validation = for {
  _ <- NameValidator(person.name)
  _ <- AgeValidator(person.age)
} yield ()
validate(validation, interpreter) match {
  case Nil => save(person)
  case errors => errors foreach println
}


 

可以在免费验证中找到该实现。


结论

免费的monad是一种允许你从任何Functor构建monad的构造。 像其他单子一样,它是表示和操纵计算的一种纯方法。

特别是免费的monad提供了一种实用的方法:

  • 将状态计算表示为数据,然后运行它们

  • 以堆栈安全的方式运行递归计算

  • 构建嵌入式DSL(特定于域的语言)

  • 使用自然转换将计算重新定位到另一个解释器

(以上是项目类型的重点)

根据Leif Battermann的说法:

 “应用程序使我们能够编写独立的操作并评估每个操作。即使中间评估失败。这也使我们能够收集错误消息,而不仅仅是返回发生的第一个错误。”

在本文中,我们介绍了一种为你提供两全其美的方法——一种验证框架,它是不带应用程序的免费monad。希望能对你有帮助!有想法的话欢迎评论!

 


추천

출처blog.51cto.com/14631216/2458898