I'm trying to integrate Arrow-kt's Either into an application that needs to parse and validate filter input. This input is a comma separated list of criteria. Either sound like a good candidate for that job because it does both jobs at the same time.
Big-Picture
I've got a parser that takes care of the first step:
interface Parse<out T> {
    operator fun invoke(value: String): Either<String, T>
}
object ParseList : Parse<List<String>> {
    override fun invoke(value: String): Either<String, List<String>> {
        val values =
            value
                .split(",")
                .map { it.trim() }
                .filter { it.isNotEmpty() }
        return if (values.any()) Either.Right(values)
        else Either.Left("Value is not a list.")
    }
}
and other parsers that take care of an individual value like a date:
class ParseDate : Parse<LocalDate> {
    @Suppress("MemberVisibilityCanBePrivate")
    var formatter: DateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
    override fun invoke(value: String) =
        runCatching { formatter.parse(value) }
            .map { LocalDate.from(it) }
            .map { Either.Right(it) }
            .getOrElse { Either.Left("Value is not a date.") }
}
Combining these to components results in:
List<Either<String, T>>
so it needs to be converted into this:
Either<String, List<T>>
API
In orther to convert a List of Eithers into an Either of Lists i wrote the merge extension that processes each item and stops at the first Left, but keeps running on Right and collecting their values into a new list that is then return as a new Either:
fun <A, B> List<Either<A, B>>.merge(): Either<A, List<B>> {
    val result = mutableListOf<B>()
    for (x in this) {
        when (x) {
            is Either.Right -> result.add(x.value)
            is Either.Left -> return Either.Left(x.value)
        }
    }
    return Either.Right(result)
}
class MergeTest : FunSpec({
    test("Can stop on left.") {
        val list = listOf(
            "foo".right(),
            "bar".left(),
        )
        list.merge() shouldBe "bar".left()
    }
    test("Can merge right.") {
        val list = listOf(
            "foo".right(),
            "bar".right(),
        )
        list.merge() shouldBe listOf("foo", "bar").right()
    }
})
Is it necessary to do this on your own or is there a more clever way?
