kotlin result

JAVA源码 2025-08-20

kotlin-result

用于建模成功或故障操作的乘以结果单元。

安装

repositories {
    mavenCentral()
}

dependencies {
    implementation( " com.michael-bull.kotlin-result:kotlin-result:2.0.1 " )
}

介绍

在功能编程中, Result类型是具有返回值或错误的单声道类型。

要指示成功的操作,请返回具有成功valueOk(value) 。如果失败,请返回带有导致故障的errorErr(error)

这有助于定义一条清晰/不愉快的执行道路,该执行方式通常称为面向铁路的编程,从而将快乐和不愉快的道路表示为单独的铁路。

开销

Result类型被建模为内联值类。这可以在快乐的道路上实现零对象分配。

台式设计文档中提供了带有示例输出Java代码的完整故障。

乘法支持

kotlin-result针对Kotlin/本地目标支持概述的所有三个层

阅读更多

以下是该库主题撰写的视频和文章的集合。如果您想包括您的,请随时在Github上打开拉动请求。

  • [en]结果monad-亚当·贝内特(Adam Bennett)
  • [en]一种功能性处理方法 - 特里斯坦·汉密尔顿(Tristan Hamilton)
  • [en] Kotlin:功能性金矿-Mark Bucciarelli
  • [EN]面向铁路的编程-Scott Wlaschin
  • [JP] Kotlinで结果型使うならkotlin-resultを使おう
  • [JP] Kotlinのコードに返回结果を组み込む

Wiki上可以使用映射,以帮助使用其他语言的Result类型的经验来帮助那些:

  • 榆树
  • 哈斯克尔
  • Scala

入门

以下是一个简单的示例,说明如何使用Result类型来建模可能失败的函数。

 fun checkPrivileges ( user : User , command : Command ): Result < Command , CommandError > {
    return if (user.rank >= command.minimumRank) {
        Ok (command)
    } else {
        Err ( CommandError . InsufficientRank (command.name))
    }
}

当可能会引发异常的控件外的代码交互时,请用runCatching包裹呼叫以捕获其执行Result

 val result : Result < Customer , Throwable > = runCatching {
    customerDb.findById(id = 50 ) // could throw SQLException or similar
}

可以使用toResultOr扩展功能将可无效的类型(例如下面示例中的find方法)转换为Result

 val result : Result < Customer , String > = customers
    .find { it.id == id } // returns Customer?
    .toResultOr { " No customer found " }

转换结果

成功和故障结果都可以在铁路轨道的阶段进行转换。下面的示例演示了如何将内部程序错误转换为裸露的客户端错误IncorrectPassword UnlockError

.mapError { IncorrectPassword } // transform UnlockError into IncorrectPassword">
 val result : Result < Treasure , UnlockResponse > =
    unlockVault( " my-password " ) // returns Result
    .mapError { IncorrectPassword } // transform UnlockError into IncorrectPassword

链接

可以链接结果以产生执行的“快乐之路”。例如,用户输入命令进入管理控制台的快乐路径将包含:命令已被标记,注册命令,用户具有足够的特权以及执行相关操作的命令。下面的示例使用了我们之前定义的checkPrivileges函数。

printToConsole("failed to execute, reason: ${error.reason}") } )">
tokenize(command.toLowerCase())
    .andThen(::findCommand)
    .andThen { cmd -> checkPrivileges(loggedInUser, cmd) }
    .andThen { execute(user = loggedInUser, command = cmd, timestamp = LocalDateTime .now()) }
    .mapBoth(
        { output -> printToConsole( " returned: $output " ) },
        { error  -> printToConsole( " failed to execute, reason: ${error.reason} " ) }
    )

绑定(单调理解)

binding函数允许多个调用,每个调用每个返回Result都必须束缚。当在binding块内部时,可以在任何Result上访问bind()函数。每个bind的呼叫都将尝试解开Result并存储其值,如果Result是错误的,请尽早返回。

在下面的示例中, functionX()返回错误,然后执行将跳过functionY()functionZ() ,而是将来自functionX的错误存储在命名sum的变量中。

 fun functionX (): Result < Int , SumError > { .. . }
fun functionY (): Result < Int , SumError > { .. . }
fun functionZ (): Result < Int , SumError > { .. . }

val sum : Result < Int , SumError > = binding {
    val x = functionX().bind()
    val y = functionY().bind()
    val z = functionZ().bind()
    x + y + z
}

println ( " The sum is $sum " ) // prints "The sum is Ok(100)"

binding函数主要从BOW的binding功能中汲取灵感,但是下面是关于MONAD综合主题的其他资源列表。

  • 单元综合 - 箭头(kotlin)
  • 单调综合 - 弓(Swift)
  • 用于综合-Scala

Coroutine结合支持

coroutineBinding块中使用暂停功能需要额外的依赖性:

dependencies {
    implementation( " com.michael-bull.kotlin-result:kotlin-result:2.0.1 " )
    implementation( " com.michael-bull.kotlin-result:kotlin-result-coroutines:2.0.1 " )
}

coroutineBinding功能在coroutineScope内部运行,从而有助于同时进行工作分解

当块内部的任何调用bind()失败时,范围会失败,取消所有其他孩子。

下面的示例展示了一个计算昂贵的功能,该功能需要五毫秒才能计算一旦较小的功能失败,只需一毫秒即可消失:

 suspend fun failsIn5ms (): Result < Int , DomainErrorA > { .. . }
suspend fun failsIn1ms (): Result < Int , DomainErrorB > { .. . }

runBlocking {
    val result : Result < Int , BindingError > = coroutineBinding { // this creates a new CoroutineScope
        val x = async { failsIn5ms().bind() }
        val y = async { failsIn1ms().bind() }
        x.await() + y.await()
    }

    // result will be Err(DomainErrorB)
}

灵感

该图书馆的灵感来自其他语言,其中单调存在,其中包括:

  • 榆树
  • 哈斯克尔
  • Scala

诸如stdlib的现有解决方案的改进包括:

  • 降低了运行时开销,在快乐路径上分配零对象分配
  • 功能奇偶校验与其他语言的结果类型,包括Elm,Haskell和Rust
  • value / error无效性的LAX限制
  • error类型的继承的LAX约束(不从Exception继承)
  • 最高级别OkErr功能避免了与Result.Ok / Result.Err合格用法。
  • 高阶函数标记为减少运行时开销的inline关键词
  • 扩展功能在IterableList上用于折叠,组合,分区
  • 与其他语言的现有结果库保持一致(例如mapmapErrormapBothmapEither andandThenororElseunwrap
  • 涵盖每个图书馆方法的近100个单位测试的广泛测试套件

例子

该示例模块包含Scott示例应用程序的实现,该应用程序在现实世界中演示了Result的用法。

它在带有A /customers端点的端口9000上托管KTOR服务器。端点响应带有提供的idGETPOST请求,例如/customers/100 。将42的客户ID升级为硬编码,以抛出SQLException ,以说明Result类型如何将内部程序错误映射到更合适的面向用户的错误。

贡献

欢迎在GitHub上进行错误报告和拉动请求。

执照

该项目可根据ISC许可条款获得。有关版权信息和许可条款,请参见LICENSE文件。

下载源码

通过命令行克隆项目:

git clone https://github.com/michaelbull/kotlin-result.git