rcd27
05/28/2021, 8:21 AMRetrofit
responses to arrow-kt
Either monad:
class JSONRpcResponseEnvelopeConverter<T>(
private val delegate: Converter<ResponseBody, JSONRpcResponseEnvelope<Any>>
) : Converter<ResponseBody, Either<Throwable, T>> {
override fun convert(value: ResponseBody): Either<Throwable, T> {
val response = delegate.convert(value)
val error = response?.error
return if (error == null) {
Either.Right(
response?.result as T
)
} else {
Either.Left(
InternalServerException(response.error)
)
}
}
}
But it fails with:
java.lang.RuntimeException: Failed to invoke private arrow.core.Either() with no args
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:113)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
at com.tochka.bank.npd.core.network.JSONRpcResponseEnvelopeConverter.convert(JSONRpcResponseEnvelopeConverter.kt:12)
at com.tochka.bank.npd.core.network.JSONRpcResponseEnvelopeConverter.convert(JSONRpcResponseEnvelopeConverter.kt:7)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.InstantiationException: Can't instantiate abstract class arrow.core.Either
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:110)
... 13 more
Maybe there are already proper converters for retrofit2 to arrow-kt?Giovan
05/31/2021, 10:38 AMubu
06/01/2021, 2:08 PMabstract val
property):
@optics
sealed class TestArrow {
abstract val isSelected : Boolean
companion object {}
@optics
data class Test1(override val isSelected: Boolean, val fooBar1: String) : TestArrow() {
companion object {}
}
@optics
data class Test2(override val isSelected: Boolean, val fooBar1: String) : TestArrow() {
companion object {}
}
@optics
data class Test3(override val isSelected: Boolean, val fooBar1: String) : TestArrow() {
companion object {}
}
}
fun TestArrow.updateSelected(isSelected: Boolean) : TestArrow {
return when(this) {
is TestArrow.Test1 -> this.copy(isSelected = isSelected)
is TestArrow.Test2 -> this.copy(isSelected = isSelected)
is TestArrow.Test3 -> this.copy(isSelected = isSelected)
}
}
Any help will be very appreciatedthanh
06/02/2021, 10:07 AMrefined-type
plugin.
here is an example:
@JvmInline
@Serializable
value class GameId private constructor(val value: String) {
companion object : Refined<String, GameId>(::GameId, {
ensure((it.length == 8) to "Expected $it has 8 characters")
})
}
@Serializable
data class Game(
val gameId: GameId,
val color: String,
)
fun main() {
val json = """{"gameId":"abcd1234","color":"white"}"""
println(Json.decodeFromString<Game>(json))
val json2 = """{"gameId":"","color":"white"}"""
println(Json.decodeFromString<Game>(json2))
}
Output:
Game(gameId=GameId(value=abcd1234), color=white)
Game(gameId=GameId(value=), color=white)
Is this something we have to accept or should we put some require in init
block?Jose Antonio Jimenez
06/02/2021, 10:26 AMshouldBeLeft
of kotest 4.4.3:
arrow.core.Either$Left.getA()Ljava/lang/Object
Marko Novakovic
06/02/2021, 11:31 AMkierans777
06/03/2021, 4:52 AMf compose g
in my code. However why is compose
an infix function? That's the sort of documentation I'm after, and I'm hoping someone can point me in the right direction. 😄Mitchell Skaggs
06/05/2021, 8:25 AMGetter<S,A>
be contravariant on S
? I'm trying to use it in a contravariant way and it's not working in compositions. Having it contravariant in the original type would fix this.Roger Cyr
06/05/2021, 3:03 PMMitchell Skaggs
06/06/2021, 3:59 AMOption.lift
an entire optic? I'm currently just lifting each function in an Iso
individually, and it seems like that would be a useful function to have when creating lots of optics.Roger Cyr
06/06/2021, 4:31 PMCLOVIS
06/07/2021, 3:39 PMeither
block?
I currently have:
if (some condition) {
val left: Either<Failure, DbUser> =
UnknownFailure("some message here")
.left()
left.bind()
}
I would have just written
if (some condition)
UnknownFailure("message").left().bind()
however, that casts the entire either block to Either<Failure, Nothing>.
Cody Mikol
06/07/2021, 4:16 PMMono / Flux
to Either / Validated
? I find the suspended handling of parZip / parTraverse
to be much more intuitive than the Webflux functionalitiesJimmy Alvarez
06/09/2021, 1:56 AMEither.catch {}
on some network calls, one comment was that using a try/catch
is more explicit. how could you sell the idea that Either.catch {}
is better than usual try/catch
.
For me, the way it looks y just clean, but they think the other way, for them is more clear an imperative style.
I don’t wanna get back to try/catch
😂kierans777
06/09/2021, 6:27 AMfun add(a: Int, b: Int): Int = a + b
val multiply: (Int, Int) -> Int = { a: Int, b: Int -> a * b }
val add3 = add.curried()(3) // does not compile
val multiply2 = multiply.curried()(2)
Where this affects me is that I want to have a function that can take different parameter types eg: an Int or a String. Standard function overloading gets me out of this
fun add(a: Int, b: Int): Int = a + b
fun add(a: String, b: String): Int = add(Integer.parseInt(a), Integer.parseInt(b))
However I lose the nice FP'ness ie: currying, composability, etc.kierans777
06/09/2021, 11:15 AMMarius Kotsbak
06/09/2021, 2:21 PMfun <A, B> Collection<Either<A, B>>.allLefts(): List<A> = this.mapNotNull { either -> either.fold({ it }, { null }) }
Do you have any ideas for better ways to do it with Arrow or should something be added? Use case here is to not do short circuit, so we can't use traverseEither.Peter
06/09/2021, 5:23 PMGarth Gilmour
06/09/2021, 7:49 PMraulraja
06/10/2021, 10:24 AMSaiedmomen
06/11/2021, 10:00 AMChris Paul
06/14/2021, 11:25 AMreturn newStockItem.right()
.flatMap { checkFirstThing(newStockItem) }
.flatMap { checkSecondThing(newStockItem) }
vs
return checkFirstThing(newStockItem)
.flatMap { checkSecondThing(newStockItem) }
I find the first a little more readable but does mean extra box operations.Alexander Levin
06/14/2021, 3:09 PMMyType.foo.bar.every.baz.modify(obj) { someSuspendFun(it) }
dnowak
06/15/2021, 2:27 PM@JvmStatic
@JvmName("tryCatch")
inline fun <A> catch(recover: (Throwable) -> Unit, f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
recover(t.nonFatalOrThrow())
None
}
Why recover is (Throwable) -> Unit
not (Throwable) -> Option<A>
? Shouldn’t the caller decide if the exception should be mapped to None
or Some
?Pedro Sena
06/15/2021, 5:15 PM@Transactional
and Either
?
Basically I'm using Either<Throwable, Something>
as return type for many of my services and now I'd like to add transactional control through annotations instead of doing it manually (just recently integrated micronaut into the project)
Do you have any tips on how(if possible) to accommodate both ?Pedro Sena
06/15/2021, 5:15 PM@Transactional
depends on an exception being thrown to rollback the transaction, which does not happen because I wrap the exception on Left
)kierans777
06/17/2021, 4:18 AMEither
. For example (Int) -> Either<Error, Int>
. I can use monandic comprehensions ie:
val c = either {
val a = func1(1).bind()
val b = func2(a).bind()
b
}
However I want to create a pipe/composition to remove the intermediate variables. In pseudo code
val pipe = func2 composeK func1
val c = pipe(1)
Is this possible?Marcello Lelio Albano
06/17/2021, 11:17 PMstojan
06/18/2021, 8:01 AMJascha Smacka
06/18/2021, 2:13 PMJascha Smacka
06/18/2021, 2:13 PMOliver Eisenbarth
06/19/2021, 6:30 PMraulraja
06/20/2021, 9:12 AMsuspend fun
.
There are no ambitions to compete against those as in most cases they are purely functional or offer a means to just use suspension which is equivalent as being wrapped in IO[A]
plus the additional powers like direct syntax that continuations offer natively.
In contrast to other langs like Scala where there is no native IO and most FP programs are written depending on heavy frameworks here instead we just rely on suspension. This means that if you want to make a library compatible with Arrow, you could definitely use Arrow to build and provide utilities like Either, comprehensions, parZip etc but if your library does not need those and you just use suspend fun
for all IO related ops then it’s still compatible 100% with arrow and the rest of Kotlin’s libraries.
In Scala and others the discipline is about writing code over F with the type class abstractions these libraries provide or sticking to the boxed data types framework like Zio pack.
In Arrow the discipline is just use suspend fun
when you need to perform IO or anything that need to be effect protected.
IMO Kotlin already has better dependency injection and support for FP interoperability of libraries and programs through receiver funs, inline and suspension (eliminating transformers), compiler optimized continuations and soon multiple scoped functions which in my opinion cover most of the features you find in other Scala libraries in a boxed form, here in a more performant and ergonomic syntax.