that looks okay to me, it’s `io.map { ei -> ei....
# arrow
p
that looks okay to me, it’s
io.map { ei -> ei.map { l -> l.map { b -> toC(b) } } }
j
This produces
IO<Either<A, List<Either<A, C>>>>
, instead of
IO<Either<A, List<C>>
. 😵 Still having a hard time going from the first to the latter.
p
toC
returns Either then?
j
Yeah,
Either<A, C>
. Also see second function in the initial snippet.
p
ei.flatMap { l -> l.map { b -> toC(b) }.sequence(Either.applicative<A>()) }
y
Thanks, guys, you're a blessing to have around. Also,
flatMap
is life.
❤️ 1
j
I’m still puzzled about this. Probably because my toC function is suspended. I’m making a thinking error, but can’t figure out where.
p
ooooh
more and more layers to it 😄
so you have a
IO<Either<String, List<A>>
and you want to apply a suspend function to it
so you have to propagate everything…it’s not an easy problem
the way of doing it is having
IO<Either<String, List<IO<B>>>
and then into IO<Either<String, IO<List<B>>> And then IO<IO<Either<String, List<A>>> and finally you can flatten that
Copy code
IO.fx {
  val eit: Either<String, List<A>> = io.bind()
  val eit2: Either<String, IO<List<B>>> = 
    ei.map { l -> l.map { b -> toC(b) }.sequence(IO.applicative()) }
  val eit3: Either<String, List<B>> = 
    eit2.sequence(IO.applicative()).bind()
}
so tl;dr two
.sequence(IO.applicative())
j
it’s not an easy problem The alternative could be to rewrite the toC (or in my scenario the
fun Candidate.toViewModel()
) function. Because maybe it doesn’t need to be complicated. 😅 But will try with
.sequence(IO.applicative())
now and see if I can get past this not an easy problem. 🙂
toC(b)
in the snippet you posted can’t be invoked without a coroutine scope.
IO.fx { !effect { toC(b) } }
This does make it possible to invoke
toC(b)
. But then the
.sequence(IO.applicative())
isn’t happy. 😵
p
right, right, one sec
l.map { b -> IO.effect { toC(b) } }
I forgot that
what does the sequence complain about?
also, the first or the second one?
j
The first sequence.
p
.fix()
after sequence inside the map
and then
map { it.fix() }
and there's one layer of either to unpack
xD
okay, so you know the APIs: map and sequence
between the both of them it has to work
if you ever get a kind<ForX, A> just use
fix
on it
and the rest is type tetris playtime 😄
r
no more fixing soon 🤞
j
Nailed it. (Maybe it can use some minor revisions.) Anyways, thanks for the help. And two followup questions. What is the difference between
IO.fx { !effect { ... } }
and
IO.effect { ... }
? Is there another way to go from
Kind<ForListK, C>
to
List<C>
than
it.fix() as List<C>
(without casting)?
p
What is the difference between
IO.fx { !effect { ... } }
and
IO.effect { ... }
?
The first one goes through extra hoops to get the same result
Maybe it can use some minor revisions
I’m sure you can get away with a couple fewer fixes. Still, you won the game of type tetris 😄
it.fix() as List<C>
looks incorrect, is my only concern
what’s
it
here?
eit445.map { it.flatten() }
is just
flatMap { it }
, hence the name 😄
j
it
in
it.fix() as List<C>
is a `Kind<ForListK, C>. To me, that looked also not correct. 😅 That is why I asked the question if there is another way to do this transformation.
Still, you won the game of type tetris 😄
I slept like a rock! 🥇😴
p
it.value()
instead of
it.fix().value
IIRC
although you’re right, ListK is a List via delegation
we had a discussion about whether a type hint or a cast was the correct approach
I prefer hint
Copy code
val a: List<C> = it.fix()
a
j
👍