Created
July 27, 2023 14:57
-
-
Save bastman/8045d7e6b664526e58c8423bef19b50a to your computer and use it in GitHub Desktop.
railway-oriented-programming (kotlin, playgorund)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo | |
// based on ... | |
// https://www.reddit.com/r/Kotlin/comments/15b16px/little_example_of_railway_oriented_programming_in/ | |
// https://github.com/GabrielLasso/Kotlin-railway-example | |
fun main() { | |
val pipeline: (data: Either<Throwable, Person>) -> Either<Throwable, Response> = | |
(::validate `→` ::save `→` ::notify `→` ::buildResponse) | |
val validInput = Person("Gabriel", 26) | |
val validResponse: Either<Throwable, Response> = validInput | |
.let { Either.Right(it) } | |
.let(pipeline::invoke) | |
val invalidInput = Person("Invalid age", -3) | |
val invalidResponse: Either<Throwable, Response> = invalidInput | |
.let { Either.Right(it) } | |
.let(pipeline::invoke) | |
println("input: $validInput ==> response: $validResponse") | |
println("input: $invalidInput ==> response: $invalidResponse") | |
} | |
sealed class Either<out L, out R> { | |
data class Left<L>(val value: L) : Either<L, Nothing>() | |
data class Right<R>(val value: R) : Either<Nothing, R>() | |
} | |
typealias Arrow<A, B> = (A) -> B | |
infix fun <A, B, C> Arrow<A, B>.`→`(f: Arrow<B, C>): Arrow<A, C> { | |
return { | |
f(this(it)) | |
} | |
} | |
data class Person(val name: String, val age: Int) | |
data class Response(val body: String, val code: Int) | |
fun validate(data: Either<Throwable, Person>): Either<Throwable, Person> { | |
if (data is Either.Left) { | |
return data | |
} | |
data as Either.Right | |
if (data.value.age < 0) { | |
return Either.Left(Exception("Age must be non negative")) | |
} | |
return data | |
} | |
fun save(data: Either<Throwable, Person>): Either<Throwable, Person> { | |
if (data is Either.Left) { | |
return data | |
} | |
println("Saved $data") | |
return data | |
} | |
fun notify(data: Either<Throwable, Person>): Either<Throwable, Person> { | |
if (data is Either.Left) { | |
return data | |
} | |
println("Notified user $data") | |
return data | |
} | |
fun buildResponse(data: Either<Throwable, Person>): Either<Throwable, Response> { | |
if (data is Either.Left) { | |
return data | |
} | |
return Either.Right(Response("Ok: $data", 200)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment