Chris Lee
01/12/2024, 2:46 PMEither
return types and .bind()
.
One pattern that has been problematic has been aggregating list of errors into a custom wrapper type; while doable in a few different ways, none were really elegant and flowed well; ended up creating mapOrAccumulateInto
providing transformations on the happy path and a transformation on the error path of Nel<Error>
to CustomErrorType(Nel<Error>)
. Perhaps useful as a common pattern (or perhaps I haven’t fully grokked other built-in ways of doing this yet).
context(Raise<ConfigurationError>)
private fun someMethod(
node: SomeType,
type: KType,
context: SomeContext
): List<Any?> {
// ensure statements here
val typeArguments = type.typeArguments
return typeArguments
.zip(node.elements)
.mapOrAccumulateInto(ConversionError::TupleConversionErrors) { (type, element) ->
context.converterFor(type).convert(element, type, context)
}
}
public class TupleConversionErrors(private val errors: Nel<ConfigurationError>) :ConfigurationError()
context(Raise<ConfigurationError>)
@OptIn(ExperimentalTypeInference::class)
public fun <Error : ConfigurationError, AggError : ConfigurationError, A, B> Iterable<A>.mapOrAccumulateInto(
errorTransform: (Nel<Error>) -> AggError,
@BuilderInference transform: Raise<Error>.(A) -> B
): List<B> {
val errors = mutableListOf<Error>()
val results = ArrayList<B>()
for (item in this) {
arrow.core.raise.fold<Error, B, Unit>(
{ transform(this, item) },
{ error -> errors.add(error) },
{ results.add(it) }
)
}
return errors.toNonEmptyListOrNull()?.let { raise(errorTransform(it)) } ?: results
}
Youssef Shoaib [MOD]
01/12/2024, 5:24 PMwithError
Chris Lee
01/12/2024, 5:57 PMYoussef Shoaib [MOD]
01/12/2024, 5:59 PM= withError(ConversionError::TupleConversionErrors {
Chris Lee
01/12/2024, 6:04 PMcontext(Raise<ConfigurationError>)
private fun listToTuple(
node: ResolvedNode.ListNode,
type: KType,
context: ConversionContext
): List<Any?> {
ensureListSize(node, elementCount)
ensureTypeArguments(type, elementCount)
val typeArguments = type.typeArguments
return withError(ConversionError::TupleConversionErrors) {
mapOrAccumulate(typeArguments.zip(node.elements)) { (type, element) ->
context.converterFor(type).convert(element, type, context)
}
}
}
Youssef Shoaib [MOD]
01/12/2024, 6:11 PMcontext(Raise<ConfigurationError>)
private fun listToTuple(
node: ResolvedNode.ListNode,
type: KType,
context: ConversionContext
): List<Any?> = withError(ConversionError::TupleConversionErrors) {
ensureListSize(node, elementCount)
ensureTypeArguments(type, elementCount)
val typeArguments = type.typeArguments
return mapOrAccumulate(typeArguments.zip(node.elements)) { (type, element) ->
context.converterFor(type).convert(element, type, context)
}
}
Youssef Shoaib [MOD]
01/12/2024, 6:14 PMsimon.vergauwen
01/16/2024, 10:40 AM