kyleg
01/15/2020, 1:05 AMfix()
. 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:
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>
?Jannis
01/15/2020, 1:44 AMtraverse
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...