https://kotlinlang.org logo
#arrow-contributors
Title
# arrow-contributors
d

dnowak

03/06/2020, 3:05 PM
Hi, is somewhere available the documentation for 0.11.0?
a

aballano

03/06/2020, 3:06 PM
Hi there! Not yet, that’s still under construction + we only target the next version, which will be 0.10.5
s

simon.vergauwen

03/06/2020, 3:13 PM
@dnowak any specific questions on 0.11.0? The only difference you’ll find there compared to
0.10.5
at this point is
IO<E, A>
.
d

dnowak

03/06/2020, 3:18 PM
IO<E, A>
is the reason I wanted to play with 0.11.
s

simon.vergauwen

03/06/2020, 3:19 PM
The API of
IO<E, A>
did not change a lot compared to
IO<A>
. What’ll find is you’ll have
IO.raiseError
and
IO.raiseException
, and additional error handlers to deal with them.
👍 1
d

dnowak

03/06/2020, 3:19 PM
I wanted to use monad comprehension but got error on
IO.fx {
- compiler has two candidate functions and does not know which one to choose. So I wanted to refer to documentation…
s

simon.vergauwen

03/06/2020, 3:19 PM
We’re currently on the verge of releasing
0.10.5
and the work on the docs and finalizing the API will follow.
@dnowak yes that’s the biggest issue we’re still dealing with.
Nothing
is quite pervasive throught the codebase
IO.fx<Nothing, Int>
or
IO.fx<DomainError, Int>
is what you’re looking for
d

dnowak

03/06/2020, 3:22 PM
This works - but looks strange as I have to repeat the types in result type and then in fx call:
Copy code
fun crate(command: CreateLedgerCommand): IO<CreateError, Unit> = IO.fx<CreateError, Unit> {
s

simon.vergauwen

03/06/2020, 3:23 PM
Yes, sadly Kotlin cannot infer that. At least I don’t know a solution that could help the Kotlin compiler infer those types.
a

aballano

03/06/2020, 3:23 PM
there’s a ticket for that, so that’s something we definitely want to try to fix
s

simon.vergauwen

03/06/2020, 3:24 PM
Kotlin should be able to infer multiple type args, no? 🤔
a

aballano

03/06/2020, 3:24 PM
yes, but only if you provide it somewhere within the params
s

simon.vergauwen

03/06/2020, 3:24 PM
val program = IO<CreateError, Unit> = IO.fx<CreateError, Unit>
should be inferable, no?
a

aballano

03/06/2020, 3:24 PM
the problem here is that the error might not be there, but I bet we can hack it somehow 😄
yes
d

dnowak

03/06/2020, 3:25 PM
OK, and what about this:
Copy code
val (ledger)  = getLedger(command.ledgerId)
I get error that there is no component1 function
a

aballano

03/06/2020, 3:25 PM
it was deprecated on 0.10.5, maybe removed there
1
you should better use ! or .bind()
until arrow meta is out and we will be able to improve that 😉
s

simon.vergauwen

03/06/2020, 3:26 PM
I think it’s because there is a
fun <A> IO.Companion.fx
overload which fixes to
Nothing
. Maybe you need disambiguate because of that.
d

dnowak

03/06/2020, 3:26 PM
OK, I actualy liked very much the destruring call :-(
s

simon.vergauwen

03/06/2020, 3:26 PM
Yes, same here 😞 But there is a problem since Kotlin doesn’t support nested destructuring
So you cannot do
val ((a, b, c, d)) = parTupled(fa, fb, fc, fd)
a

aballano

03/06/2020, 3:27 PM
that + ops not executed if you ignore the variable name with
_
😄
val (_) = IO { … }
because of kotlin optimization
s

simon.vergauwen

03/06/2020, 3:28 PM
Wait what!? really?
That sounds like a horribly dangerous optimisation 😮
a

aballano

03/06/2020, 3:29 PM
well, depends on the point of view I guess… one could argue that destructuring a class, the same way as accessing a variable shouldn’t trigger a side effect, therefore… 🧌
d

dnowak

03/06/2020, 3:29 PM
Is there a new module? IDEA is not able to find
.bind()
a

aballano

03/06/2020, 3:30 PM
@dnowak can you share some of the code? at least the fx block
r

raulraja

03/06/2020, 3:34 PM
destructuring also is broken for data types like List which destructuring with componentN is not the same as monad bind
d

dnowak

03/06/2020, 3:36 PM
I just started with this:
Copy code
fun crate(command: CreateLedgerCommand): IO<CreateError, Unit> = IO.fx<CreateError, Unit> {
    val ledger  = getLedger(command.ledgerId).bind()
}
s

simon.vergauwen

03/06/2020, 3:37 PM
What is the return type of
getLedger
?
d

dnowak

03/06/2020, 3:37 PM
Copy code
typealias GetLedger = (LedgerId) -> IO<RepositoryError, Ledger>

typealias StoreEvents = (List<Any>) -> IO<EventStoreError, Unit>
I wanted to switch to 0.11.0 as we our current system is based on
IO<Either<E, A>>
. I hoped that Bi IO will let me get rid of EitherT , which was needed to map errors.
s

simon.vergauwen

03/06/2020, 3:40 PM
Yes, it will allow you to get rid of
EitherT
I wouldn’t recommend using it just yet, unless you’re just curious to play with the API. In 3-4 weeks I expect the API to be more stable, and the docs to be more up to date since we’ll be actively working on that release then.
d

dnowak

03/06/2020, 3:42 PM
Ok, I’m going back to IO<Either>>
s

simon.vergauwen

03/06/2020, 3:42 PM
You cannot bind the error
RepositoryError
to
CreateError
unless you map the error using something like
flatMapLeft
,
fallbackWith
,
handleErrorWith
or another error handler.
Or you’d have to define your error domain as.
Copy code
sealed class CreateError {
   sealed class RepositoryError : CreateError {
      //...
   }

   sealed class EventStoreError : CreateError {
      //...
   }
}
Then you should be able to bind
RepositoryError
within
IO.fx<CreateError, A>
There is no way for
fx
to go from
RepositoryError
to
CreateError
otherwise and it doesn’t know how to
flatMap
.
d

dnowak

03/06/2020, 3:50 PM
OK, the error that I have is:
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public abstract suspend fun <A> Kind<IOPartialOf<CreateError> /* = Kind<ForIO, CreateError> */, TypeVariable(A)>.bind(): TypeVariable(A) defined in arrow.fx.extensions.IOSyntax
s

simon.vergauwen

03/06/2020, 3:51 PM
Yes, it’s saying it expects
CreateError
and you’re trying to bind
RepositoryError
which is a compilation error since the domain errors don’t align
If you rewrite to
flatMap
you’ll see that it’s unrelated to
bind
or
fx
.
d

dnowak

03/06/2020, 3:52 PM
Sorry, my fault
s

simon.vergauwen

03/06/2020, 3:52 PM
No problem! 🙂 All questions and feedback on
IO<E, A>
is very welcome since we’re still polishing the final API
So if you continue playing with it and have some feedback I’d love to hear it!
d

dnowak

03/06/2020, 3:54 PM
I would like to request
.mapLeft
function 🙂. Simple error mapping would be easier to read:
Copy code
.flatMapLeft { e -> IO.raiseError(CreateError.Unexpected("error")) }
👌 1
s

simon.vergauwen

03/06/2020, 3:55 PM
Noted! that will be for sure added 🙂
d

dnowak

03/06/2020, 3:56 PM
Thank you
j

Jannis

03/06/2020, 3:58 PM
Doesn't
handleErrorWith
do that? Or ist that fixed to the same
E
? Probably wouldn't hurt inference to allow it to return a different
E
Although the
MonadError
-instance would then end up having different behavior so using a different operator name might be better
s

simon.vergauwen

03/06/2020, 4:14 PM
handleErrorWith
covers
E
and
Throwable
a

aballano

03/06/2020, 4:48 PM
don’t we have a differentiation on handleError and handleException in this sense? although handleException might better be a left map of some sort 🤔
s

simon.vergauwen

03/06/2020, 5:01 PM
Probably best to compile a list of all names and signatures when we start working actively on `IO<E, A>`’s final API
👍 2
2 Views