dev.marksman.kraftwerk.CoProducts Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kraftwerk Show documentation
Show all versions of kraftwerk Show documentation
Purely functional random data generation
The newest version!
package dev.marksman.kraftwerk;
import com.jnape.palatable.lambda.adt.Either;
import com.jnape.palatable.lambda.adt.Maybe;
import com.jnape.palatable.lambda.adt.These;
import com.jnape.palatable.lambda.adt.Unit;
import dev.marksman.kraftwerk.frequency.FrequencyMap;
import dev.marksman.kraftwerk.weights.BooleanWeights;
import dev.marksman.kraftwerk.weights.EitherWeights;
import dev.marksman.kraftwerk.weights.MaybeWeights;
import dev.marksman.kraftwerk.weights.TernaryWeights;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static dev.marksman.kraftwerk.Generators.constant;
import static dev.marksman.kraftwerk.weights.EitherWeights.rights;
import static dev.marksman.kraftwerk.weights.MaybeWeights.justs;
import static dev.marksman.kraftwerk.weights.TernaryWeights.ternaryWeights;
final class CoProducts {
private CoProducts() {
}
private static final Generator GENERATE_UNIT = constant(Unit.UNIT);
private static final Generator GENERATE_TRUE = constant(true);
private static final Generator GENERATE_FALSE = constant(false);
private static final MaybeWeights DEFAULT_MAYBE_WEIGHTS = justs(9).toNothings(1);
private static final EitherWeights DEFAULT_EITHER_WEIGHTS = rights(9).toLefts(1);
private static final TernaryWeights DEFAULT_THESE_WEIGHTS = ternaryWeights();
static Generator generateUnit() {
return GENERATE_UNIT;
}
static Generator generateBoolean(BooleanWeights weights) {
int trueWeight = weights.getTrueWeight();
int falseWeight = weights.getFalseWeight();
if (trueWeight == falseWeight) {
return Generators.generateBoolean();
} else {
return FrequencyMap.frequencyMap(generateFalse().weighted(falseWeight))
.add(generateTrue().weighted(trueWeight))
.toGenerator();
}
}
static Generator generateTrue() {
return GENERATE_TRUE;
}
static Generator generateFalse() {
return GENERATE_FALSE;
}
static Generator> generateMaybe(MaybeWeights weights, Generator g) {
return FrequencyMap.frequencyMap(generateJust(g).weighted(weights.getJustWeight()))
.add(CoProducts.generateNothing().weighted(weights.getNothingWeight()))
.toGenerator();
}
static Generator> generateMaybe(Generator g) {
return generateMaybe(DEFAULT_MAYBE_WEIGHTS, g);
}
static Generator> generateJust(Generator g) {
return g.fmap(Maybe::just);
}
static Generator> generateNothing() {
return constant(nothing());
}
static Generator> generateEither(EitherWeights weights, Generator leftGenerator, Generator rightGenerator) {
return FrequencyMap.frequencyMap(CoProducts.generateLeft(leftGenerator).weighted(weights.getLeftWeight()))
.add(CoProducts.generateRight(rightGenerator).weighted(weights.getRightWeight()))
.toGenerator();
}
static Generator> generateEither(Generator leftGenerator, Generator rightGenerator) {
return generateEither(DEFAULT_EITHER_WEIGHTS, leftGenerator, rightGenerator);
}
static Generator> generateLeft(Generator g) {
return g.fmap(Either::left);
}
static Generator> generateRight(Generator g) {
return g.fmap(Either::right);
}
static Generator> generateThese(Generator generatorA, Generator generatorB) {
return generateThese(DEFAULT_THESE_WEIGHTS, generatorA, generatorB);
}
static Generator> generateThese(TernaryWeights weights, Generator generatorA, Generator generatorB) {
return FrequencyMap.frequencyMap(generatorA.fmap(These::a).weighted(weights.getWeightA()))
.add(generatorB.fmap(These::b).weighted(weights.getWeightB()))
.add(generatorA.zipWith(These::both, generatorB).weighted(weights.getWeightC()))
.toGenerator();
}
}