I define two objects:
data class ParserK
annotated with @higherkind
interface ParserKFunctor
annotated with @extension
Here is the code:
@higherkind
data class ParserK<A>(val f: (String) -> Option<A>): ParserKOf<A> {
companion object
}
@extension
interface ParserKFunctor : Functor<ForParserK> {
override fun <A, B> Kind<ForParserK, A>.map(f: (A) -> B): Kind<ForParserK, B> {
...
}
}
When I execute ./gradlew :app:kaptKotlin
I get:
error: "Arrow's annotations can only be used on Kotlin classes". Not valid for error.NonExistentClass
> Task :app:kaptGenerateStubsKotlin
> Task :app:kaptKotlin FAILED
e: error: Arrow's annotations can only be used on Kotlin classes. Not valid for error.NonExistentClass
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:kaptKotlin'.
> Compilation error. See log for more details
Here is what I discovered:
@higherkind
from the data class ParserK
and copy the generated sources into the same file where ParserK
is defined then I can see the generated code for the functor.It seems like a bug for me, correct me if I am wrong, please
UPDATED:
(For arrow-version 0.9.1-SNAPSHOT and prior)
The Higherkinded Processor and Extension Processors have a dependency. Correctly, the extension annotation depends on the code generated by the higherkinded annotation. Why check this link.
The brief summary is, whenever you try implementing typeclasses the compiler needs the Higherkinded Types of your datatype.
@extension
interface ListKFunctor : Functor<ForListK> {
// ^^^^^^^^
// This exists after building your module
override fun <A, B> Kind<ForListK, A>.map(f: (A) -> B): Kind<ForListK, B> {
return this.fix().map(f)
}
}
The simplest answer to this question is:
Always separate your Higherkinded Types from your typeclass definitions.
But Arrow is experimenting with other options on Codegen. Meaning in future releases this problem will be solved.