Skip to content

Instantly share code, notes, and snippets.

@gustavofranke
Created May 26, 2024 06:10
Show Gist options
  • Save gustavofranke/3062c5bf6a2f66c3aef4ce60e7f7624c to your computer and use it in GitHub Desktop.
Save gustavofranke/3062c5bf6a2f66c3aef4ce60e7f7624c to your computer and use it in GitHub Desktop.
kotlin typeclasses
object Fintech5 {
data class ValidationError(val message: String)
data class CreatePortfolio(val userId: String, val amount: Double)
data class ChangePortfolio(val userId: String, val stock: String, val quantity: Int)
interface Validator<T> {
fun T.check(): EitherNel<ValidationError, T>
}
val createPortfolioValidator = object : Validator<CreatePortfolio> {
override fun CreatePortfolio.check(): EitherNel<ValidationError, CreatePortfolio> =
EitherNel.zipOrAccumulate(
if (!Storage.users.contains(userId)) Either.Left(ValidationError("Error: user $userId does not exist"))
else Either.Right(this),
if (amount < 0) Either.Left(ValidationError("Error: amount is negative"))
else Either.Right(this)
) { a, _ -> a }
}
val changePortfolioValidator = object : Validator<ChangePortfolio> {
override fun ChangePortfolio.check(): EitherNel<ValidationError, ChangePortfolio> =
EitherNel.zipOrAccumulate(
if (!Storage.users.contains(userId)) Either.Left(ValidationError("Error: user $userId does not exist"))
else Either.Right(this),
if (!Storage.stocks.contains(stock)) Either.Left(ValidationError("Error: user $stock is invalid"))
else Either.Right(this)
) { a, _ -> a }
}
context(Validator<T>)
fun <T> process(event: T) = either {
val validated: T = event.check().bind()
println("Successfully processed the event: $validated")
}.onLeft { errors -> println("Found validation errors: ${errors.map { it.message }}") }
@JvmStatic
fun main(args: Array<String>) {
with(createPortfolioValidator) {
process(CreatePortfolio("asdf", -123.0))
process(CreatePortfolio("user-123", 123.0))
}
with(changePortfolioValidator) {
process(ChangePortfolio("asdf", "qwer", -12))
process(ChangePortfolio("user-444","TSLA", 12))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment