Description
ADTs are a very important part of any modern programming language.
- Kotlin has sealed classes
- Swift has enums with associated values
Imagine you have a network call that submits login credentials. This call can:
- log the user in
- fail because the user entered incorrect wrong credentials
- fail because the user doesn't have network connectivity
- fail because of an unknown defect in your code or server broke API contract and the call failed
In Kotlin, the return value could be represented as the following sealed class
sealed class LoginResponse {
data class Success(val authToken) : LoginResponse()
object InvalidCredentials : LoginResponse()
object NoNetwork : LoginResponse()
data class UnexpectedException(val exception: Exception) : LoginResponse()
}
Kotlin's when
statement unwraps this beautifully, smart casting LoginResponse
.
fun on(loginResponse: LoginResponse) {
return when (loginResponse) {
is LoginResponse.Success -> {
// direct access to auth token available w/o need to cast
loginResponse.authToken
}
is LoginResponse.InvalidCredentials -> {
}
is LoginResponse.NoNetwork -> {
}
is LoginResponse.Unexpected -> {
// direct access to exception available w/o need to cast
loginResponse.exception
}
}
}
Sadly, languages like Java and Dart are unable to elegantly express this concept (ADTs). For a best case example, checkout out Retrofit's Response
object. It is a single pojo that contains both:
- The success
.body()
- The
.errorBody()
Both these fields are nullable, but one must be non-null and the other must be null. To know which field can be accessed, you have to check the .isSuccessful()
flag.
Now imagine the verbosity if this best case scenario has to scale to 4 or more possible results. A whole new enum class would have to be added to work around it...it's not pretty.
Please add support for ADTs to Dart.
note: As an Android developer, I find that Flutter is an interesting proposition that is currently held back by the language.