raulraja
10/01/2017, 10:42 PMinterface Semigroup<A> {
fun combine(a: A, b: A): A
}
Users can define implicit instances for such a type class:
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.
import foo.*
fun add(a: Int, b: Int, implicit SI: Semigroup<Int>): Int = SI.combine(a, b) //compiles
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
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 🙂