## Configuration should be "Maintainable" π§
This principle is the main reason why we choose to use `dhall`
[Dhall](https://dhall-lang.org/) is a "simple" language and set of tools which allow for the management of configuration.
It focuses on being delightful to maintian, maximizing the productivity and correctness of the user.
It is an excellent choice for small teams trying to do hit ambitious goals with a few knowledgable maintainers
### "Maintainable" means we reuse code efficiently
To facilicate this, `dhall` provides some programming constructs:
- Variables + Strict scoping
- Functions
- Imports
#### Variables + Strict scoping
`dhall` uses the `let` keyword to indicate setting a variable
We want out code to be declarative, so `dhall` forces us to specify where we want a variable to be in scope
An `in` block must _always_ be used to tell `dhall` where and how the variables will be used!
```dhall
let x = 5
in x + 10
```
We can express more complicated variables by using Records and Lists
```dhall
let thisGuyIKnow =
{ person = { name = "Johnnathan Doe", age = 67 }
, nicknames = ["JohnnyBoy", "Johnny-O", "KingJohnVI"]
, address =
{ country = "United States"
, state = "Pennsylvania"
, city = "Philadelphia"
}
}
in "I need to always specify an in block, even if I don't use any of my variables!"
```
yields `"I need to always specify an in block, even if I don't use any of my variables!"`
#### Functions
We often want to reuse the same code snippet to take some inputs and generate some outputs.
We can define functions like this
```dhall
let addThese
: Natural -> Natural -> Natural
= \(x : Natural) -> \(y : Natural) -> x + y
in addThese 10 10
```
yields `20`
You'll notice that functions are very restrictive in what they can do, this is intentional for the sake of safety, a principle which [other configuration specification languages try and adhere to](https://developer.hashicorp.com/terraform/language/expressions/function-calls#when-terraform-calls-functions)!
#### Imports
We want to be able to import code, either from the internet
For example, if I want to import the standard library:
```dhall
let Prelude = (https://prelude.dhall-lang.org/v19.0.0/package.dhall)
```
Or from a local file
For example, if I want to import the file we just made:
```dhall
let addThese = ./placeWhereAddTheseIsDefined.dhall
```
For the security conscious, these can be cached, are referentially transparent, and a SHA can be attached optionally to prevent tampering with the source π¦Ύ
### "Maintiainable" means state is hard to misconfigure
To facilicate this, `dhall` provides some programming constructs:
- Types
- Type Checking
- Clear Error-Messages
#### Types
When we specify a dependency in software, we create an interface. A `type` is how we formalize an interface!
As we did in our above example of specifying variables, here we declare a specific type to assert that our variable conforms to.
```dhall
let Profile : Type
= { person :
{ name : Text
, age : Natural
}
, address :
{ country : Text
, state : Text
, city : Text
}
}
let john : Profile =
{ person =
{ name = "John Doe"
, age = 67
}
, address =
{ country = "United States"
, state = "Pennsylvania"
, city = "Philadelphia"
}
}
in john
```
#### Type Checking
If I mess up this contract by accident, I want to know as quickly as possible that I messed up so that I can fix it!
```dhall
let jane : Profile =
{ person =
{ name = "Jane Doe"
-- , age = 67
}
, address =
{ country = "United States"
, state = "Pennsylvania"
, city = "Philadelphia"
}
}
in jane
```
Type checking is also a very difficult thing to build from scratch. Dhall is implemented in Haskell; we trust in Haskell to provide us tooling to write good compilers π
#### Clear Error-Messages
The error message for the above type error is clear as day! π
You can get these clear explanations by passing in the `--explain` flag
```dhall
You or the interpreter annotated this expression:
β³ { person.name = "Jane Doe"
, address =
{ country = "United States", state = "Pennsylvania", city = "Philadelphia" }
}
... with this type or kind:
β³ { address : { city : Text, country : Text, state : Text }
, person : { age : Natural, name : Text }
}
... but the inferred type or kind of the expression is actually:
β³ { address : { city : Text, country : Text, state : Text }
, person : { name : Text }
}
```
### "Maintainable" means good tooling to provide feedback
To facilicate this, `dhall` provides some tooling:
- Easy Installation
- IDE support
- CLI Tooling
- Interoperability
#### Easy Installation
You can install Dhall via `brew` for development
- [See here](https://formulae.brew.sh/formula/dhall)
Via `apt` and other linux package managers if you're building tooling
- [See here](https://ubuntu.pkgs.org/20.04/ubuntu-universe-arm64/dhall_1.19.1-1build2_arm64.deb.html)
And via `nix` if you're a mad-lad
- [See here](https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=dhall)
#### IDE Support
[VS Code](https://github.com/dhall-lang/vscode-dhall-lsp-server) and IntelliJ idea as well supported, and LSP bindings are included!
Dhall also is opinionated about formatting, so everyone's Dhall code looks the same!
#### CLI Tooling
I never mentioned how to actually run these!
You can specify a file like so from the command line:
```shell
> dhall --explain --file <MY_FILE.dhall>
```
Or you can pass it in via stdin!
```shell
> dhall <<< 'True && False'
```
#### Interoperability
JSON, YAML and HCL, HOCOL, TOML, and others already exist! Why do we need another syntax? π
Dhall [provides tools](https://docs.dhall-lang.org/tutorials/Getting-started_Generate-JSON-or-YAML.html#) like `dhall-to-json`, `dhall-to-yaml`, `dhall-to-terraform` and other CLI tools which take Dhall expressions and convert them to other standards!
## Footnotes! π£
### More insights on Dhall π€
See [this interview with one of the maintainers of Dhall, Gabriel Gonzalez](https://corecursive.com/040-tech-evangelism-with-gabriel-gonzalez/#crossing-the-chasm) on the [CoRecursive Podcast](https://corecursive.com/)
He describes how one of the most important important ways to get adoption of technical tooling is in the [[_Crossing The Chasm]] model. This is one such model which has personally affected my worldview. βΊοΈ
### FAQs and Reassurances: π£ -> π
#### Why do the records look weird? I don't like it... π£
The convention for Dhall is to put commas before entries in the record
This minimizes diffs when we're adding new things and we don't want to create a change in the previous line just to add a comma and add a newline.
After using this, I belive it will be quick to get used to
#### Why do functions look weird? I don't like it... π£
To promote reuse, a lot of functional languages use a techinque called [Currying](https://towardsdatascience.com/what-is-currying-in-programming-56fd57103431)
Named after the mathematitian, Haskell Curry, not the cooking style π
#### Where are my `for` loops!? I don't like it... π£
Dhall tries to promote a programming style which is [total and pure](https://developer.hashicorp.com/terraform/language/expressions/function-calls#when-terraform-calls-functions)
Dhall [provides](https://docs.dhall-lang.org/tutorials/string-matrix.html) the `List/map` and `List/fold` functions via the standard library to help deal with this