如何在Kotlin Arrow FX中使用其他效果组合IO函数
在处理请求之前,我们通常需要一些请求验证。使用arrow v 0.8,典型的消息处理程序如下所示:如何在Kotlin Arrow FX中使用其他效果组合IO函数,kotlin,functional-programming,arrow-kt,Kotlin,Functional Programming,Arrow Kt,在处理请求之前,我们通常需要一些请求验证。使用arrow v 0.8,典型的消息处理程序如下所示: fun addToShoppingCart(request: AddToShoppingCartRequest): IO<Either<ShoppingCardError, ItemAddedEvent>> = fx { request .pipe (::validateShoppingCard) .flatMap { validatedReques
fun addToShoppingCart(request: AddToShoppingCartRequest): IO<Either<ShoppingCardError, ItemAddedEvent>> = fx {
request
.pipe (::validateShoppingCard)
.flatMap { validatedRequest ->
queryShoppingCart().bind().map { validatedRequest to it } // fun queryShoppingCart(): IO<Either<DatabaseError, ShoppingCart>>
}
.flatMap { (validatedRequest, shoppingCart) ->
maybeAddToShoppingCart(shoppingCart, validatedRequest) // fun maybeAddToShoppingCart(...): Either<DomainError, ShoppingCart>
}
.flatMap { updatedShoppingCart ->
storeShoppingCart(updatedShoppingCart).bind() // fun storeShoppingCart(ShoppingCart): IO<Either<DatabaseError, Unit>>
.map {
computeItemAddedEvent(updatedShoppingCart)
}
}
.mapLeft(::computeShoppingCartError)
}
fun addToShoppingCart(请求:addToShoppingCart请求):IO=fx{
要求
.pipe(::validateShoppingCard)
.flatMap{validatedRequest->
queryShoppingCart().bind().map{validatedRequest to it}//fun queryShoppingCart():IO
}
.flatMap{(validatedRequest,shoppingCart)->
maybeAddToShoppingCart(shoppingCart,validatedRequest)//fun maybeAddToShoppingCart(…):或者
}
.flatMap{updatedShoppingCart->
storeShoppingCart(updatedShoppingCart).bind()//有趣的storeShoppingCart(ShoppingCart):IO
.地图{
computeItemAddedEvent(更新的购物车)
}
}
.mapLeft(::computeShoppingCartError)
}
这似乎是对工作流的一个方便而富有表现力的定义。我试图在arrow v 0.10.5中定义类似的函数:
fun handleDownloadRequest(strUrl: String): IO<Either<BadUrl, MyObject>> = IO.fx {
parseUrl(strUrl) // fun(String): Either<BadUrl,Url>
.map {
!effect{ downloadObject(it) } // suspended fun downloadObject(Url): MyObject
}
}
乐趣处理下载请求(strUrl:String):IO=IO.fx{
parseUrl(strUrl)//fun(String):或者
.地图{
!effect{downloadObject(it)}//挂起的乐趣下载对象(Url):MyObject
}
}
这会导致编译器错误“只能在协同程序体中调用挂起函数”。原因是的map
和flatMap
功能
和选项
都不是内联的
事实上,关于外汇的报道说
“很快,您就会发现无法在
为上述任一函数声明的函数,以及
其他粉丝的最爱,如map()和handleErrorWith()。为此
需要一个并发库!”
所以问题是为什么会这样?这种作文的惯用方式是什么?惯用方式是什么
fun handleDownloadRequest(strUrl: String): IO<Either<BadUrl, MyObject>> =
parseUrl(strUrl)
.fold({
IO.just(it.left()) // forward the error
}, {
IO { downloadObject(it) }
.attempt() // get an Either<Throwable, MyObject>
.map { it.mapLeft { /* Throwable to BadURL */ } } // fix the left side
})
乐趣处理下载请求(strUrl:String):IO=
解析URL(strUrl)
.折叠({
IO.just(it.left())//转发错误
}, {
IO{下载对象(it)}
.trument()//获取一个
.map{it.mapLeft{/*Throwable to BadURL*/}//修复左侧
})
就我个人而言,我不会使用这个函数深入IO的最深处,而是将其重写为一个挂起函数
suspend fun handleDownloadRequest(strUrl: String): Either<BadUrl, MyObject> =
parseUrl(strUrl)
.fold(::Left) { // forward the error
Either.catch({ /* Throwable to BadURL */ }) { downloadObject(it) }
}
suspend-fun-handleDownloadRequest(strUrl:String):或者=
解析URL(strUrl)
.fold(::Left){//转发错误
catch({/*Throwable to BadURL*/}){downloadObject(it)}
}
在0.8.X中,或
的函数过去是内联的。这样做的一个意外副作用是,您可以在任何地方调用挂起函数。虽然这很好,但它可能导致抛出异常(或跳转线程或死锁)