{"id":20394195,"url":"https://github.com/erwin-kok/result-monad","last_synced_at":"2026-05-26T23:31:19.319Z","repository":{"id":162872242,"uuid":"531153030","full_name":"erwin-kok/result-monad","owner":"erwin-kok","description":"Explicit success/failure modeling for Kotlin using a Result monad. Favors explicit control flow and predictable error handling over exceptions.","archived":false,"fork":false,"pushed_at":"2026-01-16T11:10:56.000Z","size":318,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T00:58:26.504Z","etag":null,"topics":["error-handling","explicit-control-flow","functional-programming","kotlin","monad","result-t"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erwin-kok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-08-31T15:49:43.000Z","updated_at":"2026-01-16T11:11:00.000Z","dependencies_parsed_at":"2024-11-15T03:52:14.038Z","dependency_job_id":"58c635fe-e85b-4e9e-a10d-db823b972998","html_url":"https://github.com/erwin-kok/result-monad","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/erwin-kok/result-monad","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fresult-monad","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fresult-monad/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fresult-monad/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fresult-monad/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erwin-kok","download_url":"https://codeload.github.com/erwin-kok/result-monad/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fresult-monad/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33543973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["error-handling","explicit-control-flow","functional-programming","kotlin","monad","result-t"],"created_at":"2024-11-15T03:52:10.964Z","updated_at":"2026-05-26T23:31:19.312Z","avatar_url":"https://github.com/erwin-kok.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Result Monad\n\n[![ci](https://github.com/erwin-kok/result-monad/actions/workflows/ci.yaml/badge.svg)](https://github.com/erwin-kok/result-monad/actions/workflows/ci.yaml)\n[![Maven Central](https://img.shields.io/maven-central/v/org.erwinkok.result/result-monad)](https://central.sonatype.com/artifact/org.erwinkok.result/result-monad)\n[![Kotlin](https://img.shields.io/badge/kotlin-2.3.0-blue.svg?logo=kotlin)](http://kotlinlang.org)\n[![License](https://img.shields.io/github/license/erwin-kok/result-monad.svg)](https://github.com/erwin-kok/result-monad/blob/master/LICENSE)\n\n## Introduction\n\nConsider the following function signature:\n\n```kotlin\nfun createItem(name: String): String {\n    ...\n} \n```\n\nWhile simple, this signature communicates only the success path. It provides no information about possible failure modes, nor whether failure is expressed via return values or exceptions.\n\nDocumenting error conditions in comments is brittle: comments drift, but types do not. For long-lived codebases, the type system should describe both success and failure.\n\nThis library provides a small, explicit Result type to model this directly.\n\n## Motivation\n\nException-based control flow is implicit and non-local. Once execution enters a `try` block, it becomes unclear which operation caused control to jump to a `catch` clause.\n\n```kotlin\ntry {\n    doSomething()\n    doSomethingElse()\n    finalizeTheThing()\n    doSomeCleanup()\n} catch (e: IllegalArgumentException) {\n    ...\n}\n```\n\nIn this example, it is impossible to determine:\n\n- Which call failed\n- Which resources were successfully acquired\n- Which cleanup steps are still required\n\nThis complicates reasoning about control flow and resource lifetime.\n\nAn explicit Result type keeps failure local and visible.\n\n## Result Monad\n\nIn its generic form, a result monad represents either:\n\n- Ok(value) on success\n- Err(error) on failure\n\nExample:\n\n```kotlin\nfun divideNumbers(a: Float, b: Float): Result\u003cFloat\u003e {\n    if (b == 0) {\n        return Err(\"Division by zero is not allowed\")\n    }\n    return Ok(a / b)\n}\n```\n\nThe caller is required to handle the result explicitly:\n\n```kotlin\nval result = divideNumber(n1, n2)\n    .getOrElse {\n        // Handle division by zero\n        log.error { \"Division by zero: ${it.message}\" }\n        return Err(it) // Return the error to its caller.\n    }\nlog.info { \"n1 divided by n2 is $result\" }\n```\n\nFailure is now part of the normal control flow, not an exceptional side-channel.\n\n## Chaining calls\n\nBecause Result distinguishes success and failure, operations can be composed safely.\n\nFunctions such as map apply transformations only when a value is present:\n\n```kotlin\nval result = divideNumber(n1, n2)\n    .map { it * 2 }\n```\n\nIf `divideNumbers` returns `Err`, the transformation is skipped and the error is propagated unchanged.\n\nThis enables linear, readable pipelines without nested conditionals or exception handling.\n\n## Installation\n\n```kotlin\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"org.erwinkok.result:result-monad:$latest\")\n}\n```\n\n## Design Choices\n\n### Fixed Error Type\n\nUnlike many `Result\u003cT, E\u003e` implementations, this library uses a **fixed error type**:\n\n```kotlin\nfun doSomething(): Result\u003cString\u003e\n```\n\nThis reduces verbosity and keeps APIs compact. Error is a lightweight wrapper around a message and is itself an Exception. It can be created from either a string or an existing exception:\n\n```kotlin\nreturn Err(\"Invalid argument\")\n\n\nreturn Err(IllegalArgumentException()())\n```\n\n### Trade-off\n\nUsing a fixed error type means the original exception type is not preserved. When error identity matters, a stable error instance can be used:\n\n```kotlin\nval illegalArgumentError = Error(\"Illegal argument\")\n```\n\n```kotlin\nval result = doSomething()\n    .getOrElse {\n        if (it === illegalArgumentError) {\n            // handle illegal argument\n        } else {\n            // handle other errors\n        }\n    }\n```\n\nThis design favors:\n\n- Explicit control flow\n- Simpler APIs\n- Reduced generic noise\n\nat the cost of typed error hierarchies.\n\n### Prior Art\n\nThe concept of a result type is well established in languages such as Go and Rust.\n\nIn Kotlin, this library is inspired by Michael Bull’s excellent [kotlin-result](https://github.com/michaelbull/kotlin-result/).\n\nThe primary difference is the use of a fixed error type, trading flexibility for simplicity and consistency.\n\n## License\n\nThis project is licensed under the BSD-3-Clause license, see [`LICENSE`](LICENSE) file for more details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferwin-kok%2Fresult-monad","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferwin-kok%2Fresult-monad","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferwin-kok%2Fresult-monad/lists"}