Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/hagl/dhall-unison
A Unison (https://www.unisonweb.org) implementation of the Dhall configuration language (https://dhall-lang.org).
https://github.com/hagl/dhall-unison
dhall dhall-lang unison unison-language
Last synced: 3 months ago
JSON representation
A Unison (https://www.unisonweb.org) implementation of the Dhall configuration language (https://dhall-lang.org).
- Host: GitHub
- URL: https://github.com/hagl/dhall-unison
- Owner: hagl
- License: bsd-3-clause
- Created: 2021-11-06T12:03:46.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-01-28T20:58:47.000Z (10 months ago)
- Last Synced: 2024-06-24T23:34:05.835Z (5 months ago)
- Topics: dhall, dhall-lang, unison, unison-language
- Homepage:
- Size: 65.9 MB
- Stars: 7
- Watchers: 2
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-dhall - dhall-unison - Unison language support. (Binding)
README
# dhall-unison
A [Unison][unison] implementation of the [Dhall configuration language][dhall-lang].## Table of contents
* [Installation](#installation)
* [Status](#status)
* [Usage](#usage)
* [Copyright and license](#copyright-and-license)## Installation
To install the latest version in your Unison codebase use the following ucm command:
```
pull hagl.public.dhall .lib.dhall
```## Usage
The main interface for this library are the functions
```
evaluate : Text ->{IO} Either Text DhallValue
evaluateSimple : Text -> Either Text DhallValue
```Both evaluate a text containing a dhall expression into an error or a value of type `DhallValue`.
```
unique type DhallValue
= DhallInteger Integer
| DhallNatural Natural
| DhallFloat Float
| DhallList [DhallValue]
| DhallBoolean Boolean
| DhallText Text
| DhallRecord (Map Text DhallValue)
| DhallOptional (Optional DhallValue)
````evaluate` supports all of Dhall's features. In order to resolve imports (i.e. environment variables, local or remote files) it needs the `IO` ability.
`evaluateSimple` is a pure function and can be used to evaluate a self-contained dhall expression (i.e. without any imports). It will fail and return a `Left` value when encountering an import during evaluation.
### Example 1: Converting a Dhall expression to a Unison value
Let's have a look at this Dhall program from the [Dhall homepage][dhall-lang]
```dhall
let Config : Type =
{ home : Text
, privateKey : Text
, publicKey : Text
}let makeUser : Text -> Config = \(user : Text) ->
let home : Text = "/home/${user}"
let privateKey : Text = "${home}/.ssh/id_ed25519"
let publicKey : Text = "${privateKey}.pub"
let config : Config = { home, privateKey, publicKey }
in configlet configs : List Config =
[ makeUser "bill"
, makeUser "jane"
]in configs
```Assume we want to use the above Dhall program to generate a list of Unison UserConfig values
```unison
unique type UserConfig = UserConfig Text Text Text
```This mapping function converts the evaluated DhallValue into UserConfig by pattern matching on the structure.
Since the Dhall type-checker verifies that the result has the correct structure, we can use non-exhaustive pattern matching:```unison
convertConfigs : DhallValue -> List UserConfig
convertConfigs = cases
DhallList list ->
List.map (cases DhallRecord map ->
getString key = Map.get key map |> cases (Optional.Some (DhallText text)) -> text
UserConfig (getString "home") (getString "publicKey") (getString "privateKey")) list-- evaluate and convert input in a watch expression
> evaluateSimple input |> Either.mapRight convertConfigs
```
The watch expression will give the following output in `ucm`
```ucm
> evaluateSimple input |> Either.mapRight convertConfigs
⧩
Right
[ UserConfig
"/home/bill" "/home/bill/.ssh/id_ed25519.pub" "/home/bill/.ssh/id_ed25519",
UserConfig
"/home/jane" "/home/jane/.ssh/id_ed25519.pub" "/home/jane/.ssh/id_ed25519" ]
```This example is also available online on [Unison Share][unison-share-hagl-dhall]
### Example 2: Evaluating Dhall code in ucm
This library also ships an unsupported runnable `dhallRun` function that can be used to quickly test a dhall expression directly from `ucm`.
The implementation uses a bit of a hack to not require quoting or escaping dhall code inside ucm.
Here are a few examples what you can do:Simple calculations
```
.> run dhallRun 47 * 71
3337
```Text interpolation, access to environment variables and calling built-in functions
```
.> run dhallRun "Hello ${env:USER as Text}!\n 3 + 4 = ${Natural/show (3 + 4)}"
"Hello harald!
3 + 4 = 7"
```Defining and applying functions
```
.> run dhallRun let add = \(x: Natural) -> \(y: Natural) -> x + y in add 1 2
3
```Using remote dhall expressions (e.g. fold from Dhall prelude)
```
.> run dhallRun let sum = \(l: List Natural) -> https://prelude.dhall-lang.org/List/fold.dhall Natural l Natural (\(x: Natural) -> \(y: Natural) -> x + y) 0 in sum [1,2,3,4,5]
15
```Loading and evaluating the remote expression takes some time. By adding a semantic hash to the import, the function can be cached locally. This will reduce the runtime of the second call below. You can use `dhallHash` to calculate the hash value of an import expression:
```
.> run dhallRun https://prelude.dhall-lang.org/List/fold.dhall
sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814.> run dhallRun let sum = \(l: List Natural) -> https://prelude.dhall-lang.org/List/fold.dhall sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814 Natural l Natural (\(x: Natural) -> \(y: Natural) -> x + y) 0 in sum [1,2,3,4,5]
15.> run dhallRun let sum = \(l: List Natural) -> https://prelude.dhall-lang.org/List/fold.dhall sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814 Natural l Natural (\(x: Natural) -> \(y: Natural) -> x + y) 0 in sum [1,2,3,4,5]
15
```See the [Dhall documentation](dhall-lang) for more details about the language.
## Status
This project is currently in development, release v3 has alpha status.
The [Dhall Acceptance Tests][dhall-tests] can be run with the the from `ucm` with the command
```ucm
run .external.dhall.trunk.testsuite.runTestSuite
```
At the time of this writing this will give the following results
```
1495 total tests ( ✅ 1492 passed, 🚫 3 failed) in directory ./dhall-lang
Duration: 567.007s
```
The remaining failing tests are* `dhall-lang/tests/type-inference/success/preludeA.dhall` : This test recursively loads all of prelude and shows some performance problems in the current implementation. It would probably succeed, but would take hours/days to do so. See the issues labeled [performance](https://github.com/hagl/dhall-unison/issues?q=is%3Aissue+label%3Aperformance+) for some ideas how to improve the performance.
* `./dhall-lang/tests/parser/failure/spacing/LetNoSpace3`
* `./dhall-lang/tests/parser/failure/spacing/LetNoSpace4`
### LimitationsThe following features are not yet supported
* date & time types are not exposed in the resolved DhallValue, since there are no matching type in the Unsion standard library### Future directions
Once Unison has some reflection/meta-programming possibilities it should be possible to
* generate a Dhall type for a Unison type (giving type checking & editor support for config files)
* automatically convert a Dhall value into a Unison value when their types are compatible## Copyright and license
All code in this repository is available under the [3-Clause BSD License][license].
Copyright 2021-2022 [Harald Gliebe][hagl]
This project is based on and uses code from the projects
- [dhall-lang][dhall-lang-project] ([3-Clause BSD License][dhall-lang-license])
- [dhall-haskell][dhall-haskell] ([3-Clause BSD License][dhall-lang-license])
- [stew/uniparsec][stew-parser]
- [stew/httpclient][stew-http][license]: https://github.com/hagl/dhall-unison/blob/main/LICENSE
[unison]: https://www.unisonweb.org/
[dhall-lang]: https://dhall-lang.org/
[dhall-lang-project]: https://github.com/dhall-lang/dhall-lang
[dhall-lang-license]: https://github.com/dhall-lang/dhall-lang/blob/main/LICENSE
[dhall-haskell]: https://github.com/dhall-lang/dhall-haskell
[dhall-haskell-license]: https://github.com/dhall-lang/dhall-haskell/blob/main/LICENSE
[dhall-tests]: https://github.com/dhall-lang/dhall-lang/tree/master/tests
[stew-parser]: https://share.unison-lang.org/@stew/p/code/latest/namespaces/public/projects/uniparsec/main
[stew-http]: https://share.unison-lang.org/@stew/p/code/latest/namespaces/public/projects/httpclient/main
[hagl]: https://twitter.com/hagl
[unison-share-hagl-dhall]: https://share.unison-lang.org/latest/terms/hagl/dhall/README