Dhall is amazing when it comes to getting and setting fields of nested records. However, when those fields are wrapped into some types (e.g. Optional), then you need to use more verbose standard functions to extract relevant fields.
To address this ergonomic problem, I propose to add the optional chaining operator ?. for accessing nested optional fields, similar to other languages, e.g. Kotlin.
Note: I do understand that this doesn't address the more general problem of having other wrapper nested types such as lists, maps, etc. But I believe that Optional is a very popular use-case, and improving ergonomics only for this special data type would already be a huge productivity boost.
Real-life use case
I'm working with Dhall bindings to the OpenShift API, produced by the great dhall-openapi tool. And the generated types contain a lot of options. Specifically, one example from our code base:
target.dhall
{ metadata : API.ObjectMeta.Type
, spec : Optional API.PodTemplateSpec.Type
}
PodTemplateSpec.dhall
{ metadata : Optional ./io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.dhall
, spec : Optional ./io.k8s.api.core.v1.PodSpec.dhall
}
ObjectMeta.dhall
{ labels : Optional (List { mapKey : Text, mapValue : Text })
, ...
}
I want to extract labels from the spec field of the target.dhall type. My current code looks like this:
let selector =
Prelude.Optional.concatMap
API.PodTemplateSpec.Type
(List { mapKey : Text, mapValue : Text })
( λ(podSpec : API.PodTemplateSpec.Type) →
Prelude.Optional.concatMap
API.ObjectMeta.Type
(List { mapKey : Text, mapValue : Text })
(λ(metadata : API.ObjectMeta.Type) → metadata.labels)
podSpec.metadata
)
params.target.spec
With the optional ?. chaining operator it becomes:
let selector = params.target.spec?.metadata?.labels
Proposed change
Introduce the optional chaining ?. operator for getting fields of nested Optional fields inside records.
Semantics:
- Priority is the same as for ordinary
., so they can be mixed together.
- The parenthesis in my example above:
(((params.target).spec)?.metadata)?.labels
- When at least one of the fields in the chain is
None, the result will be None. Otherwise, return Some with the value of the last field specified
The ?. operator can be a syntax sugar for Optional.concatMap, but that's implementation details.
Dhall is amazing when it comes to getting and setting fields of nested records. However, when those fields are wrapped into some types (e.g.
Optional), then you need to use more verbose standard functions to extract relevant fields.To address this ergonomic problem, I propose to add the optional chaining operator
?.for accessing nested optional fields, similar to other languages, e.g. Kotlin.Real-life use case
I'm working with Dhall bindings to the OpenShift API, produced by the great
dhall-openapitool. And the generated types contain a lot of options. Specifically, one example from our code base:target.dhall{ metadata : API.ObjectMeta.Type , spec : Optional API.PodTemplateSpec.Type }PodTemplateSpec.dhall{ metadata : Optional ./io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.dhall , spec : Optional ./io.k8s.api.core.v1.PodSpec.dhall }ObjectMeta.dhall{ labels : Optional (List { mapKey : Text, mapValue : Text }) , ... }I want to extract
labelsfrom thespecfield of thetarget.dhalltype. My current code looks like this:With the optional
?.chaining operator it becomes:Proposed change
Introduce the optional chaining
?.operator for getting fields of nestedOptionalfields inside records.Semantics:
., so they can be mixed together.(((params.target).spec)?.metadata)?.labelsNone, the result will beNone. Otherwise, returnSomewith the value of the last field specifiedThe
?.operator can be a syntax sugar forOptional.concatMap, but that's implementation details.