Minor: move ErrorOr into the core module and tweak its API a bit. Add a Path div operator.

This commit is contained in:
Mike Hearn 2016-09-08 13:08:45 +02:00
parent d8d639f192
commit 34ee44b532
3 changed files with 56 additions and 50 deletions

View File

@ -1,40 +0,0 @@
package com.r3corda.client.mock
class ErrorOr<out A> private constructor(
val value: A?,
val error: Exception?
) {
constructor(value: A): this(value, null)
constructor(error: Exception): this(null, error)
fun <T> match(onValue: (A) -> T, onError: (Exception) -> T): T {
if (value != null) {
return onValue(value)
} else {
return onError(error!!)
}
}
fun getValueOrThrow(): A {
if (value != null) {
return value
} else {
throw error!!
}
}
// Functor
fun <B> map(function: (A) -> B): ErrorOr<B> {
return ErrorOr(value?.let(function), error)
}
// Applicative
fun <B, C> combine(other: ErrorOr<B>, function: (A, B) -> C): ErrorOr<C> {
return ErrorOr(value?.let { a -> other.value?.let { b -> function(a, b) } }, error ?: other.error)
}
// Monad
fun <B> bind(function: (A) -> ErrorOr<B>): ErrorOr<B> {
return value?.let(function) ?: ErrorOr<B>(error!!)
}
}

View File

@ -1,5 +1,7 @@
package com.r3corda.client.mock
import com.r3corda.client.mock.Generator.Companion.choice
import com.r3corda.core.ErrorOr
import java.util.*
/**
@ -54,7 +56,7 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) {
companion object {
fun <A> pure(value: A) = Generator { ErrorOr(value) }
fun <A> impure(valueClosure: () -> A) = Generator { ErrorOr(valueClosure()) }
fun <A> fail(error: Exception) = Generator<A> { ErrorOr(error) }
fun <A> fail(error: Exception) = Generator<A> { ErrorOr.of(error) }
// Alternative
fun <A> choice(generators: List<Generator<A>>) = intRange(0, generators.size - 1).bind { generators[it] }
@ -85,10 +87,11 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) {
val result = mutableListOf<A>()
for (generator in generators) {
val element = generator.generate(it)
if (element.value != null) {
result.add(element.value)
val v = element.value
if (v != null) {
result.add(v)
} else {
return@Generator ErrorOr(element.error!!)
return@Generator ErrorOr.of(element.error!!)
}
}
ErrorOr(result)
@ -99,11 +102,12 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) {
fun <A> Generator.Companion.oneOf(list: List<A>) = intRange(0, list.size - 1).map { list[it] }
fun <A> Generator<A>.generateOrFail(random: Random, numberOfTries: Int = 1): A {
var error: Exception? = null
var error: Throwable? = null
for (i in 0 .. numberOfTries - 1) {
val result = generate(random)
if (result.value != null) {
return result.value
val v = result.value
if (v != null) {
return v
} else {
error = result.error
}
@ -146,8 +150,9 @@ fun <A> Generator.Companion.replicatePoisson(meanSize: Double, generator: Genera
ErrorOr(Unit)
}
}
if (errorOr.error != null) {
return@Generator ErrorOr(errorOr.error)
val e = errorOr.error
if (e != null) {
return@Generator ErrorOr.of(e)
}
}
ErrorOr(result)

View File

@ -218,4 +218,45 @@ fun extractZipFile(zipPath: Path, toPath: Path) {
// TODO: Generic csv printing utility for clases.
val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
/** Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform separator problems. */
operator fun Path.div(other: String): Path = resolve(other)
/** Representation of an operation that may have thrown an error. */
data class ErrorOr<out A> private constructor(val value: A?, val error: Throwable?) {
constructor(value: A) : this(value, null)
companion object {
/** Runs the given lambda and wraps the result. */
inline fun <T> catch(body: () -> T): ErrorOr<T> = try { ErrorOr(body()) } catch (t: Throwable) { ErrorOr.of(t) }
fun of(t: Throwable) = ErrorOr(null, t)
}
fun <T> match(onValue: (A) -> T, onError: (Throwable) -> T): T {
if (value != null) {
return onValue(value)
} else {
return onError(error!!)
}
}
fun getOrThrow(): A {
if (value != null) {
return value
} else {
throw error!!
}
}
// Functor
fun <B> map(function: (A) -> B) = ErrorOr(value?.let(function), error)
// Applicative
fun <B, C> combine(other: ErrorOr<B>, function: (A, B) -> C): ErrorOr<C> {
return ErrorOr(value?.let { a -> other.value?.let { b -> function(a, b) } }, error ?: other.error)
}
// Monad
fun <B> bind(function: (A) -> ErrorOr<B>) = value?.let(function) ?: ErrorOr.of(error!!)
}