gpt4 book ai didi

kotlin - 为什么使用 Arrow 的 Options 而不是 Kotlin 可为空的

转载 作者:IT老高 更新时间:2023-10-28 13:41:15 34 4
gpt4 key购买 nike

我正在查看找到的箭头库 here .为什么要使用 Option 类型而不是 Kotlin 的内置 nullables?

最佳答案

我已经使用 Arrow 提供的 Option 数据类型一年多了,一开始,我们对自己做了完全相同的问题。答案如下。

Option vs Nullable

如果您仅将 option 数据类型与 Kotlin 中的 nullables 进行比较,它们几乎是偶数。相同的语义(有或没有一些值),几乎相同的语法(选项使用 map,可空值​​使用 safe call operator)。

但是当使用 Options 时,您可以从箭头生态系统中获益!

箭头生态系统(功能生态系统)

当使用 Options 时,您使用的是 Monad 模式。将 monad 模式与 arrow 等库一起使用时, scala cats , scalaz ,您可以从几个功能概念中受益。仅 3 个好处示例(还有很多):

1。访问其他 Monads

Option 不是唯一的!例如,Either 对于表达避免抛出异常非常有用。 TryValidatedIO 是其他常见 monad 的示例,它们可以帮助我们(以更好的方式)我们在典型项目中所做的事情。

2。 monads + 抽象之间的转换

您可以轻松地将一个 monad 转换为另一个。您有一个 Try 但想返回(并表达)一个 Either?只需转换为它。您有一个 Either 但不关心错误?只需转换为 Option

val foo = Try { 2 / 0 }
val bar = foo.toEither()
val baz = bar.toOption()

这种抽象还可以帮助您创建不关心容器(monad)本身的函数,只关心内容。例如,您可以创建与 ANY MONAD 一起使用的扩展方法 Sum(anyContainerWithBigDecimalInside, anotherContainerWithBigDecimal)(更准确地说:“适用于任何 applicative 实例” )这样:

fun <F> Applicative<F>.sum(vararg kinds: Kind<F, BigDecimal>): Kind<F, BigDecimal> {
return kinds.reduce { kindA, kindB ->
map(kindA, kindB) { (a, b) -> a.add(b) }
}
}

理解起来有点复杂,但非常有用且易于使用。

3。 Monad 推导式

从 nullables 到 monads 不仅仅是将安全调用运算符更改为 map 调用。看看箭头作为“Monad Comprehensions”模式的实现提供的“绑定(bind)”功能:

fun calculateRocketBoost(rocketStatus: RocketStatus): Option<Double> {
return binding {
val (gravity) = rocketStatus.gravity
val (currentSpeed) = rocketStatus.currentSpeed
val (fuel) = rocketStatus.fuel
val (science) = calculateRocketScienceStuff(rocketStatus)
val fuelConsumptionRate = Math.pow(gravity, fuel)
val universeStuff = Math.log(fuelConsumptionRate * science)

universeStuff * currentSpeed
}
}

上例中使用的所有函数以及 rocketStatus 参数的属性都是 Options。在 binding block 中,flatMap 调用是为我们抽象的。该代码更易于阅读(和编写),您无需检查值是否存在,如果其中一些不存在,则计算将停止,结果将是带有 None< 的选项!

现在试着想象这段代码用空验证代替。不仅仅是安全调用操作符,还可能是if null then return 代码路径。不是更难吗?

另外,上面的例子使用了 Option,但是作为抽象的 monad 理解的真正威力是当你将它与像 IO 这样的 monad 一起使用时。您可以在其中以与上述完全相同的“干净、顺序和命令式”的方式抽象异步代码执行:O

结论

我强烈建议您在看到概念符合您需要的语义时立即开始使用诸如 OptionEither 等 monad,即使您不确定如果您将从功能生态系统中获得其他巨大好处,或者您还不太了解它们。很快你就会在没有注意到学习曲线的情况下使用它。在我的公司,我们几乎在所有 Kotlin 项目中都使用它,甚至在面向对象的项目中(占大多数)。

关于kotlin - 为什么使用 Arrow 的 Options 而不是 Kotlin 可为空的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48895103/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com