gpt4 book ai didi

kotlin - 如何使用Kotlin和Arrow执行程序

转载 作者:行者123 更新时间:2023-12-02 13:34:48 27 4
gpt4 key购买 nike

我正在尝试使用Kotlin和Arrow学习一些函数式编程,通过这种方式,我已经阅读了一些博客文章,例如:https://jorgecastillo.dev/kotlin-fp-1-monad-stack,很好,我已经理解了主要思想,但是在创建程序时,我不知道如何运行它。

让我更加明确:

我有以下代码:

typealias EitherIO<A, B> = EitherT<ForIO, A, B>

sealed class UserError(
val message: String,
val status: Int
) {
object AuthenticationError : UserError(HttpStatus.UNAUTHORIZED.reasonPhrase, HttpStatus.UNAUTHORIZED.value())
object UserNotFound : UserError(HttpStatus.NOT_FOUND.reasonPhrase, HttpStatus.NOT_FOUND.value())
object InternalServerError : UserError(HttpStatus.INTERNAL_SERVER_ERROR.reasonPhrase, HttpStatus.INTERNAL_SERVER_ERROR.value())
}


@Component
class UserAdapter(
private val myAccountClient: MyAccountClient
) {
@Lazy
@Inject
lateinit var subscriberRepository: SubscriberRepository

fun getDomainUser(ssoId: Long): EitherIO<UserError, User?> {
val io = IO.fx {
val userResource = getUserResourcesBySsoId(ssoId, myAccountClient).bind()
userResource.fold(
{ error -> Either.Left(error) },
{ success ->
Either.right(composeDomainUserWithSubscribers(success, getSubscribersForUserResource(success, subscriberRepository).bind()))
})
}
return EitherIO(io)
}

fun composeDomainUserWithSubscribers(userResource: UserResource, subscribers: Option<Subscribers>): User? {
return subscribers.map { userResource.toDomainUser(it) }.orNull()
}
}

private fun getSubscribersForUserResource(userResource: UserResource, subscriberRepository: SubscriberRepository): IO<Option<Subscribers>> {
return IO {
val msisdnList = userResource.getMsisdnList()
Option.invoke(subscriberRepository.findAllByMsisdnInAndDeletedIsFalse(msisdnList).associateBy(Subscriber::msisdn))
}
}

private fun getUserResourcesBySsoId(ssoId: Long, myAccountClient: MyAccountClient): IO<Either<UserError, UserResource>> {
return IO {
val response = myAccountClient.getUserBySsoId(ssoId)
if (response.isSuccessful) {
val userResource = JacksonUtils.fromJsonToObject(response.body()?.string()!!, UserResource::class.java)
Either.Right(userResource)
} else {
when (response.code()) {
401 -> Either.Left(UserError.AuthenticationError)
404 -> Either.Left(UserError.UserNotFound)
else -> Either.Left(UserError.InternalServerError)
}
}
}.handleError { Either.Left(UserError.InternalServerError) }
}

如您所见,它正在将一些结果累积到IO monad中。我应该从箭头使用 unsafeRunSync()运行该程序,但是在javadoc上声明如下: **NOTE** this function is intended for testing, it should never appear in your mainline production code!
我应该提到我对 unsafeRunAsync有所了解,但就我而言,我想保持同步。

谢谢!

最佳答案

而不是运行unsafeRunSync,您应该更喜欢unsafeRunAsync

如果您有myFun(): IO<A>并想要运行它,那么您可以在其中myFun().unsafeRunAsync(cb)调用cb: (Either<Throwable, A>) -> Unit

例如,如果您的函数返回IO<List<Int>>,则可以调用

myFun().unsafeRunAsync {  /* it (Either<Throwable, List<Int>>) -> */
it.fold(
{ Log.e("Foo", "Error! $it") },
{ println(it) })
}

这将异步运行IO中包含的程序,并将结果安全地传递给回调,如果IO抛出则将记录错误,否则将打印整数列表。

您应该出于多种原因而避免使用 unsafeRunSync,在 here中进行了讨论。它处于阻塞状态,可能导致崩溃,可能导致死锁,并且可能导致应用程序停止。

如果您确实想将IO作为阻塞计算运行,则可以在此之前加上 attempt(),以使 IO<A>成为类似于 IO<Either<Throwable, A>>回调参数的 unsafeRunAsync。至少那么您不会崩溃。

但是 unsafeRunAsync是首选。另外,请确保传递给 unsafeRunAsync的回调不会引发任何错误,因为它不会。 Docs

关于kotlin - 如何使用Kotlin和Arrow执行程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59026505/

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