pablisco
01/18/2021, 6:25 PMsealed class Input<A> {
object ForInt : Input<Int>()
object ForString : Input<String>()
object ForDouble : Input<Double>()
}
fun <A> process(input: Input<A>): A = when(input) {
ForInt -> fetchInt() // returns Int
ForString -> fetchString() // returns String
ForDouble -> fetchDouble() // returns Double
}
This won’t compile, despite being correct.
One way to solve it is like this:
@Suppress("UNCHECKED_CAST")
fun <A> process(input: Input<A>): A = when(input) {
ForInt -> fetchInt() // returns Int
ForString -> fetchString() // returns String
ForDouble -> fetchDouble() // returns Double
} as A
The problem with this is that now we get rid of all type safety since we can return any values, which can result on fun runtime errors.
We have all the information there, so I think the compiler should be able to infer the type from the input and the case and tell us if we are returning the right type or not :)
Is there any plan to support auto cast on the result of a when clause like this? If not, I’ll happily create a KEEP for it.pablisco
01/19/2021, 10:48 AMlouiscad
01/19/2021, 5:49 PMpablisco
01/19/2021, 6:23 PMwhen
clauses and it would be a specialisation of when for sealed classes or interfaces.louiscad
01/19/2021, 6:46 PMpablisco
01/19/2021, 7:40 PMlouiscad
01/19/2021, 7:48 PMHans Ellegard
01/20/2021, 12:06 PMwhen
expression seems troublesome. to check its validity, it won't be enough to let it be an anonymous union type (currently it's the least upper bound of the types of the cases - Any
in the example), but it must be the exact type introduced by the type parameter, A
. while having the type A
, the expression must harbour branches of types different from A
, for a particular A
. i guess requiring the code to be inlined would make it a bit easier, as the unused branches could be removed, simplifying the type of the when
expression, but i don't know if that's the Kotlin way (it feels quite C++-ish to me... not that i don't like C++): other Kotlin generics don't work this way.pablisco
01/20/2021, 2:45 PMfun ForInt.process(): Int = fetchInt()
fun ForString.process(): String = fetchString()
fun ForDouble.process(): Double = fetchDouble()
This works, but doesn’t work if we want to have composition of functions. at least not as transparentlyraulraja
01/21/2021, 11:16 AMraulraja
01/21/2021, 11:19 AMraulraja
01/21/2021, 11:21 AMresult as A
because Kotlin does not consider unifying the branches of A
in an exhaustive match.