Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inferring only some type parameters in Kotlin

Tags:

kotlin

I have a method with two type parameters, only one of which can be inferred from arguments, something like (no need to comment this cast is evil, the body is purely for the sake of example)

fun <A, B> foo(x: Any, y: A.() -> B) = (x as A).y()

// at call site
foo<String, Int>("1", { toInt() })

However, the compiler can tell B is Int if A is String. And more generally, if it knows A, B can be inferred.

Is there a way to only provide A at the call site and infer B?

Of course, the standard Scala approach works:

class <A> Foo() {
    fun <B> apply(x: Any, y: A.() -> B) = ...
}

// at call site
Foo<String>().apply("1", { toInt() })

I was interested in whether Kotlin has a more direct solution.

like image 642
Alexey Romanov Avatar asked Sep 25 '17 09:09

Alexey Romanov


1 Answers

Based on this issue/proposal, I'd say no(t yet):

Hello, I am proposing two new feature for kotlin which go hand in hand: partial type parameter list and default type parameters :) Which in essence allows to do something as the following:

    data class Test<out T>(val value: T)

    inline fun <T: Any, reified TSub: T> Test<T>.narrow(): Test<TSub>{
        return if(value is TSub) Test(value as TSub) else throw ClassCastException("...")
    }

    fun foo() {
        val i: Any = 1
        Test(i).narrow<_, Int>() // the _ means let Kotlin infer the first type parameter
        // Today I need to repeat the obvious:
        Test(i).narrow<Any, Int>()
    } 

It would be even nicer, if we can define something like:

    inline fun <default T: Any, reified TSub: T> Test<T>.narrow(): Test<TSub>{
        return if(value is TSub) Test(value as TSub) else throw ClassCastException("...")
    } 

And then don't even have to write _

    fun foo() {
        val i: Any = 1
        Test(i).narrow<Int>() //default type parameter, let Kotlin infer the first type parameter
    }
like image 194
nhaarman Avatar answered Oct 18 '22 18:10

nhaarman