Francis Reynders
03/07/2023, 4:08 PMNorbi
03/07/2023, 8:29 PMraise()
.
The code in my next message references different catch()
functions, and their return type and semantic is different as well.
How should I refactor the second eagerEffect {}
call to make it execute fold()
in the background?Alejandro Serrano Mena
03/08/2023, 2:55 PMNorbi
03/10/2023, 9:57 AMRaise<R>
, how should I use it in "real" code?
My problem is:
1. I've found that very often I want to know the root cause of an error - so I've reinvented the cause
mechanism of exceptions 😐
2. I've found that by handling raise()
-d errors, the contextual information is lost at the top level, where I maybe want to log a stack trace for easier investigation of the problem.
Do you have some practical advice for using it?
Maybe my head has just "stuck" thinking only by exceptions 🙂
Thanks.Marko Novakovic
03/10/2023, 11:21 AMimport arrow.core.memoize
for suspend fun
?Marko Novakovic
03/10/2023, 5:54 PMEither
.catch { httpClient.get("") }
.map { it.body() }
is enough?dave08
03/12/2023, 3:42 PMcontext(Raise<...>)
requires suspend fun
since all side-effects should be suspend fun
... am I wrong?Tower Guidev2
03/13/2023, 9:32 AMarrow.retrofit.adapter.either.ResponseE
in retrofit calls as follows:-
@FormUrlEncoded
@POST(OAUTH2_TOKENS_URL_PATH)
suspend fun accessToken(
@HeaderMap headers: Map<String, String> = emptyMap(),
@FieldMap(encoded = true) fields: Map<String, String>
) : ResponseE<CallError, AccessTokenResponse>
where CallError
is arrow.retrofit.adapter.either.networkhandling.CallError
as when i execute my android application I recieve a kotlin serialisation error stating no serialiser can be found for CallError
do i have to supply my own custom version of CallError that is annotated as @Serializable?
I am using this version of Arrow
api platform('io.arrow-kt:arrow-stack:1.1.5')
api 'io.arrow-kt:arrow-core'
api 'io.arrow-kt:arrow-core-retrofit'
CLOVIS
03/13/2023, 10:36 AMdave08
03/13/2023, 4:27 PMfun foo() = effect {
raise(DomainError)
}
fun bar() = effect {
val context = ....
val result = foo().bind()
}
data class WrappedError(val context: Context, val error: DomainError)
// elsewhere
bar().fold({ e -> // I need e to be WrappedError but I can only get the context in bar() ... and foo() raises DomainErrors w/o the context. }) { ... }
dave08
03/13/2023, 4:28 PMdave08
03/13/2023, 4:58 PMeffect { }
block processing the request:
val formParameters =
catch({ call.receiveParameters() }) { e -> raise(GenericRequestFailure(e.message ?: "")) }
but I can't since I don't have a Raise<> context (and I need the ApplicationCall as the receiver), do I just have to create another effect { } block for it and then use bind()
or is there a better way? It seems like Either.catch...
is deprecated... (and doesn't have a raise function?)Jorge Bo
03/13/2023, 10:49 PMeither {
val changeType: String
if (changeType == "do nothing") {
//leave early, this is not an error
return Either.Right("leave early)
}
..do some complicated logic and leave
"quit".right()
}
Marko Novakovic
03/14/2023, 11:35 AMlet f = [ 1; 2; 3; 4; 5 ] |> List.map (fun x -> x * 2) |> List.map string
Kotlin
fun f() = listOf(1, 2, 3, 4, 5).map { it * 2 }.map(Int::toString)
it’s much nicer looking in Kotlin because map
is en extension function.
same goes for .let {}
, .apply {}
etc.dnowak
03/14/2023, 1:26 PMIO
was in early versions of arrow?
2. Any advantage of using Effect
compared to suspended function
?
3. Where can I find some “reference” code showing how to use effects - combining small effects into larger ones, using effects in the application?Fred Friis
03/14/2023, 1:45 PMrednifre
03/14/2023, 6:02 PMrednifre
03/14/2023, 6:31 PMEmil Kantis
03/14/2023, 10:42 PMEitherNel<CreateInvoiceError, A>
)
listOfNotNull(
if (dueDate <= invoiceDate) CreateInvoiceError.InvalidDueDate(invoiceDate, dueDate) else null,
if (rows.isEmpty()) CreateInvoiceError.NoRows else null,
).toNonEmptyListOrNull()?.let { raise(it) }
rednifre
03/15/2023, 8:36 AMCLOVIS
03/15/2023, 10:45 AMinterface A
interface B
context(A, B)
fun foo() { … }
can I call it like this?
class Context : A, B
with(Context()) {
foo()
}
Said otherwise, can a single object satisfy multiple context receivers?dave08
03/15/2023, 12:10 PMdave08
03/15/2023, 12:14 PMRaehat Singh Nanda
03/16/2023, 1:21 PMFrancis Reynders
03/16/2023, 5:03 PMonExit
method will be called). The Rescource.use
and resourceScope
functions only provide the resource in the lambda, however I would like to have the resource available between object initialization and onExit
, so during the lifecycle of the object). Is there a standard way to do so?
I was thinking of creating a CoroutineScope and lauching a coroutine in the init
part, running resourceScope there and waiting for cancellation. The onExit
method would cancel that scope. However that would mean the acquired resource would need to be defined as a lateinit var
rather than val since the compiler does not allow initialization from within the coroutine. It also seems a bit convoluted.
class Test() {
val scope = CoroutineScope(EmptyCoroutineContext)
lateinit var resource: String
init {
scope.launch {
resourceScope {
resource = install({"test"}, { _,_ -> Unit })
}
awaitCancellation()
}
}
If there is a better way I would love to hear about it.Tom Everton
03/17/2023, 2:31 PMdave08
03/19/2023, 11:53 AM{ "some": "json" }
and I have JsonPath["some2"].set(json, JsonPrimitive("json2"))
it just silently doesn't do anything... I would have expected it to create the new key. Is there any way to do that?dave08
03/19/2023, 12:42 PMdave08
03/19/2023, 4:50 PMasdf asdf
03/19/2023, 7:10 PMeither
builder has to be called from a suspending context? It seems to work fine with a non-suspending implementation like this:
fun main() {
val res = nonSuspendingEither {
if (Random.nextBoolean()) shift(AuthResult.Success(534))
else AuthResult.Failure("Invalid")
}
println(res)
}
@RestrictsSuspension
interface RestrictedEffectScope<E> : EffectScope<E>
fun <E, A> nonSuspendingEither(closure: suspend RestrictedEffectScope<E>.() -> A): Either<E, A> {
var result: Either<E, A>? = null
val scope = object : RestrictedEffectScope<E> {
override suspend fun <B> shift(r: E): B {
result = Either.Left(r)
return suspendCoroutine { /*no-op*/ }
}
}
closure.startCoroutine(scope, Continuation(EmptyCoroutineContext) {
result = Either.Right(it.getOrThrow())
})
return result!!
}
asdf asdf
03/19/2023, 7:10 PMeither
builder has to be called from a suspending context? It seems to work fine with a non-suspending implementation like this:
fun main() {
val res = nonSuspendingEither {
if (Random.nextBoolean()) shift(AuthResult.Success(534))
else AuthResult.Failure("Invalid")
}
println(res)
}
@RestrictsSuspension
interface RestrictedEffectScope<E> : EffectScope<E>
fun <E, A> nonSuspendingEither(closure: suspend RestrictedEffectScope<E>.() -> A): Either<E, A> {
var result: Either<E, A>? = null
val scope = object : RestrictedEffectScope<E> {
override suspend fun <B> shift(r: E): B {
result = Either.Left(r)
return suspendCoroutine { /*no-op*/ }
}
}
closure.startCoroutine(scope, Continuation(EmptyCoroutineContext) {
result = Either.Right(it.getOrThrow())
})
return result!!
}
simon.vergauwen
03/19/2023, 7:35 PMeither.eager
to achieve the same as you do here with @RestrictSuspension
. In fact the implementation is 99% the same.
However in 1.2.x we've simplified this, and either
is simply inline fun
there. You can use it in 1.1.6-alpha.59
, it's source compatible with 1.1.x given some extra imports 😉asdf asdf
03/19/2023, 7:58 PM