y
04/23/2024, 9:04 PMfun <T> identity(t: T): T = t
fun <T, E> Iterable<T>.allSameValue(f : (T) -> E = ::identity) : E? { /* ... */ }
I'm getting Required: T, Found E
for the default value on the parameter. why? what's wrong with E = T
?Gleb Minaev
04/23/2024, 9:08 PMT = E
, everything is OK. But compiler says, "What if E != T
? Then ::identity
function does not fit the type (T) -> E
."Gleb Minaev
04/23/2024, 9:10 PMfun main() {
listOf(1, 2, 3).allSameValue<Int, String>()
}
y
04/23/2024, 9:10 PMPaul Griffith
04/23/2024, 9:10 PMidentity
you have to make an explicit unsafe casty
04/23/2024, 9:11 PME
and then ::identity
doesn't agree with the requirement of returning E
Szymon Jeziorski
04/24/2024, 6:48 AMT
must be a subtype of E
:
fun <T : E, E> Iterable<T>.allSameValue(f: (T) -> E = ::identity): E?
With such signature identity
function would always fit into generics bound, and mapping function could be used with its result matching supertypes of T.
Example:
val l = listOf(123)
val x: Number? = l.allSameValue { it.toDouble() }
y
04/24/2024, 1:21 PMfun <T> Iterable<T>.allSameValue(): T? = allSameValue { it }
Szymon Jeziorski
04/24/2024, 1:50 PMT : E
and not not passing any arguments would achieve basically the same, since from the default value of of f
being identity
function, E
would just be inferred as T
, since indentity
takes and returns same generic type:
val l = listOf(1, 2, 3)
val x = l.allSameValue() // inferred as Int?
val z = l.allSameValue<_, Number>() // inferred as Number? because of explicit generics type declaration