While benchmarking the example from #769 I saw that a significant amount of time was spent benchmarking record literals. When I looked at the code more closely I saw that the first key in the record literal was being type-checked twice (once to figure out the record's associated type-checking constant and once as part of the `process` loop). This change fixes that, which speeds up interpretation of the large example by 9%: Before: ``` time 18.13 s (18.11 s .. 18.16 s) 1.000 R² (1.000 R² .. 1.000 R²) mean 18.09 s (18.07 s .. 18.11 s) std dev 21.92 ms (10.66 ms .. 29.76 ms) variance introduced by outliers: 19% (moderately inflated) ``` After: ``` time 16.53 s (16.49 s .. 16.60 s) 1.000 R² (1.000 R² .. 1.000 R²) mean 16.59 s (16.56 s .. 16.64 s) std dev 43.65 ms (6.227 ms .. 56.35 ms) variance introduced by outliers: 19% (moderately inflated) ``` |
||
---|---|---|
.. | ||
benchmark | ||
dhall | ||
dhall-lang@61c6d3c74b | ||
doctest | ||
examples | ||
src | ||
tests | ||
CHANGELOG.md | ||
default.nix | ||
dhall.cabal | ||
LICENSE | ||
README.md | ||
Setup.hs | ||
shell.nix |
dhall
For installation or development instructions, see:
Full documentation here:
Introduction
Dhall is a programmable configuration language that is not Turing-complete
You can think of Dhall as: JSON + functions + types + imports
Motivation
"Why not configure my program using JSON or YAML?"
JSON or YAML are suitable for small configuration files, but larger configuration files with complex schemas require programming language features to reduce repetition. Otherwise, the repetitive configuration files become error-prone and difficult to maintain/migrate.
This post explains in more detail the motivation behind programmable configuration files:
"Why not configure my program using Haskell code?"
You probably don't want to rebuild your program every time you make a configuration change. Recompilation is slow and requires the GHC toolchain to be installed anywhere you want to make configuration changes.
Example
Given this Haskell program saved to example.hs
:
-- example.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import Dhall
data Example = Example { foo :: Integer, bar :: Vector Double }
deriving (Generic, Show)
instance Interpret Example
main :: IO ()
main = do
x <- input auto "./config"
print (x :: Example)
... which reads in this configuration file:
$ cat ./config
{ foo = 1
, bar = ./bar
}
... which in turn references this other file:
$ cat ./bar
[3.0, 4.0, 5.0]
... you can interpret the Haskell program like this:
$ nix-shell ../nix/test-dhall.nix
[nix-shell]$ runghc example.hs
Example {foo = 1, bar = [3.0,4.0,5.0]}
You can also interpret Dhall programs directly using the installed command-line compiler:
$ dhall
List/head Double ./bar
<Ctrl-D>
Optional Double
Some 3.0
... and you can reference remote expressions or functions by their URL, too:
$ dhall
let null = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/null
in null Double ./bar
<Ctrl-D>
Bool
False
Now go read the Dhall tutorial to learn more.
Standard-compatibility table
Haskell package version | Supported standard version |
---|---|
1.20.* |
5.0.0 |
1.19.* |
4.0.0 |
1.18.* |
3.0.0 |
1.17.* |
2.0.0 |
1.16.* |
1.0.0 |