Kotlin 使用箭头kt验证对象
我有一个对象(书),哪些字段应该通过事件更新(作者已更改)。假设书中的作者字段只有在作者结婚并改名后才会改变,但如果作者刚搬到一个新的城市,书中的作者字段不会改变 在这个简单的例子中,我可以检查Kotlin 使用箭头kt验证对象,kotlin,arrow-kt,Kotlin,Arrow Kt,我有一个对象(书),哪些字段应该通过事件更新(作者已更改)。假设书中的作者字段只有在作者结婚并改名后才会改变,但如果作者刚搬到一个新的城市,书中的作者字段不会改变 在这个简单的例子中,我可以检查book.authorName==event.author.name并返回或。但是我怎么能检查不止一个字段呢?如果我继续执行这两种方法中的任何一种,该过程将在它遇到的第一个NothingChangedFailure时停止,但我希望聚合所有更新,并且仅返回NothingChangedFailure,前提是书
book.authorName==event.author.name
并返回或。但是我怎么能检查不止一个字段呢?如果我继续执行这两种方法中的任何一种,该过程将在它遇到的第一个NothingChangedFailure
时停止,但我希望聚合所有更新,并且仅返回NothingChangedFailure
,前提是书中的任何字段都没有更改
我尝试了选项
,或者
,然后继续阅读验证
,但我发现,如果出现一次故障,它们似乎都会导致整个结果失败。那么有没有我看不到的选项呢?有一个例子显示了我们可以组合验证失败的情况
对于你的情况(我将在这里假设一些事情,比如书中可用的字段),我猜它看起来像:
data class Book(val title: String, val authorName: String, val pageCount: Int)
在这里,我们使用半群的定义创建错误:
sealed class BookValidationError {
data class PropertyNotChanged(val propertyName: String) : BookValidationError()
data class Multiple(val errors: Nel<BookValidationError>) : BookValidationError()
}
object BookValidationErrorSemigroup : Semigroup<BookValidationError> {
override fun BookValidationError.combine(b: BookValidationError): BookValidationError = when {
this is Multiple && b is Multiple -> Multiple(errors + b.errors)
this is Multiple && b !is Multiple -> Multiple(errors + b)
this !is Multiple && b is Multiple -> Multiple(this.nel() + b.errors)
else -> BookValidationError.Multiple(NonEmptyList(this, b))
}
}
我们将其与助手类结合在一起:
class BookValidation(
private val book: Book
) : ApplicativeError<ValidatedPartialOf<BookValidationError>, BookValidationError> by bookApplicativeError {
fun <T> fieldIsNot(name: String, actualValue: T, incorrectValue: T): Kind<ValidatedPartialOf<BookValidationError>, Book> =
if(actualValue == incorrectValue) raiseError(BookValidationError.PropertyNotChanged(name))
else just(book)
}
然后,如果您像这样执行它:
fun main() {
Book("a", "b", 123).validateThat(
titleIsNot = "c",
authorNameIsNot = "d",
pageCountIsNot = 124
).let(::println)
Book("a", "b", 123).validateThat(
titleIsNot = "a",
authorNameIsNot = "b",
pageCountIsNot = 123
).let(::println)
Book("a", "b", 123).validateThat(
titleIsNot = "c",
authorNameIsNot = "b",
pageCountIsNot = 124
).let(::println)
}
第一个将对以下输出有效:
Valid(a=Book(title=a, authorName=b, pageCount=123))
Invalid(e=PropertyNotChanged(propertyName=authorName))
但第二个将输出:
Invalid(e=Multiple(errors=NonEmptyList(all=[PropertyNotChanged(propertyName=pageCount), PropertyNotChanged(propertyName=title), PropertyNotChanged(propertyName=authorName)])))
在这个Invalid
实例中,我们有一个非空列表,其中包含验证失败的所有字段。如果我们重新格式化一点输出,我们可以看到它们:
Invalid(e=Multiple(
errors=NonEmptyList(all=[
PropertyNotChanged(propertyName=pageCount),
PropertyNotChanged(propertyName=title),
PropertyNotChanged(propertyName=authorName)
])
))
现在,对于第三种情况,由于其中只有一种保持不变,我们得到以下输出:
Valid(a=Book(title=a, authorName=b, pageCount=123))
Invalid(e=PropertyNotChanged(propertyName=authorName))
啊,我明白了!我会尽快试一试+谢谢你!这对于验证整本书非常有用,但我仍然无法确定某个属性是否已更改?我需要比较潜在变化的总和和错误的总和?如果错误少于潜在的更改,则说明该书已更改?正如本文所述,只有在所有值均未更改的情况下,此解决方案才会通过。也可以通过一些修改为每个字段创建多个错误,这样您就可以搜索特定故障的结果。它有可能通过反射来推广。我将对其进行更新以简化结果。用更多细节更新了示例。