In Kategory we are working on a proposal that demo...
# kontributors
r
In Kategory we are working on a proposal that demonstrates Type Classes in Kotlin. Initially we thought about implementing this with an annotation processor and kapt3 with help from @Eugenio but after inspecting the use cases and seeing what is possible with annotation processors and codegen looks like our solution needs to be in either a compiler plugin or directly in the Kotlin compiler itself. The solution should include reasonable instance lookups for type classes which in other langs is achieved via implicits. This proposal does not attempt to bring to Kotlin full blown implicits like Scala but just global ones that are easier to reason about and look up. The following features would be enabled if Kotlin had support for Type classes: Given a typeclass declaration like the one below
Copy code
interface Semigroup<A> {
  fun combine(a: A, b: A): A
}
Users can define implicit instances for such a type class:
Copy code
package foo
implicit val intSemigroup: Semigroup<Int> = object : Semigroup<Int> {
  fun combine(a: Int, b: Int): Int = a + b
}
These implicit instances are automatically injected by the compiler where requested both in generic and concrete call sites.
Copy code
import foo.*

fun add(a: Int, b: Int, implicit SI: Semigroup<Int>): Int = SI.combine(a, b) //compiles
Copy code
import foo.*

fun <A> add(a: A, b: A, implicit SI: Semigroup<A>): A = SI.combine(a, b) //compiles

add(1, 2) //compiles

add("a", "b") //fails to compile: No `Semigroup<String>` found implicitly
Implicits can also be expressed as functions and require other implicits as dependencies
Copy code
implicit fun <A> optionSemigroup(implicit SA: Semigroup<A>): Semigroup<Option<A>> = ...

add(Option(1), Option(2)) //compiles because it can find the `Semigroup<Int>` and therefore the `Semigroup<Option<Int>>`

add(listOf(1), listOf(1)) // fails to compile because there is no implicit `Semigroup<List<A>>`
add(Option("a"), Option("b")) // fails to compile because it can't find a `Semigroup<String>`
Such a feature will enable in Kotlin compile time Dependency Injection and drastically increase performance in places where frameworks based on runtime/reflection DI are in use today. This feature would not suffer for the compilation performance issues that Scala has because there is no scoping involved, just global instances available if imported. My questions are the following: 1. Do compiler plugins support enough hooks for this to be implemented as a plugin? 2. If compilers plugin are not suitable for this proposal what are the relevant source places in the Kotlin compiler where I can start looking at regarding type checking of call sites when applied in generic contexts? 3. Is this of interest to the Kotlin lang designers / community? Kategory has already overcome most of the langs limitation when encoding typed FP in Kotlin but type classes failing at runtime is far from ideal for users and most of the comments and questions we are getting are related to the limitation of using
inline reified
to do the above mentioned features at runtime. Also
inline reified
has many shortcomings, for example they can't be used inside classes and refer to the classes generic arguments since those are not reified. We need a compile time solution and we are determined to find the best one that not only helps Kategory users but also the Kotlin community at large. Any feedback is appreciated and sorry for the long post 🙂