I’m having an issue/confusion with `fix()` . I tho...
# arrow
k
I’m having an issue/confusion with
fix()
. I thought it converted
Kind<F, A>
into
F<A>
, where (for example)
F
is
Option
. But then I have this, and the compiler disagrees that my type is correct:
Copy code
import arrow.core.Either
import arrow.core.Option
import arrow.core.extensions.option.traverse.traverse
import arrow.core.k
import <http://arrow.fx.IO|arrow.fx.IO>
import arrow.fx.extensions.fx
import <http://arrow.fx.extensions.io|arrow.fx.extensions.io>.applicative.applicative
import arrow.fx.fix
import <http://java.io|java.io>.File

interface MediaId
interface Entity
interface Foo { val source: Option<File> }
val pathArgs: Foo = TODO()
fun bar(x: String): IO<Sequence<File>> = TODO()
fun transform(it: File): Entity = TODO()
fun baz(x: Entity): IO<Either<Throwable, MediaId>> = TODO()


val result: IO<Option<Sequence<Either<Throwable, MediaId>>>> = pathArgs.source.traverse(IO.applicative()) {
    IO.fx {
        val files = bar(it.canonicalPath).bind()
        files.k().traverse(IO.applicative()) {
            val entity = transform(it)
            baz(entity)
        }.fix().bind()
    }
}.fix() // IO<Kind<ForOption, SequenceK<Either<Throwable, MediaId>>>> ???
The
fix()
at the end does turn it from
Kind<IO, …>
into
IO<…
but why doesn’t the
fix()
tagged onto the internal
traverse
not turn the
Kind<ForOption, SequenceK
into
Option<SequenceK>
?
j
That is because
traverse
is defined to return
Kind<F, Kind<G, A>>
and for your types that is
Kind<ForIO, Kind<ForOption, A>>
.
fix
only ever deals with the outer layer, so you only get
IO<Kind<ForOption, A>>
. This sucks but there is no good way to have
traverse
return a value which has the inner
Kind
fixed already. To deal with this you can either change your expected type to
IO<OptionOf<A>> = IO<Kind<ForOption, A>>
or use
map { it.fix() }
for the inner part. Both of these "solutions" suck and I cannot wait for arrow-meta to once and for all end this with the higherkind compiler-plugin...
👍 2