Tsvetan Ovedenski
03/17/2020, 1:37 PMdata class Item (val name: String)
sealed class Permission <T> {
object Create : Permission<Unit>()
object Edit : Permission<Item>()
}
fun <T> verify(permission: Permission<T>, item: T): Boolean = when (permission) {
is Create -> true
is Edit -> item.name == "editable" // Unresolved reference: name
}
For some reason I expected that when it's known that T
is Item
(as it is in Edit
), then item
would be properly casted, but I realise that maybe I expected too much. Any idea on how to connect the two (permission
and item
)?Francisco Javier Ruiz Rodriguez
03/17/2020, 1:50 PMfun <T> verify(permission: Permission<T>, item: T): Boolean = when (permission) {
is Permission.Create -> true
is Permission.Edit -> (item as Item).name == "editable" // Unresolved reference: name
}
Tsvetan Ovedenski
03/17/2020, 2:04 PMitem
as Item
in Create
case. Could this be connected with type erasure?
Just for completeness, the same example in Haskell typechecks:
{-# LANGUAGE GADTs #-}
data Item = MkItem { itemName :: String }
data Permission a where
Create :: Permission ()
Edit :: Permission Item
verify :: Permission a -> a -> Bool
verify permission item = case permission of
Create -> True
Edit -> itemName item == "test"
cypher121
03/17/2020, 2:11 PMas
is not a compile-time-checked cast, but a runtime-checked one. You can use it anywhere you want, but it will crash at runtime if it's not a valid castJakub Pi
03/17/2020, 2:31 PMdata class Item (val name: String)
sealed class Permission {
object Create : Permission()
object Edit : Permission()
}
fun verify(permission: Permission, item: Item): Boolean = when (permission) {
Permission.Create -> true
Permission.Edit -> item.name == "editable"
}
Jakub Pi
03/17/2020, 2:32 PMcypher121
03/17/2020, 2:38 PMcypher121
03/17/2020, 2:39 PMTsvetan Ovedenski
03/17/2020, 2:39 PMPermission
and have each permission have a field with the value (so Create
stays object, Edit
is converted to data class).Tsvetan Ovedenski
03/17/2020, 2:40 PMverify
for Permission<Unit>
that passes Unit as second argument.Shawn
03/17/2020, 2:44 PMdata class Item (val name: String)
sealed class Permission<T>(val value: T) {
object Create : Permission<Unit>(Unit)
class Edit(item: Item) : Permission<Item>(item)
}
fun verify(permission: Permission<*>): Boolean = when (permission) {
Permission.Create -> true
is Permission.Edit -> permission.value.name == "editable"
}
Jakub Pi
03/17/2020, 3:57 PMfun <T> verify(permission: Permission<out T>, item : T): Boolean = when (permission) {
Permission.Create -> true
Permission.Edit -> when(item) {
is Item -> item.name == "editable"
else -> false
}
}
The smart cast just can't cope with the relationship between Permission<T> and Item:T, but you can just have an inner when. Notice the out modifier, which allows the following call to compile:
verify(Permission.Create, item)
Tsvetan Ovedenski
03/17/2020, 5:00 PM