What are "Non-literal" function types?

Q1. Slight confusion with the terms:

In the documentation https://kotlinlang.org/docs/reference/lambdas.html#instantiating-a-function-type

Non-literal values of function types with and without receiver are interchangeable, so that the receiver can stand in for the first parameter, and vice versa. For instance, a value of type (A, B) -> C can be passed or assigned where a A.(B) -> C is expected and the other way around:

val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
val twoParameters: (String, Int) -> String = repeatFun // OK

fun runTransformation(f: (String, Int) -> String): String {
    return f("hello", 3)
val result = runTransformation(repeatFun) // OK

In the code, are repeatFun and twoParameters “non-literal” function types?
What is the definition of “Non-literal” function types?
From my understanding,
function literals are either lambda expressions or anonymous functions.

Therefore I thought “non-literal” function types would be function types which are neither lambda expression nor anonymous function.

In the code

val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }

{ times -> this.repeat(times) } this is a lambda expression, which is a function literal.

What am I missing here?

Should I understand this differently, so that
{ times -> this.repeat(times) } is a function literal,
but repeatFun or twoParameters are “non-literal”?

More below in the documentation it’s stated

Note that a function type with no receiver is inferred by default, even if a variable is initialized with a reference to an extension function. To alter that, specify the variable type explicitly.

I couldn’t understand this statement. Could someone please give an example or elaborate it?

I don’t have a great explanation for this, but function types with receivers can be called and used as if the receiver is instead the first argument. E.g. you can call repeatFun two different ways:

repeatFun("string", 5)

And the concept of non-literal types is just describing this behavior


val a: String.(Int) -> Unit = { i -> ... }
val b1 = a // type is (String, Int) -> Unit
val b2: String.(Int) -> Unit = a

"string".b1(5) // error, since b isn't an extension function
"string".b2(5) // works fine

I did understand this point. But I didn’t really get what the term “non-literal” meant.

Now I understand it. Thanks for the example.

I think “non-literal” here simply means “not written literally in code”. For example, 42 is an integer literal, but x initialized with 42 is not a literal, but a variable of integer type. Same for functional types.


Thank you for the clarification!