Dhall
Programmable configuration language with strong typing
Dhall is a programmable configuration language designed as a strongly typed, total functional language: every program is guaranteed to terminate, imports are content-addressed for reproducibility, and there is no way to perform side…
Definition
Dhall is a programmable configuration language designed as a strongly typed, total functional language: every program is guaranteed to terminate, imports are content-addressed for reproducibility, and there is no way to perform side effects like network calls or arbitrary file reads at evaluation time. It generates plain JSON or YAML output, giving teams the ability to define functions, records, and reusable templates for configuration while keeping the final artifact fully deterministic and safe to evaluate.
Overview
Configuration languages generally sit on a spectrum from purely declarative formats that cannot express reuse, like plain YAML, to fully general scripting languages that can express anything but offer no safety guarantees. Dhall was designed to occupy a narrow, deliberate middle point: a language expressive enough to define functions and abstract over repeated configuration patterns, but restricted enough that every program is provably total, meaning it always terminates and never throws an unexpected runtime error once it type-checks. The mechanism that makes this possible is Dhall's foundation in a normalizing lambda calculus with a strong static type system, borrowed conceptually from typed functional languages. Because Dhall lacks general recursion, an evaluator can always reduce a well-typed Dhall expression to a normal form in finite time, which is what termination guarantees actually mean in practice. Imports, whether local files or remote URLs, can be pinned with a cryptographic hash, so a Dhall file can guarantee that a shared library it depends on has not changed since it was last reviewed, addressing a supply-chain concern that plain text-inclusion systems like YAML anchors cannot address at all. Among its neighbors, Dhall is more expressive than CUE's unification model, since Dhall supports genuine functions and higher-order abstraction, but it trades away CUE's flexible, order-independent merging in favor of a conventional evaluate-then-render pipeline. Compared to Starlark, Dhall is stricter about totality and side-effect freedom, and unlike Starlark it was designed from the outset purely as a configuration language rather than as an embeddable scripting layer for a specific host tool like Bazel. Both languages ultimately compile down to a simpler serialization format, but Dhall's output target is explicitly JSON or YAML rather than an internal build graph. In practice, teams use Dhall to define shared configuration templates once and instantiate them across multiple environments or services, catching type errors, like a missing field or a mismatched port type, before the generated file is ever deployed. It has seen use in infrastructure teams that want the DRY benefits of a programming language for their Kubernetes, Terraform, or CI configuration without inheriting a general-purpose language's ability to fail unpredictably at runtime. The Dhall CLI compiles `.dhall` files down to standard JSON or YAML that downstream tools consume unchanged. The cost of these guarantees is a genuine learning curve: engineers must understand a type system and functional idioms like records-as-modules and function application, which is a bigger ask than editing a YAML file. Dhall's ecosystem and community are also smaller than more mainstream formats, so tooling integrations and editor support can lag behind. For teams with simple, largely static configuration, the overhead of learning Dhall's type system may not be worth it, and a lighter tool such as plain YAML with a JSON Schema validator remains the more pragmatic choice.
Key Features
- Total functional language guarantees every program terminates
- Strong static type system catches configuration errors before deployment
- Content-addressed imports pin remote files by cryptographic hash
- Compiles down to plain JSON or YAML output
- Supports functions and records for reusable configuration templates
- No side effects such as network calls at evaluation time
- Higher-order abstraction not available in unification-based languages
- Explicit focus on configuration rather than general scripting