Kev
06/26/2024, 9:03 AMIorNel<Error, R>
where errors are accumulated would work. However, where would one model the warnings? Sub type of the error type and then sift through the accumulated errors to see if’s tagged with a warning interface? Or wrap the return result in some Warning
monad?Kev
06/26/2024, 9:04 AMCLOVIS
06/26/2024, 9:22 AMKev
06/26/2024, 9:25 AMCLOVIS
06/26/2024, 9:25 AMKev
06/26/2024, 9:26 AMCLOVIS
06/26/2024, 9:26 AMEitherNel<Warning, EitherNel<Error, Success>>
. Verbose, but you do want a complex thing…CLOVIS
06/26/2024, 9:26 AMCLOVIS
06/26/2024, 9:27 AMPair<Nel<Warning>, EitherNel<Error, Success>>
is closer to what you wantCLOVIS
06/26/2024, 9:31 AMsealed class OutcomeWithWarnings<out W, out F, out S> {
abstract val warnings: List<W>
}
data class WarningsOnly<W>(
override val warnings: Nel<W>
) : OutcomeWithWarnings<W, Nothing, Nothing>()
data class Failed<W, F>(
val errors: Nel<F>,
override val warnings: List<W>
) : OutcomeWithWarnings<W, F, Nothing>()
data class Success<W, S>(
val value: S,
override val warnings: List<W>
) : OutcomeWithWarnings<W, Nothing, S>()
but you'd have to re-create the entire DSLKev
06/26/2024, 9:33 AMCLOVIS
06/26/2024, 9:56 AMCLOVIS
06/26/2024, 9:57 AMProgressiveOutcome
but with warnings instead of progress information: https://gitlab.com/opensavvy/groundwork/pedestal/-/blob/main/state/src/commonMain/kotlin/progressive/Progressive.kt?ref_type=heads#L30dave08
07/11/2024, 9:27 AMAlejandro Serrano.Mena
07/11/2024, 10:33 AMdave08
07/11/2024, 10:53 AMdave08
07/11/2024, 10:54 AMdave08
07/11/2024, 10:54 AMAlejandro Serrano.Mena
07/11/2024, 10:54 AMdata class Result(
val warning: MutableList<Warning>,
val result: Either<Error, Result>
)
dave08
07/11/2024, 10:55 AMeither { }
and raise
?dave08
07/11/2024, 10:56 AMResult
... so that would be Unit
)Alejandro Serrano.Mena
07/11/2024, 10:57 AMfun Raise<Problem>.foo(
warnings: MutableList<Warning>,
): Unit
dave08
07/11/2024, 10:57 AMdave08
07/11/2024, 10:58 AMfun interface UseCase1 {
operator suspend fun invoke(...): Either<..., ...>
}
Alejandro Serrano.Mena
07/11/2024, 10:59 AMdave08
07/11/2024, 11:01 AMraise
is called, I'd still need a way to pass what I have so far of logs... so I can report them in the field in the parent use case.dave08
07/11/2024, 11:02 AMreturn
the logs, since raise
will just jump to the error lambda of recover and skip that return...dave08
07/11/2024, 11:02 AMKev
07/11/2024, 11:13 AMinterface WarningCollector {
fun get(): List<String>
fun addWarning(warning: String)
}
val collector = object : WarningCollector {
private val mutableList = mutableListOf<String>()
override fun get(): List<String> = mutableList
override fun addWarning(warning: String) {
mutableList.add(warning)
}
}
context(WarningCollector)
fun foo(): Either<Error, String> = either {
addWarning("foo returning foo")
"foo"
}
context(WarningCollector)
fun bar(): Either<Error, Int> = either {
addWarning("bar returning 1")
1
}
context(WarningCollector)
fun baz(): Either<Error, Boolean> = either {
addWarning("things go boom")
raise(Error("boom!"))
}
fun main() {
with(collector) {
foo()
baz()
bar()
}
collector.get().forEach(::println)
}
dave08
07/11/2024, 11:14 AMdave08
07/11/2024, 11:15 AMdave08
07/11/2024, 11:15 AMdave08
07/11/2024, 2:02 PM