diff --git a/client/src/main/kotlin/net/corda/client/mock/Generator.kt b/client/src/main/kotlin/net/corda/client/mock/Generator.kt index 660fd8054d..bf737bc898 100644 --- a/client/src/main/kotlin/net/corda/client/mock/Generator.kt +++ b/client/src/main/kotlin/net/corda/client/mock/Generator.kt @@ -31,42 +31,42 @@ import java.util.* * * The above will generate a random list of animals. */ -class Generator(val generate: (SplittableRandom) -> ErrorOr) { +class Generator(val generate: (SplittableRandom) -> ErrorOr) { // Functor - fun map(function: (A) -> B): Generator = + fun map(function: (A) -> B): Generator = Generator { generate(it).map(function) } // Applicative - fun product(other: Generator<(A) -> B>) = + fun product(other: Generator<(A) -> B>) = Generator { generate(it).combine(other.generate(it)) { a, f -> f(a) } } - fun combine(other1: Generator, function: (A, B) -> R) = + fun combine(other1: Generator, function: (A, B) -> R) = product(other1.product(pure({ b -> { a -> function(a, b) } }))) - fun combine(other1: Generator, other2: Generator, function: (A, B, C) -> R) = + fun combine(other1: Generator, other2: Generator, function: (A, B, C) -> R) = product(other1.product(other2.product(pure({ c -> { b -> { a -> function(a, b, c) } } })))) - fun combine(other1: Generator, other2: Generator, other3: Generator, function: (A, B, C, D) -> R) = + fun combine(other1: Generator, other2: Generator, other3: Generator, function: (A, B, C, D) -> R) = product(other1.product(other2.product(other3.product(pure({ d -> { c -> { b -> { a -> function(a, b, c, d) } } } }))))) - fun combine(other1: Generator, other2: Generator, other3: Generator, other4: Generator, function: (A, B, C, D, E) -> R) = + fun combine(other1: Generator, other2: Generator, other3: Generator, other4: Generator, function: (A, B, C, D, E) -> R) = product(other1.product(other2.product(other3.product(other4.product(pure({ e -> { d -> { c -> { b -> { a -> function(a, b, c, d, e) } } } } })))))) // Monad - fun bind(function: (A) -> Generator) = + fun bind(function: (A) -> Generator) = Generator { generate(it).bind { a -> function(a).generate(it) } } companion object { - fun pure(value: A) = Generator { ErrorOr(value) } - fun impure(valueClosure: () -> A) = Generator { ErrorOr(valueClosure()) } - fun fail(error: Exception) = Generator { ErrorOr.of(error) } + fun pure(value: A) = Generator { ErrorOr(value) } + fun impure(valueClosure: () -> A) = Generator { ErrorOr(valueClosure()) } + fun fail(error: Exception) = Generator { ErrorOr.of(error) } // Alternative - fun choice(generators: List>) = intRange(0, generators.size - 1).bind { generators[it] } + fun choice(generators: List>) = intRange(0, generators.size - 1).bind { generators[it] } - fun success(generate: (SplittableRandom) -> A) = Generator { ErrorOr(generate(it)) } - fun frequency(generators: List>>): Generator { + fun success(generate: (SplittableRandom) -> A) = Generator { ErrorOr(generate(it)) } + fun frequency(generators: List>>): Generator { val ranges = mutableListOf>() var current = 0.0 generators.forEach { @@ -87,7 +87,7 @@ class Generator(val generate: (SplittableRandom) -> ErrorOr) { } } - fun sequence(generators: List>) = Generator> { + fun sequence(generators: List>) = Generator> { val result = mutableListOf() for (generator in generators) { val element = generator.generate(it) @@ -103,9 +103,9 @@ class Generator(val generate: (SplittableRandom) -> ErrorOr) { } } -fun Generator.Companion.frequency(vararg generators: Pair>) = frequency(generators.toList()) +fun Generator.Companion.frequency(vararg generators: Pair>) = frequency(generators.toList()) -fun Generator.generateOrFail(random: SplittableRandom, numberOfTries: Int = 1): A { +fun Generator.generateOrFail(random: SplittableRandom, numberOfTries: Int = 1): A { var error: Throwable? = null for (i in 0..numberOfTries - 1) { val result = generate(random) @@ -124,6 +124,7 @@ fun Generator.generateOrFail(random: SplittableRandom, numberOfTrie } fun Generator.Companion.int() = Generator.success(SplittableRandom::nextInt) +fun Generator.Companion.long() = Generator.success(SplittableRandom::nextLong) fun Generator.Companion.bytes(size: Int): Generator = Generator.success { random -> ByteArray(size) { random.nextInt().toByte() } } @@ -143,7 +144,7 @@ fun Generator.Companion.doubleRange(from: Double, to: Double): Generator from + it.nextDouble() * (to - from) } -fun Generator.Companion.replicate(number: Int, generator: Generator): Generator> { +fun Generator.Companion.replicate(number: Int, generator: Generator): Generator> { val generators = mutableListOf>() for (i in 1..number) { generators.add(generator) @@ -152,7 +153,7 @@ fun Generator.Companion.replicate(number: Int, generator: Generator } -fun Generator.Companion.replicatePoisson(meanSize: Double, generator: Generator) = Generator> { +fun Generator.Companion.replicatePoisson(meanSize: Double, generator: Generator) = Generator> { val chance = (meanSize - 1) / meanSize val result = mutableListOf() var finish = false @@ -173,8 +174,8 @@ fun Generator.Companion.replicatePoisson(meanSize: Double, generator: ErrorOr(result) } -fun Generator.Companion.pickOne(list: List) = Generator.intRange(0, list.size - 1).map { list[it] } -fun Generator.Companion.pickN(number: Int, list: List) = Generator> { +fun Generator.Companion.pickOne(list: List) = Generator.intRange(0, list.size - 1).map { list[it] } +fun Generator.Companion.pickN(number: Int, list: List) = Generator> { val mask = BitSet(list.size) val size = Math.min(list.size, number) for (i in 0..size - 1) { @@ -199,15 +200,13 @@ fun Generator.Companion.pickN(number: Int, list: List) = Generator< fun Generator.Companion.sampleBernoulli(maxRatio: Double = 1.0, vararg collection: A) = sampleBernoulli(listOf(collection), maxRatio) -fun Generator.Companion.sampleBernoulli(collection: Collection, maxRatio: Double = 1.0): Generator> = - intRange(0, (maxRatio * collection.size).toInt()).bind { howMany -> - replicate(collection.size, Generator.doubleRange(0.0, 1.0)).map { chances -> - val result = mutableListOf() - collection.forEachIndexed { index, element -> - if (chances[index] < howMany.toDouble() / collection.size.toDouble()) { - result.add(element) - } +fun Generator.Companion.sampleBernoulli(collection: Collection, meanRatio: Double = 1.0): Generator> = + replicate(collection.size, Generator.doubleRange(0.0, 1.0)).map { chances -> + val result = mutableListOf() + collection.forEachIndexed { index, element -> + if (chances[index] < meanRatio) { + result.add(element) } - result } + result } diff --git a/core/src/main/kotlin/net/corda/core/Utils.kt b/core/src/main/kotlin/net/corda/core/Utils.kt index 6b4969bdce..ca39b64fcd 100644 --- a/core/src/main/kotlin/net/corda/core/Utils.kt +++ b/core/src/main/kotlin/net/corda/core/Utils.kt @@ -357,7 +357,7 @@ data class ErrorOr private constructor(val value: A?, val error: Throwabl } // Monad - fun bind(function: (A) -> ErrorOr): ErrorOr { + fun bind(function: (A) -> ErrorOr): ErrorOr { return if (error == null) { function(value as A) } else {