Lately, I stumbled upon a use-case for higher kinded function types. Simplified setting is as follows: A framework offers these interfaces and also instances of those.
interface Box<T> {
var data: T
}
interface BoolBox : Box<Boolean>
interface IntBox : Box<Int>
The application code:
fun <T> doSomething(box: Box<T>, t: T) {
box.data = t
}
fun m(box: Box<*>) {
when (box) {
is BoolBox -> doSomething(box, true)
is IntBox -> doSomething(box, 8)
}
}
Now we also want to execute different implementations of doSomething
but we do not want to repeat the when
code all the time. So we introduce a helper function.
fun switch(
box: Box<*>,
code: ???
) {
when (box) {
is BoolBox -> code(box, true)
is IntBox -> code(box, 8)
}
}
code
should be of some function type but which one fits here? Box
is invariant, so (Box<Any>, Any) -> Unit
does not work. What we would need here is something like (Box<T>, T) -> Unit
where T
is a free type variable, making the type expression into a higher kinded type. But this is not directly supported by Kotlin. One has to fall back to non-functional interfaces:
interface BoxCode {
operator fun <T> invoke(box: Box<T>, t: T)
}
fun switch(
box: Box<*>,
code: BoxCode
) {
when (box) {
is BoolBox -> code(box, true)
is IntBox -> code(box, 8)
}
}
fun usage(box: Box<*>) {
switch(box, object : BoxCode {
override fun <T> invoke(box: Box<T>, t: T) {
doSomething(box, t)
}
})
}
For all the usage
s, we have to use the clunky anonymous object declarations. Do you see more concise alternative solutions for the problem?