Philipp Mayer
10/19/2021, 2:25 PMimport arrow.core.Either
import arrow.core.left
import arrow.core.right
import reactor.core.publisher.Mono
fun doSomething(): Mono<Either<String, Boolean>> = Mono.just(1).flatMap { listingId ->
handle(listingId)
}
fun handle(x: Int): Either<String, Mono<Boolean>> =
if (x == 1) Mono.just(true).right()
else "something else".left()
Basically I return either a mono of some value or a default value which is not a mono (but could be if it makes things easier).
In applyforFinancing
I want to return the result of ::handle
, but that gives me:
Type mismatch.
Required:
Either<String, Mono<Boolean>>
Found:
Mono<(???..???)>
How could one achieve that?
Basically I somehow have to transform an Either<Mono<…>, Mono<…>
to Mono<Either<…,…>
Thanks in advance!Marius Kotsbak
10/20/2021, 3:19 PM* What went wrong:
Could not determine the dependencies of task ':packageJson'.
> Could not resolve all dependencies for configuration ':npm'.
> Could not resolve io.arrow-kt:arrow-core:1.0.0.
Required by:
project :
> No matching variant of io.arrow-kt:arrow-core:1.0.0 was found. The consumer was configured to find a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy' but:
- Variant 'commonMainMetadataElements' capability io.arrow-kt:arrow-core:1.0.0:
- Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attribute:
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
Peter
10/22/2021, 4:38 PMurl
has mutable state constrained locally and should still be referentially transparent i believe, does this pattern have a place in functional kotlin?ibcoleman
10/23/2021, 10:49 PMObservable<Either<T, U>>
and though the either {}
stuff is pretty straightforward, the only documentation I can find on nested monads is the old EitherT, OptionT documentation. Here Observable
is from rxjava2. What if I wanted to use a Reader and had to deal with Reader<Observable<Either<MyError, Aggregate
? Just very confused…
@Test
fun checkCallsWithEitherComprehensionTest() = runBlocking {
fun together(asset: Asset, agg: Aggregate): Either<MyError, AssetWithAggregate> =
Right(AssetWithAggregate(assetName = asset.name, aggName = agg.name, id = asset.id))
fun getAggregate(): Observable<Either<MyError, Aggregate>> =
Observable.just(Right(Aggregate(id="000", name="An Aggregate")))
fun getAsset(id: String): Observable<Either<MyError, Asset>> =
Observable.just(Right(Asset(id=id, name="An Asset")))
// How do I get rid of blockingSingle() to defer this stuff?
val togetherE: Either<MyError, AssetWithAggregate> = either {
val theAgg = getAggregate().blockingSingle().bind()
val theAsset = getAsset(theAgg.id).blockingSingle().bind()
together(theAsset, theAgg).bind()
}
// Check the values of the returned Either
togetherE.fold(
{_ -> assertTrue(false, "Error: Should be right!")},
{
assertEquals("An Asset", it.assetName)
assertEquals("An Aggregate" , it.aggName)
assertEquals("000", it.id)
}
)
}
Michael Friend
10/25/2021, 3:08 PMBenoît
10/26/2021, 9:59 AMMarius Kotsbak
10/28/2021, 11:26 AM@Suppress("ClassName")
@Deprecated(
"The `either` computation block supports validated with the right short-circuiting semantics",
ReplaceWith("either", "arrow.core.computations.either")
)
object validated {
inline fun <E, A> eager(crossinline c: suspend RestrictedValidatedEffect<E, *>.() -> A): Validated<E, A> =
Effect.restricted(eff = { RestrictedValidatedEffect { it } }, f = c, just = { it.valid() })
suspend inline operator fun <E, A> invoke(crossinline c: suspend ValidatedEffect<E, *>.() -> A): Validated<E, A> =
Effect.suspended(eff = { ValidatedEffect { it } }, f = c, just = { it.valid() })
}
As far as I can see .bind() short circuit on first validation error instead of accumulating?:
suspend fun <B> Validated<E, B>.bind(): B =
when (this) {
is Validated.Valid -> a
is Validated.Invalid -> control().shift(this@bind)
}
jean
10/29/2021, 7:16 AMdata class GetUserImageContext(val apiClient: ApiClient)
typealias GetUserImage = suspend GetUserImageContext.(path: String) -> Either<ApiError, UserImage>
fun getUserImage(): GetUserImage = { path ->
try {
// some executiuon
Either.Right(image)
} catch(e: Exception) {
Either.Left(ApiError.SomethingWentWrong)
}
}
This suits me well for unit testing but the problem comes where a function is composed of several like that one. The context object ends up containing too many things :
data class GetUserContext(
val getUserImageContext: GetUserImageContext,
val getUserImage: GetUserImage,
// keeps on going based on the functions needed for building the final object
)
...
// I need both the context object and the alias object to be able to get the final value I want
val image = getUserImage(getUserImageContext, "/some/path")
I did watch some of the video on youtube talking about this recommended the “Context” approach but they are ~3 years old.
Is there a better way to approach this now?Alvaro Blazquez checa
11/02/2021, 9:50 AMgetResultFromDatabase().tap { result ->
log(result)
}.map { result ->
transformDatabaseResult()
}
colintheshots
11/02/2021, 9:46 PMgetOrNull()
... are there docs of all the functions available somewhere?conner
11/03/2021, 11:35 AMif let Left(err) = myEitherValue { /* do something with err */ }
? basically i want to run a block if myEitherValue
is Left
, and i would like to avoid casting itthan_
11/03/2021, 3:52 PMSemigroup
is not a fun interface
?CLOVIS
11/04/2021, 10:36 AMAlvaro Blazquez checa
11/04/2021, 12:31 PMOvidiu Ionescu
11/04/2021, 8:42 PMMarko Novakovic
11/05/2021, 11:47 AMNathan Bedell
11/06/2021, 2:26 PM@Serializable(with=...)
), serialization of my data class will fail at run-time, instead of warning me at compile-time that my data class is not serializable.
Coming from experience with type-class/trait based approaches to serialization, this is really jarring to me in practice. One of the nice things to me about automatically deriving serializer/deserializers pairs is that it eliminates a whole class of unit/property-based tests I would otherwise have to write to ensure correctness of my program. If there's a possibility my program could crash at run-time because I tried to serialize something that isn't serializable, I still need to write those tests, which can be very tedious/time consuming.
However, when I asked a question and suggested at least allowing for users to "opt-out" of the "interfaces are automatically serializable" approach", I got the response:
"Open polymorphism is a powerful mechanism that is tied to the runtime by its nature, so giving up on compile-time errors is a tradeoff for convenience."
So, I have a couple of questions for the community here:
1. Does anyone understand this design decision, and exactly why this decision from the kotlinx.serialization team is convenient?
2. Is anyone else equally bothered as me from the lack of compile-time type safety in the current implementation of kotlinx.serialization?
For 2, perhaps if there is enough support we could open a new feature request specifically asking to be able to opt out of automatic interface serialization at run-time.
If the Kotlin team holds to their grounds, there's always the possibility that someone could make a fork, or a more properly type-class based approach, but I'd like to avoid that if possible. Less fragmentation is good!niltsiar
11/11/2021, 8:19 AMEither
source code and out of curiosity I was wondering why functions like map
, fold
, tap
... are member functions while flatMap
, getOrElse
and some other are extension functions.thanh
11/11/2021, 4:13 PMpublic fun <A> listPredicate(p: (A) -> Boolean): Optional<List<A>, A> = Optional(
getOption = { it.firstOrNull(p).toOption() },
set = { list, newHead ->
val index = list.indexOfFirst(p)
if (index != -1) list.take(index) + newHead + list.drop(index + 1) else list
}
)
jean
11/11/2021, 7:45 PMsuspend fun <T> getListWrapperFromDbAnApi(
getFromDb: suspend () -> Either<InOrderError, ListWrapper<T>>,
shouldUpdate: (List<T>) -> Boolean,
getFromApi: suspend () -> Either<InOrderError, ListWrapper<T>>,
saveDataFromApi: suspend (List<T>) -> Either<InOrderError, Unit>
) = flow {
getFromDb().fold(
{ emit(Either.Left(it)) },
{ dbData ->
emit(Either.Right(dbData))
if (shouldUpdate(dbData.items)) {
getFromApi().fold(
{ emit(Either.Left(it)) },
{ apiData ->
if (dbData != apiData) {
emit(Either.Right(apiData))
saveDataFromApi(apiData.items)
}
}
)
}
}
)
}
I don’t think I can use either.eager
due to the nested suspend function error Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope
SecretX
11/14/2021, 7:30 PMOption.applicative()
went with release 1.0? What should I use instead? I'm looking for a way to compose these three Option
into an object, or null
otherwise:
// example of expected input for string: "10 -55 99"
private fun parseLocation(string: String, dungeonName: String): Location? {
val args = string.split(' ', limit = 3)
if (args.size != 3) {
logger.warning("Invalid location '$string' for dungeon '$dungeonName', skipping this location for now")
return null
}
val x = args[0].toIntOrNull().toOption()
val y = args[1].toIntOrNull().toOption()
val z = args[2].toIntOrNull().toOption()
// use x y and z to create a location
}
HieiJ
11/15/2021, 9:01 PMval str1 = "hello".toOption().right()
val str2 = "world".toOption().right()
val output: Either<Any, Option<String>> = either {
option {
val value1 = str1.bind().bind()
val value2 = str2.bind().bind()
value1 + value2
}
}
I'm wondering if there is any "generic" way compose in order to obtain (for this example) an eitherOption { }
block where I can call .bind()
just one time. I know that Option and Either nested like this are not so useful, this is just for having a simple example 😃Milse113
11/16/2021, 1:28 AMplugins {
kotlin("jvm") version "1.5.0"
java
id("io.arrow-kt.refined-types") version "1.0.1"
}
buildscript {
repositories {
mavenCentral()
maven(url = "<https://oss.sonatype.org/content/repositories/snapshots/>")
}
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
implementation("io.arrow-kt:arrow-meta:1.0.1")
implementation("io.arrow-kt:arrow-refined-types:1.0.1")
implementation("io.arrow-kt:arrow-core:1.0.1")
...
}
Peter
11/17/2021, 3:33 AMNorbi
11/17/2021, 10:35 AMIvan Lorenz
11/18/2021, 1:52 PMArrow
and playing today with Validated
. As a learning exercise to explain myself and others if Validated is an Applicative
I am checking wether it satisfies Functor and Applicative laws. I am doing that verification using Kotest
using a specific instance of Validated<Nothing, String?>
- so really only formally checking those laws against that specific Type. I got stuck at verifying Interchange
and Composition
law for Applicative
and finally came up with this try for both:
"Validated applicative must satisfy interchange law" {
checkAll(genNullableString) { a ->
val f = { b: String? -> "PRE-APPENDED${b}" }
val validatedF1 = Validated.lift<Nothing, String?, String?>(f)
val validatedF2 = Validated.lift<Nothing, (String?) -> String?, String?> { f -> f(a) }
validatedF1(a.valid()) shouldBe validatedF2(f.valid())
}
}
"Validated applicative must satisfy composition law" {
checkAll(genNullableString) { a ->
val f = { b: String? -> "PRE-APPENDED${b}" }
val g = { b: String? -> "${b}POST-APPENDED" }
val validatedF1 = Validated.lift<Nothing, String?, String?>(f)
val validatedF2 = Validated.lift<Nothing, String?, String?>(g)
(validatedF2.compose(validatedF1))(a.valid()) shouldBe validatedF1(validatedF2(a.valid()))
}
}
I am not sure if I have been able to replicated in Kotlin
and Kotest
what in Haskell would have been:
• u <*> pure y *=* pure ($ y) <*> u
for Interchange law and,
• pure (.) <*> u <*> v <*> w *=* u <*> (v <*> w)
for Composition law
Are the above Kotest tests really checking what Interchange and Composition laws are for Applicatives? Or I am completely lost? Thank you very much for bringing Arrow
to us.mbonnin
11/18/2021, 3:17 PM// How do I do this with Optics?
val user = user.copy(
address = user.address.copy(
city = newCity
)
)
Ties
11/18/2021, 4:01 PMAlvaro Blazquez checa
11/19/2021, 7:31 AMval result:Try<T> = Try.applicative().tupled()
Alvaro Blazquez checa
11/19/2021, 1:40 PMarrow.core.andThen
in 1.0??Alvaro Blazquez checa
11/19/2021, 1:40 PMarrow.core.andThen
in 1.0??simon.vergauwen
11/19/2021, 1:41 PMAlvaro Blazquez checa
11/19/2021, 1:42 PMsimon.vergauwen
11/19/2021, 1:42 PMAlvaro Blazquez checa
11/19/2021, 1:42 PMsimon.vergauwen
11/19/2021, 8:45 PMandThen
and you no longer need to keep AndThen
aroundtypealias AndThen<A> = () -> A
to replace itAlvaro Blazquez checa
11/19/2021, 8:52 PMval a: MyClass.() -> Try<T> = createFunction().andThen()
infix fun <A, B, C> ((A) -> B).andThen(g: (B) -> C): (A) -> C
public expect infix fun <P1, IP, R> ((P1) -> IP).andThen(f: (IP) -> R): (P1) -> R
val a: () -> String = { " 2323" }.andThen { s -> s }
val b: Myclass.() -> String = { " 2323" }.andThen { s -> s }
simon.vergauwen
11/21/2021, 11:39 AMsuspend
variants of those functions maybe? If you’re interested feel free to create a issue/PR 😉Alvaro Blazquez checa
11/23/2021, 9:05 AM