mattmoore
02/04/2020, 5:45 PM0.11.0-SNAPSHOT
last night using Ktor. I switched from EitherT
over to IO<E, A>
and got everything compiling and running. The weird thing is that with IO<E, A>
if I respond with A
in Ktor (where A
is the successful data class I'm expecting), A
gets serialized with { "b": { ... } }
.
At first I thought I had something still wrapped, but I inspected all the functions and types and still am getting that result. When I downgraded back to 0.10.4
and switched back to EitherT
the response serializes properly without b
and instead serializes to { ... }
. Curious if anyone else has encountered this.
Here's an example:
fun getLeads(): IO<Exception, List<Lead>> =
IO.fx<Exception, List<Lead>> {
transaction {
Leads.selectAll().map { toLead(it) }
}
}
val response = getLeads().attempt().map {
when (it) {
is Either.Left -> mapOf("error" to it.a.message)
is Either.Right -> present(it.b)
}
}
call.respond(response.suspended())
It's entirely possible I'm misusing attempt
here, not sure. The Ktor serialized response I get is:
{
"b": [
{
"id": 2,
"firstName": "Matt",
"lastName": "Moore"
}
]
}
With EitherT
:
fun getLeads(): EitherT<ForIO, Exception, List<Lead>> = EitherT(
IO {
Right(
transaction {
Leads.selectAll().map { toLead(it) }
}
)
}.handleError { Left(Exception(it.message)) }
)
val response = getLeads().value().fix().map {
when (it) {
is Either.Left -> mapOf("error" to it.a.message)
is Either.Right -> present(it.b)
}
}.suspended()
call.respond(response)
When I run this example with EitherT
I get this response from Ktor:
[
{
"id": 2,
"firstName": "Matt",
"lastName": "Moore"
}
]
Note that it no longer wraps in b
Apologies for the long message!simon.vergauwen
02/04/2020, 6:33 PMsuspended()
here is still returning Right(b: B)
.simon.vergauwen
02/04/2020, 6:35 PMIO<E, A>
is by all means EitherT<ForIO
which means it deals with Throwable
, E
& A
.
The semantics of attempt
have not changed, which is attempt to run it and lift the Throwable
to A
.
val t: IO<E, A>
val t2: IO<E, Either<Throwable, A>>
val t3: IO<Nothing, IOResult<E, A>> = t.result()
val t4: IO<Nothing, A> = t.fallbackWith(IO.just(backupA))
simon.vergauwen
02/04/2020, 6:35 PMsuspended
currently always returns Either<E, A>
I think the snapshot has a suspendedGet
for IO<Nothing, A>
which you could use after providing a fallback default value.