gpt4 book ai didi

kotlin - 是否有任何理由使用 suspend fun fn(...) : Either 而不是 suspend fun fn(...) : A?

转载 作者:行者123 更新时间:2023-12-03 08:05:58 26 4
gpt4 key购买 nike

我正在考虑有关 suspend 的事情Arrow 的文档详细解释了:suspend () -> A提供与 IO<A> 相同的保证.

因此,根据文档,只需使用 suspend我们正在将不纯函数转换为纯函数:

不纯

fun log(message: String): Unit = println(message)

fun main(): Unit {
log("Hey!")
}

纯净

suspend fun log(message: String): Unit = println(message)

fun main(): Unit = runBlocking {
log("Hey!")
}

事实上,只需添加 suspend将函数变成纯函数令人惊讶,但clearly explained in the doc .

考虑到这一点,我的下一个疑问与可能导致错误 ( Throwable ) 或值 A 的业务服务建模有关。 .

到目前为止,我正在做这样的事情:

suspend fun log(message: String): Either<Throwable, Unit> = either { println(message) }
suspend fun add(sum1: Int, sum2: Int): Either<Throwable, Int> = either { sum1 + sum2 }

suspend fun main() {
val program = either<Throwable, Unit> {
val sum = add(1, 2).bind()
log("Result $sum").bind()
}
when(program) {
is Either.Left -> throw program.value
is Either.Right -> println("End")
}
}

但是,考虑到 suspend fun fn() : A是纯的,相当于 IO<A> ,我们可以将上面的程序重写为:

suspend fun add(sum1: Int, sum2: Int): Int = sum1 + sum2
suspend fun log(message: String): Unit = println(message)

fun main() = runBlocking {
try {
val sum = add(1, 2)
log("Result $sum")
} catch( ex: Throwable) {
throw ex
}
}

有什么理由选择suspend fun fn(...): Either<Throwable, A>过度暂停fun fn(...): A

最佳答案

如果您想与 Throwable 合作有 2 个选项,kotlin.Resultarrow.core.Either .

最大的区别是runCatching之间和Either.catch 。哪里runCatching将捕获所有异常,并且 Either.catch只会捕获non-fatal exceptions 。所以Either.catch会防止您意外吞咽kotlin.coroutines.CancellationException .

您应该将上面的代码更改为以下内容,因为 either { }没有捕获任何异常。

suspend fun log(message: String): Either<Throwable, Unit> =
Either.catch { println(message) }

suspend fun add(sum1: Int, sum2: Int): Either<Throwable, Int> =
Either.catch { sum1 + sum2 }

Is there any reason to prefer suspend fun fn(...): Either<Throwable, A> over suspend fun fn(...): A?

是的,使用 Result 的原因或Either返回类型中的内容将强制调用者解决错误。强制用户解决错误,即使在 IO<A> 内也是如此或suspendtry/catch 以来仍然有值(value)最后是可选的。

但是使用 Either跟踪整个业务领域的错误变得真正有意义。或者跨层但以类型化的方式解决它们。

例如:

data class User(...)
data class UserNotFound(val cause: Throwable?)

fun fetchUser(): Either<UserNotFound, User> = either {
val user = Either.catch { queryOrNull("SELECT ...") }
.mapLeft { UserNotFound(it) }
.bind()
ensureNotNull(user) { UserNotFound() }
}

关于kotlin - 是否有任何理由使用 suspend fun fn(...) : Either<Throwable, A> 而不是 suspend fun fn(...) : A?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72318777/

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