Oliver Eisenbarth
09/23/2022, 6:03 AMalexey_gusev
09/23/2022, 12:20 PMConfiguration with name 'implementation' not found.
Do I miss some dependency as it seems?João Gabriel Zó
09/23/2022, 5:02 PMEither<Error, List<A>>
is there a way to map directly into the list without having to either.map{ it.map { f } }
?Oliver Eisenbarth
09/26/2022, 9:31 AMmitch
09/26/2022, 2:34 PMList<T> -> Option<NonEmptyList<T>>
? was it missed?
Context, I found out NonEmptyList.fromList
is now deprecated in favour of nullable types list.toNonEmptyListOrNull()
which is quite verbose. In our kotlin projects, we favour Option<T>
and we don’t use nullable types, hence now we will need to do a list.toNonEmptyListOrNull().toOption()
which is even more verbose.. I wonder if there’s any objections if I raise a PR to introduce list.toNonEmptyListOrNone()
? or a shorter one such as list.toNelOrNone()
Wilerson Oliveira
09/27/2022, 2:31 PMval bar = it.invoke(command) as E
I would guess this casting is the culprit. Wouldn’t val bar = it.invoke(command).bind()
work?simon.vergauwen
09/29/2022, 10:23 AMStylianos Gakis
09/30/2022, 11:43 AMJoão Gabriel Zó
10/03/2022, 3:06 PMwhen (either) {}
everywhere.
Any ideas?Wesley Hartford
10/05/2022, 5:16 PMsealed interface LeftResult
sealed interface DatabaseLeftResult: LeftResult
sealed interface ApiLeftResult: LeftResult
fun queryDatabase() = effect<DatabaseLeftResult, Int> { 42 }
fun submitNumber(number: Int) = effect<ApiLeftResult, Unit> { println(number) }
fun queryAndSubmit() = effect<LeftResult, Unit> {
val number = queryDatabase().bind()
submitNumber(number).bind()
}
However, both of the bind
calls in queryAndSubmit
result in an unresolved reference error. If I make queryDatabase
and submitNumber
use LeftResult
on the left rather than the sub-interface, the code compiles. I can also change the bind
call to .toEither().bind()
and the code compiles. Shouldn't my original code compile though?Lukasz Kalnik
10/06/2022, 3:03 PMbind()
function of the either {}
scope stops being recognized (although it just worked a few moments before and there were no changes in the code):
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public open suspend fun <B> Either<CallError, TypeVariable(B)>.bind(): TypeVariable(B) defined in arrow.core.continuations.EffectScope
public open suspend fun <B> Option<TypeVariable(B)>.bind(shift: () -> CallError): TypeVariable(B) defined in arrow.core.continuations.EffectScope
public open suspend fun <B> Validated<CallError, TypeVariable(B)>.bind(): TypeVariable(B) defined in arrow.core.continuations.EffectScope
public open suspend fun <B> EagerEffect<CallError, TypeVariable(B)>.bind(): TypeVariable(B) defined in arrow.core.continuations.EffectScope
public open suspend fun <B> Effect<CallError, TypeVariable(B)>.bind(): TypeVariable(B) defined in arrow.core.continuations.EffectScope
public open suspend fun <B> Result<TypeVariable(B)>.bind(transform: (Throwable) -> CallError): TypeVariable(B) defined in arrow.core.continuations.EffectScope
Kristian Nedrevold
10/07/2022, 12:38 AMfun foo(): String? = if ((0..1).random() == 1) "Hello World" else null
fun bar(s: String): String? = if ((0..1).random() == 1) s else null
fun maybe(foo: () -> String?, bar: (input: String) -> String?): Either<Err, String> =
foo()?.let { first ->
bar(first)?.let { second ->
Either.Right(second)
} ?: Either.Left(Err("Could not find second"))
} ?: Either.Left(Err("Could not find first"))
maybe(::foo, ::bar)
John Herrlin
10/10/2022, 8:04 AMproduct
to be called first and if that succeeds add
should be called.
But in the following code product
and add
is called concurrently. How can I make them not concurrent? 😃
import java.io.IOException
import arrow.core.computations.either
import arrow.core.Either
import arrow.core.Either.Left
import arrow.core.Either.Right
import arrow.core.getOrHandle
data class Error(val errorString: String, val exception: Exception?)
fun <A> remote(f: () -> A): A = if (Math.random() > 0.2) f() else throw IOException("boom!")
fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
try { Right(f()) }
catch (e: Exception) { Left(Error(errorString, e)) }
fun multiply(a: Int, b: Int): Either<Error, Int> = trap("multiplication failed") { remote { a * b } }
fun add(a: Int, b: Int): Either<Error, Int> = trap("addition failed") { remote { a + b } }
// If fetching `product` is failing `sum` should not be called at all.
suspend fun calculate(a: Int, b: Int): Either<Error, Int> =
either<Error, Int> {
val product = multiply(a, b).bind()
val sum = add(a, b).bind()
sum }
suspend fun main() {
println(calculate(2, 10).getOrHandle { it.errorString })
println(calculate(2, 10).getOrHandle { it.errorString })
}
Marc Plano-Lesay
10/13/2022, 5:16 AMLukáš Kúšik
10/13/2022, 7:58 AMremoved-in-arrow-2
branch in this commit: https://github.com/arrow-kt/arrow/commit/62044120c483b01304819900a5e4cd8b4f1e8ece
Would it be possible to back-port this fix to the current version?Jakub Gwóźdź
10/13/2022, 9:48 AMValidatedNel
to validate and accumulate potential errors when converting objects from one domain to another. Thing is that these objects (deserialized from rest endpoints) have like 20+ fields, which requires me to write custom large .zip
extensions, since the library provides arity only up to 10.
This is not only inconvenient, but also simply smelly.
Is there any better way (or some kind of best practice) to perform validations/conversions on such large number of parameters?Kristian Nedrevold
10/13/2022, 9:05 PMdata class Ssn(val ssn: String) {
companion object {
suspend fun create(ssn: String): ValidatedNel<ValidationError, Ssn> = Validated.fromEither(
either {
val validLengthAndAllNumerical = validateLengthAndAllNumerical(ssn).bind()
Ssn(validateControlNumbers(validLengthAndAllNumerical).bind())
})
private fun validateLengthAndAllNumerical(ssn: String): ValidatedNel<ValidationError, String> = with(ssn) {
length().zip(allNumbers()) { _, _-> ssn }
}
context(String)
private fun length(): ValidatedNel<ValidationError, Unit> =
if (length == 11) Unit.valid()
else ValidationError.IncorrectLength.invalidNel()
context(String)
private fun allNumbers(): ValidatedNel<ValidationError, Unit> =
if (filter { it.isDigit() }.length == length) Unit.valid()
else ValidationError.NotAllDigits.invalidNel()
private fun validateControlNumbers(ssn: String): ValidatedNel<ValidationError, String> {
val firstCtrl = listOf(3, 7, 6, 1, 8, 9, 4, 5, 2, 1)
val secondCtrl = listOf(5, 4, 3, 2, 7, 6, 5, 4, 3, 2, 1)
val ssnNumeric = ssn.map { it.digitToInt() }
val firstValid = ssnNumeric.dropLast(1).reduceIndexed { index, acc, i ->
acc + (i * firstCtrl[index]) } % 11 == 0
val secondValid = ssnNumeric.reduceIndexed { index, acc, i ->
acc + (i * secondCtrl[index]) } % 11 == 0
return if (firstValid && secondValid) ssn.valid()
else ValidationError.RuleViolation.invalidNel()
}
}
}
sealed class ValidationError {
data object Error: ValidationError()
data object IncorrectLength: ValidationError()
data object NotAllDigits: ValidationError()
data object RuleViolation: ValidationError()
}
Jakub Gwóźdź
10/14/2022, 7:36 AMValidated.zip(...)
? Where the last parameter (combining function) also returns ValidatedNel, not the resulting value?Jakub Gwóźdź
10/14/2022, 7:37 AMValidated
is going away in favour of Either
. Are there any tutorials how to perform error-accumulating validations with Either
?Davide Giuseppe Farella
10/15/2022, 1:28 PMEither<NetworkError, T>
Something like
fun <T : Any> MyFun(
...
fetch: suspend () -> Either<NetworkError, T>,
...
): Flow<Either<DataError, T>>
Now I have a new use case, as I started supporting a guest mode, so besides NetworkError
and T
I need something to represent a case when the user is not logged in, which I don’t want to be part of either of the 2 mentioned.
What would you suggest to use instead of Either<NetworkError, T>
? ( Skipped
= call didn’t happen )
Here are some solutions that I thought of, but dunno which one would be nicer, or if there are other solutions:
• Either<Either<NetworkError, Skipped>, T>
this would be the easier one to achieve/refactor; not sure how nice it would be to nest 2 Either
• Either<NetworkResult, T>
sealed interface NetworkResult {
object Skipped : NetworkResult
data class Error(val networkError: NetworkError)
}
• Replace Either
with a sealed interface, like following
sealed interface NetworkResult<T> {
object Skipped : NetworkResult<Nothing>
data class Error<Nothing>(val networkError: NetworkError)
data class Data(val data: T)
}
The last solution is probably the cleanest, but I’d lose the Either
operators that I’m currently using, like tap
, fold
, bind
, etc
The second one would be my preferredNorbi
10/16/2022, 7:44 AMcarbaj0
10/17/2022, 4:25 AMOption<S>
Since we are kotlin syntax friends, i wonder if isn´t possible to set/modify nullable typesCLOVIS
10/18/2022, 1:36 PMbind
abstraction is implemented? I'd like to adapt it to a StateFlow (essentially the same as Either's with success and error, but the value changes over time).Lukasz Kalnik
10/19/2022, 12:11 PMarrow-fx-stm
dependency?pakoito
10/19/2022, 3:55 PMpakoito
10/19/2022, 3:55 PMsimon.vergauwen
10/19/2022, 4:09 PMShabinder Singh
10/19/2022, 6:46 PMList<Either<A,B>>
TO
Either<List<A>,List<B>>
OR
ValidaterNel<A,List<B>>
basically it iterates over either and collect both errors and success,
• .sequence
shortCircuits which isnt wanted here*,*
• .traverse {}
is there but I thought there would a extension function for above as its a common useCase I guess, is there an extension for above ?okarm
10/20/2022, 5:43 PMeither
inside withContext
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
either {
// Code that uses all of shift, bind,
// and currentCoroutineContext().ensureActive()
}
}
2. withContext
inside either
either {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
// Code that uses all of shift, bind,
// and currentCoroutineContext().ensureActive()
}
}
gabib
10/24/2022, 1:40 PMhttps://youtu.be/BIPG5ooWMJM▾
gabib
10/24/2022, 1:40 PMhttps://youtu.be/BIPG5ooWMJM▾
Stylianos Gakis
11/11/2022, 9:23 PMcontext()
feature to the talk. Only makes me more eager to see it become available sometimes soon, in KMP too!