packages feed

dhall 1.11.1 → 1.42.3

raw patch · 3993 files changed

Files

CHANGELOG.md view
@@ -1,3 +1,1724 @@+1.42.3++* [Fix the typechecking rule for `Optional` + `with`](https://github.com/dhall-lang/dhall-haskell/pull/2650)+* [Add `*WithIndex` instances for `Map`](https://github.com/dhall-lang/dhall-haskell/pull/2633)+* [`dhall package`: Add support for automatic sub-packags](https://github.com/dhall-lang/dhall-haskell/pull/2639)+* [`dhall to-directory-tree`: Add `binary-file` support](https://github.com/dhall-lang/dhall-haskell/pull/2641)+* [Support GHC 9.12.1](https://github.com/dhall-lang/dhall-haskell/pull/2649)+* [`dhall to-directory-tree`: create parents of files when using fixpoint representation](https://github.com/dhall-lang/dhall-haskell/pull/2653)++1.42.2++* [Supports standard version 23.1.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.1.0)+  * [Allow `Natural` and `Integer` literals in binary notation](https://github.com/dhall-lang/dhall-haskell/pull/2540)+* Fix macOS build [[#2561](https://github.com/dhall-lang/dhall-haskell/pull/2561)] / [[#2586](https://github.com/dhall-lang/dhall-haskell/pull/2586)]+* [`dhall to-directory-tree`: Fix support for empty `Map`s](https://github.com/dhall-lang/dhall-haskell/pull/2609)+* [`Dhall.TH`: Improve recompilation checking](https://github.com/dhall-lang/dhall-haskell/pull/2620)+  * `Dhall.TH` utilities now use `addDependentFile` internally so that GHC will recompile if any Dhall dependencies change+* Performance improvements+  * Optimize `Natural/fold`: [[#2585](https://github.com/dhall-lang/dhall-haskell/pull/2585)] / [[#2596](https://github.com/dhall-lang/dhall-haskell/pull/2596)]+  * [Improve `Dhall.Map.traverseWithKey` performance](https://github.com/dhall-lang/dhall-haskell/pull/2589)+    * The fold will now short-circuit if it reaches a fixed point+  * [#2611](https://github.com/dhall-lang/dhall-haskell/pull/2611)+* Fixes and improvements to test suite+  * [#2593](https://github.com/dhall-lang/dhall-haskell/pull/2593)+* Fixes and improvements to haddocks+  * [#2546](https://github.com/dhall-lang/dhall-haskell/pull/2546)+* Fixes and improvements to code formatting+  * [#2608](https://github.com/dhall-lang/dhall-haskell/pull/2608)++1.42.1++* Add several new entrypoints to `Dhall` module [[#2534](https://github.com/dhall-lang/dhall-haskell/pull/2534)] / [[#2544](https://github.com/dhall-lang/dhall-haskell/pull/2544)]+* Build against latest versions of:+  * [`ansi-terminal`](https://github.com/dhall-lang/dhall-haskell/pull/2521)+  * [`optparse-applicative`](https://github.com/dhall-lang/dhall-haskell/pull/2543)+  * [`optparse-generic`](https://github.com/dhall-lang/dhall-haskell/pull/2519)+  * [`lens`](https://github.com/dhall-lang/dhall-haskell/pull/2539)+  * `template-haskell` [[#2532](https://github.com/dhall-lang/dhall-haskell/pull/2532)] / [[#2542](https://github.com/dhall-lang/dhall-haskell/pull/2542)]+  * [`unix-compat`](https://github.com/dhall-lang/dhall-haskell/pull/2532)+1.42.0++* [Supports standard version 23.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.0.0)+  * [BREAKING CHANGE TO THE API AND LANGUAGE: Language support for `Bytes` literals](https://github.com/dhall-lang/dhall-haskell/pull/2499)+    * This is a breaking change to the API due to adding new `Bytes` and `BytesLiteral` constructors to the `Expr` type+    * This is a breaking change to the language now that `Bytes` is a reserved identifier+  * [BREAKING CHANGE TO THE API AND LANGUAGE: New `{Date,Time,TimeZone}/show` builtins](https://github.com/dhall-lang/dhall-haskell/pull/2493)+    * This is a breaking change to the API due to adding new `{Date,Time,TimeZone}Show` constructors to the `Expr` type+    * This is a breaking change to the language now that `{Date,Time,TimeZone}/show` are not reserved identifiers+* [BREAKING CHANGE: `dhall lint` no longer sorts `let` bindings](https://github.com/dhall-lang/dhall-haskell/pull/2503)+  * This had to be removed because the old behavior was not always correct+  * The old behavior would sometimes change the behavior of a Dhall program or break the program+  * Out of an abundance of caution we're disabling the feature until it can be properly fixed (which is't trivial)+* [BUG FIX: Fix pretty-printing of `Time` literals](https://github.com/dhall-lang/dhall-haskell/pull/2466)+  * The pretty-printer was stripping leading zeros from the fractional component+    of seconds+* [BUG FIX: Fix custom normalizers to work for things other than functions](https://github.com/dhall-lang/dhall-haskell/pull/2464)+  * Before this change you could extend the language with custom functions, but+    not custom values (e.g. `foo = 1`)+* [BUG FIX: Don't URL encode path components](https://github.com/dhall-lang/dhall-haskell/pull/2505)+  * The pretty-printer was URL-encoding path components, which is not correct (according to the standard)+  * URL path components are supposed to be already URL-encoded by the user and left undisturbed by the interpreter (which is now what it correctly does)+* New `dhall package` command: [#2478](https://github.com/dhall-lang/dhall-haskell/pull/2487), [#2508](https://github.com/dhall-lang/dhall-haskell/pull/2508)+  * This command makes it easier to turn a directory full of Dhall expressions+    into a dhall package (e.g. `package.dhall`)+* [Improved `dhall to-directory-tree` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/2437)+  * The `dhall to-directory-tree` subcommand now optionally supports specifying+    metadata for generated paths+  * For a worked example, see: https://github.com/dhall-lang/dhall-haskell/blob/main/dhall/examples/to-directory-tree.dhall+* `dhall freeze --cache --all` is now idempotent: [#2486](https://github.com/dhall-lang/dhall-haskell/pull/2486), [#2500](https://github.com/dhall-lang/dhall-haskell/pull/2500)+  * Before this change a second run would fail due to attempting to resolve+    the `missing` import it would generate+* [New Template Haskell options for adding strictness annotations to generated Haskell types](https://github.com/dhall-lang/dhall-haskell/pull/2504)+* [Template Haskell can now generate higher-kinded Haskell types from higher-kinded Dhall types](https://github.com/dhall-lang/dhall-haskell/pull/2506)+* [New `Dhall.Freeze` utilities for working with custom evaluators](https://github.com/dhall-lang/dhall-haskell/pull/2478)+* [Add `Data` instances for `Import` and various other types](https://github.com/dhall-lang/dhall-haskell/pull/2462)+* [Add `Eq` instances for `InvalidDecoder` and `ExtractError`](https://github.com/dhall-lang/dhall-haskell/pull/2482)++1.41.2++* [BUG FIX: Fix `:hash` REPL command to α-normalize input](https://github.com/dhall-lang/dhall-haskell/pull/2420)+* [Add `{From,To}Dhall` instances for `DayOfWeek`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* [Add `{From,To}Dhall` instances for `ShortText`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* Performance improvements+  * [#2423](https://github.com/dhall-lang/dhall-haskell/pull/2423)+* Fixes and improvements to haddocks+  * [#2396](https://github.com/dhall-lang/dhall-haskell/pull/2396)+* Fixes and improvements to test suite+  * [#2342](https://github.com/dhall-lang/dhall-haskell/pull/2382)+  * [#2394](https://github.com/dhall-lang/dhall-haskell/pull/2394)+* Build against newer dependencies+  * [`pretty-simple-4.1`](https://github.com/dhall-lang/dhall-haskell/pull/2408)+  * [`aeson-2.1`](https://github.com/dhall-lang/dhall-haskell/pull/2424)+  * [`vector-0.13`](https://github.com/dhall-lang/dhall-haskell/pull/2427)+  * [`turtle-1.6`](https://github.com/dhall-lang/dhall-haskell/pull/2431)++1.41.1++* [BUG FIX: Don't escape `?` path component when pretty-printing `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2392)++1.41.0++* [Support standard version 22.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v22.0.0)+  * [Allow `with` expressions to update `Optional` values using `?`](https://github.com/dhall-lang/dhall-haskell/pull/2386)+  * [Add `showConstructor` keyword](https://github.com/dhall-lang/dhall-haskell/pull/2384)+* [BUG FIX: Fix pretty-printing of time zones](https://github.com/dhall-lang/dhall-haskell/pull/2379)+  * Timezones with a negative offset were previously being rendered with two+    leading minus signs instead of one+* [BUG FIX: `dhall freeze --cache` to work with standard version 21.0.0](https://github.com/dhall-lang/dhall-haskell/pull/2350)+  * `dhall freeze` will now use `missing sha256:…` for the first import so that+    the latter import will be tried if the import is not in cache+  * The old behavior is incompatible with standard version 21.0.0 because the+    new behavior of the `?` operator doesn't fall back on hash mismatches+* [BUG FIX: Allow `with` expression to update a field named `Some`](https://github.com/dhall-lang/dhall-haskell/pull/2354)+  * This fixes a discrepancy between the Haskell implementation and the standard+    where the Haskell implementation would not permit+    `{ Some = 0 } with Some = 1 `+* [Fix `dhall {format,lint,freeze}` to preserve leading shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2364)+* [Add `FromDhall` instances for `Int{8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2349)++1.40.2++* [Supports standard version 21.1.0](https://github.com/dhall-lang/dhall-haskell/pull/2236)+    * [The interpreter now supports customizing headers using a `headers.dhall`+      configuration file](https://github.com/dhall-lang/dhall-haskell/pull/2236)+    * [Generalize grammar for certain annotations](https://github.com/dhall-lang/dhall-haskell/pull/2320)+    * [Add support for a trailing line comment without a newline](https://github.com/dhall-lang/dhall-haskell/pull/2309)+* [BUG FIX: `dhall repl` no longer ignores type annotations on `:let` commands](https://github.com/dhall-lang/dhall-haskell/pull/2297)+    * Before this fix, `:let x : T = 3` would ignore the `: T` type annotation+* [BUG FIX: Don't accept a bar after an empty union](https://github.com/dhall-lang/dhall-haskell/pull/2338)+    * Before this fix, the interpreter would accept something like `<>|`, which+      is not valid according to the standard grammar+* New `FromDhall`/`ToDhall` instances for `Day`/`TimeOfDay`/`TimeZone` [#2294](https://github.com/dhall-lang/dhall-haskell/pull/2294) [#2300](https://github.com/dhall-lang/dhall-haskell/pull/2300)+    * These types correspond to the recent temporal literals added to the+      language+* [New `subExpressionsWith` `Traversal`](https://github.com/dhall-lang/dhall-haskell/pull/2302)+* [Add Template Haskell support for modifying field names in generated Haskell+  types](https://github.com/dhall-lang/dhall-haskell/pull/2285)+    * This adds a new `makeHaskellTypesWith` utility with takes a+      `GenerateOptions` function argument for customizing the code-generation+      logic+    * This comes in handy when Dhall fields have names are reserved keywords in+      Haskell code.  You can now transform the Haskell field names to avoid+      collisions+* [Support GHC 9.2](https://github.com/dhall-lang/dhall-haskell/pull/2328)+* Fixes and improvements to documentation+    * [#2290](https://github.com/dhall-lang/dhall-haskell/pull/2290)+* Fixes and improvements to error messages+    * [#2303](https://github.com/dhall-lang/dhall-haskell/pull/2303)++1.40.1++* [BUG FIX: Fix equivalence check for `Date` / `Time` / `TimeZone`](https://github.com/dhall-lang/dhall-haskell/pull/2291)+    * This fixes a serious bug in the recently introduced support for temporal+      literals where they would fail to type-check when given a correct type+      annotation or when they were checked against an existing type+    * For example, `00:00:00 : Time` was failing to type-check++1.40.0++* [Almost supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+    * The main thing that is missing is support for the `headers.dhall` file+    * [BREAKING CHANGE TO THE LANGUAGE: Add support for `Date` / `Time` / `TimeZone` ](https://github.com/dhall-lang/dhall-haskell/pull/2247)+        * This is a breaking change because `Date`, `Time`, and `TimeZone` are+          now reserved identifiers+    * [Improved fallback behavior for `?`](https://github.com/dhall-lang/dhall-haskell/pull/2203)+* [BREAKING CHANGE TO THE LANGUAGE: Require whitespace before `with`](https://github.com/dhall-lang/dhall-haskell/pull/2213)+    * The parser now requires whitespace before the `with` keyword, which brings+      the Haskell implementation into closer compliance with the standard+    * In practice this is a technically breaking change which will not affect+      most programs+* [New `FromDhall` instances for `Predicate`, `Equivalence`, and `Op`](https://github.com/dhall-lang/dhall-haskell/pull/2278)+* [`dhall lint` will now sort `let` bindings with imports](https://github.com/dhall-lang/dhall-haskell/pull/2205)+    * `dhall lint` now reorders `let` bindings to move imports to the top so+      long as doing so does not change the behavior of the program+* Fixes and improvements to code formatting+    * [#2280](https://github.com/dhall-lang/dhall-haskell/pull/2280)+* Fixes and improvements to error messages+    * [#2244](https://github.com/dhall-lang/dhall-haskell/pull/2244)+    * [#2238](https://github.com/dhall-lang/dhall-haskell/pull/2238)++1.39.0++* [Supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+    * [Add support for Unix shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2175)+* [BREAKING CHANGE TO THE API: `dhall {format,freeze,lint}` now accept multiple+  files](https://github.com/dhall-lang/dhall-haskell/pull/2169)+    * The `--inplace` flag is no longer necessary and you can now specify+      multiple files to update in place on the command line, like+      `dhall format foo.dhall bar.dhall`+    * The `--inplace` flag is still accepted, but does nothing, and will emit a+      warning+    * This is a breaking change to the API for formatting/freezing/linting files+      because now you can specify multiple inputs instead of one input+* [BREAKING CHANGE: Pre-6.0.0 hashes are no longer supported](https://github.com/dhall-lang/dhall-haskell/pull/2190)+    * The interpreter no longer provides backwards compatibility for integrity+      checks computed before standard version 6.0.0+    * This is a breaking change to the API of the `Dhall.Binary` module, where+      certain utilities are no longer parameterized on a `StandardVersion`+    * This is also a breaking change to any Dhall code that depended on these+      really old integrity checks+* [BUG FIX: Formatting `≡` now correctly preserves the original character set](https://github.com/dhall-lang/dhall-haskell/pull/2176)+* [BUG FIX: Don't panic on `Text/replace ""`](https://github.com/dhall-lang/dhall-haskell/pull/2184)+* [Quasiquotation support for Dhall](https://github.com/dhall-lang/dhall-haskell/pull/2198)+    * You can now convert a Dhall expression to the corresponding syntax tree+      using a quasiquoter like this: `[dhall| \x -> x + 2 ]`+* [New `Dhall.Marshal.{Encode,Decode}` modules](https://github.com/dhall-lang/dhall-haskell/pull/2193)+    * These modules split up the `Dhall` module into two smaller modules for+      encoding and decoding logic, respectively+    * The `Dhall` module still re-exports the same functionality as before, so+      this is not a breaking change+* [Support GHC 9.0.1](https://github.com/dhall-lang/dhall-haskell/pull/2154)+* Fixes and improvements to code formatting+    * [Improve pretty-printing of `sha256`](https://github.com/dhall-lang/dhall-haskell/pull/2189)++1.38.1++* [Add `INLINABLE` annotations in more places](https://github.com/dhall-lang/dhall-haskell/pull/2164)+    * This may improve performance by enabling more specializations+* [Fix `hashable`-related test failures](https://github.com/dhall-lang/dhall-haskell/pull/2152)+* [Fix support for GHC 8.4.4](https://github.com/dhall-lang/dhall-haskell/pull/2143)+    * … by using `GeneralizedNewtypeDeriving` (with a `z`)+* [Allow doctest-0.18](https://github.com/dhall-lang/dhall-haskell/pull/2148)+* [Allow bytestring-0.11](https://github.com/dhall-lang/dhall-haskell/pull/2144)++1.38.0++* [BREAKING CHANGE: Detect preferred character set from input](https://github.com/dhall-lang/dhall-haskell/pull/2108)+    * `dhall format` will now preserve the character set of the formatted file+      by default.  In other words, if the file uses ASCII punctuation then+      `dhall format` will format the file using ASCII punctuation.+    * If the file contains both ASCII and Unicode punctuation it will prefer+      Unicode by default+    * This is a breaking change because the `Lam` / `Pi` / `Combine` /+      `CombineTypes`, and `Prefer` constructors now take an additional argument+      to record which character set was used+* [BUG FIX: Fix CORS compliance check](https://github.com/dhall-lang/dhall-haskell/pull/2121)+    * Previous versions were not correctly enforcing CORS compliance+    * This implies that some imports that would have worked previously by+      accident will now fail; specifically: an import from one domain+      transitively importing something from another domain that has not opted+      into CORS+* [Add `ToDhall (Fix f)` instance](https://github.com/dhall-lang/dhall-haskell/pull/2122)+* Fixes and improvements to error messages+    * [#2130](https://github.com/dhall-lang/dhall-haskell/pull/2130)++1.37.1++* [Fix performance regression for `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2112)++1.37.0++* [Supports version 20.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.0.0)+    * [Implement revised `Text/replace` β-normalization](https://github.com/dhall-lang/dhall-haskell/pull/2072)+    * [Allow `Text/replace ""` to support an abstract haystack](https://github.com/dhall-lang/dhall-haskell/pull/2084)+    * [Support `if` expressions returning a type or kind](https://github.com/dhall-lang/dhall-haskell/pull/2080)+* BREAKING CHANGE TO THE API: [Improve error message for duplicate projection label](https://github.com/dhall-lang/dhall-haskell/pull/2097)+    * This also makes the implementation more standards-compliant, by treating+      a duplicate label as a type error instead of a parse error+    * This is a breaking change since the `Project` constructor now stores a+      `[Text]` instead of `Set Text`+* [Add `--cache` flag to `dhall hash`](https://github.com/dhall-lang/dhall-haskell/pull/2093)+    * This flag adds the hashed expression to the cache when enabled+* [Deprecate `Inject` / `Interpret`](https://github.com/dhall-lang/dhall-haskell/pull/2099)+    * You should instead use `ToDhall` / `FromDhall`, respectively+* Fixes and improvements to the haddocks:+    * [#2098](https://github.com/dhall-lang/dhall-haskell/pull/2098)+    * [#2100](https://github.com/dhall-lang/dhall-haskell/pull/2100)+* Fixes and improvements to error messages:+    * [#2082](https://github.com/dhall-lang/dhall-haskell/pull/2082)+    * [#2095](https://github.com/dhall-lang/dhall-haskell/pull/2095)+* Fixes and improvements to the parser:+    * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2089)+* Fixes and improvements to the pretty printer:+    * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2083)+    * [#2101](https://github.com/dhall-lang/dhall-haskell/pull/2101)++1.36.0++* [Supports version 19.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v19.0.0)+    * BREAKING CHANGE TO THE API: [Add `Text/replace` built-in](https://github.com/dhall-lang/dhall-haskell/pull/2063)+    * [Implement `with` without syntactic sugar](https://github.com/dhall-lang/dhall-haskell/pull/2055)+* [`dhall lint` will now add a `.dhall` extension to all Prelude imports](https://github.com/dhall-lang/dhall-haskell/pull/2061)+    * The old extension-free Prelude imports are deprecated+* [Fix command-line completions for files](https://github.com/dhall-lang/dhall-haskell/pull/2016)+* [Improve Template Haskell support for record constructors](https://github.com/dhall-lang/dhall-haskell/pull/2070)+* Fixes and improvements to code formatting+    * [#2037](https://github.com/dhall-lang/dhall-haskell/pull/2037)+    * [#2048](https://github.com/dhall-lang/dhall-haskell/pull/2048)+    * [#2069](https://github.com/dhall-lang/dhall-haskell/pull/2069)++1.35.0++* [Supports version 18.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v18.0.0)+    * [Implement more efficient `with` desugaring](https://github.com/dhall-lang/dhall-haskell/pull/1993)+        * Chained `with` expressions will now be much more efficient+* [BREAKING CHANGE TO THE API: Preserve whitespace for `Lam` constructor](https://github.com/dhall-lang/dhall-haskell/pull/1980)+    * This change extends the `Lam` constructor to preserve whitespace around+      the variable binding+    * The motivation for this change is to enable `dhall-docs` to support+      jumping to definitions+    * You can replace your existing `Lam` constructors with+      `Dhall.Core.makeFunctionBinding`+* [BREAKING CHANGE TO THE API: Preserve whitespace for `Field` constructors](https://github.com/dhall-lang/dhall-haskell/pull/1991)+    * This change extends the `Field` constructor to preserve whitespace around+      the selected field+    * The motivation for this change is to enable `dhall-docs` to support+      jumping to definitions+    * You can use `Dhall.Core.makeFieldSelection` and+      `Dhall.Core.fieldSelectionLabel` to convert between the detailed and the+      simple representation of the selected field.+* [Add `FromDhall` instances for `{Int,Word}{,8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2012)+* [Add `--output` option for `dhall text` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/1974)+* [Add `Dhall.Crypto.toString`](https://github.com/dhall-lang/dhall-haskell/pull/1976)+* [Make the HTTP `Manager` configurable](https://github.com/dhall-lang/dhall-haskell/pull/2027)+    * Several import-related functions now provide an alternative variants that+      allows the user to supply a custom `Manager`+    * You can use this to tweak HTTP request timeouts or use a different TLS+      manager (e.g. one from `http-client-openssl`)+* Fixes and improvements to code formatting+    * [#2000](https://github.com/dhall-lang/dhall-haskell/pull/2000)+    * [#2021](https://github.com/dhall-lang/dhall-haskell/pull/2021)++      The formatter now preserves comments for record fields (both record types+      and record literals)+* Fixes and improvements to documentation+    * [#2011](https://github.com/dhall-lang/dhall-haskell/pull/2011)+    * [#2013](https://github.com/dhall-lang/dhall-haskell/pull/2013)+    * [#2014](https://github.com/dhall-lang/dhall-haskell/pull/2014)+* Fixes and improvements to test suite+    * [#2020](https://github.com/dhall-lang/dhall-haskell/pull/2020)++1.34.0++* [Supports version 17.1.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v17.1.0)+    * [Add support for trailing commas](https://github.com/dhall-lang/dhall-haskell/pull/1885)+* BREAKING CHANGE to the API: [Support prefix comments on record key-value pairs](https://github.com/dhall-lang/dhall-haskell/pull/1908)+    * The Dhall AST (i.e. `Expr`) now preserves some comments for record types+      and record literals+    * The impact of this change is that you will need to add+      `Dhall.Syntax.makeRecordField` or `Dhall.Syntax.recordFieldValue` in a few+      places wherever your Haskell assembles or disassembles record expressions+    * The motivation of this change is two-fold:+        * To eventually enable `dhall-docs` support for rendering record+          comments as documentation+        * To eventually enable support for preserving record-related comments+          when formatting Dhall code+* BUG FIX: [Fix `with` expressions to permit functions on their left-hand side](https://github.com/dhall-lang/dhall-haskell/pull/1897)+    * This was a case of the Haskell implementation not being compliant with the+      standard grammar+* [Drop support for GHC 8.2](https://github.com/dhall-lang/dhall-haskell/pull/1949)+* [Add a new `dhall rewrite-with-schemas` command](https://github.com/dhall-lang/dhall-haskell/pull/1902)+    * You can now simplify a Dhall expression using a schema record (e.g. a+      `./schemas.dhall` record that a package might provide)+    * This simplification replaces large anonymous records with an+      equivalent use of a record completion when possible+* [Add `--transitive` flag to `dhall {format,lint,freeze}](https://github.com/dhall-lang/dhall-haskell/pull/1880)+    * This flag lets you format/lint/freeze a file and all of its transitive+      dependencies that are reachable via relative file imports+* [Move `man/dhall.1` to `data-files`](https://github.com/dhall-lang/dhall-haskell/pull/1921)+    * This ensures that Cabal will install `dhall`'s `man` pages in the+      correct directory+* Performance improvements+    * [#1879](https://github.com/dhall-lang/dhall-haskell/pull/1879)+* Standards compliance+    * [#1953](https://github.com/dhall-lang/dhall-haskell/pull/1953)+    * [#1954](https://github.com/dhall-lang/dhall-haskell/pull/1954)+    * [#1956](https://github.com/dhall-lang/dhall-haskell/pull/1956)+    * [#1957](https://github.com/dhall-lang/dhall-haskell/pull/1957)+    * [#1958](https://github.com/dhall-lang/dhall-haskell/pull/1958)+* Fixes and improvements to haddocks+    * [#1881](https://github.com/dhall-lang/dhall-haskell/pull/1881)+    * [#1955](https://github.com/dhall-lang/dhall-haskell/pull/1955)++1.33.1++* [Multi-line REPL / support `repline-0.4.0.0`](https://github.com/dhall-lang/dhall-haskell/pull/1867)+    * `dhall repl` supports a new `:paste` command that lets you input a command+       by pasting one or more lines++1.33.0++* [Supports version 17.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v17.0.0)+    * BREAKING CHANGE: [URLs no longer support quoted path components](https://github.com/dhall-lang/dhall-haskell/pull/1812)+    * BREAKING CHANGE: [`Optional/{fold,build}` are no longer built-ins](https://github.com/dhall-lang/dhall-haskell/pull/1802)+    * [Record fields now permit empty labels](https://github.com/dhall-lang/dhall-haskell/pull/1812)+* BREAKING CHANGE: [Fail instead of hanging when deriving `FromDhall` for recursive types](https://github.com/dhall-lang/dhall-haskell/pull/1825)+    * This is a breaking change as now the `expected` type returns an+      `Expector (Expr Src Void)` (essentially an `Either`) instead of+      `Expr Src Void`+    * If you really don't want to handle the new error-related wrapper, you can+      get the old behavior using a partial pattern match (which will be partial,+      still an improvement over the previous behavior, which was hanging)+* BREAKING CHANGE: [Records can no longer contain attributes named after language keywords](https://github.com/dhall-lang/dhall-haskell/pull/1801)+    * This is a bugfix, because the language standard disallows using+      keywords as record labels. However, some users were relying on+      this bug.+    * If you need to use a keyword as a record label, enclose it in backticks:+      ``{ `assert` = 1 }``.+* [Fix invalid cache entries](https://github.com/dhall-lang/dhall-haskell/pull/1793)+    * The interpreter will now correct cached expressions that are incorrect+      and warn you when this happens+    * Specifically, if there is a hash mismatch from the cached expression the+      interpreter will resolve the import again and fix the cache if the+      resolved import matches the expected hash+* [Make `encodeExpression` polymorphic](https://github.com/dhall-lang/dhall-haskell/pull/1789)+    * `encodeExpression` now has a more general type, which means that you+      can use it to serialise expressions without imports (i.e.+      ones of type `Expr Void Void`)+* [Add `--quiet` option for `dhall decode`](https://github.com/dhall-lang/dhall-haskell/pull/1803)+* [Add `--noted` flag for `dhall haskell-syntax-tree`](https://github.com/dhall-lang/dhall-haskell/pull/1843)+* Performance improvements:+    * There were several performance improvements related to binary decoding,+      which should improve cache lookup speed+    * [#1807](https://github.com/dhall-lang/dhall-haskell/pull/1807)+    * [#1809](https://github.com/dhall-lang/dhall-haskell/pull/1809)+    * [#1857](https://github.com/dhall-lang/dhall-haskell/pull/1857)+* Improvements to error messages+    * [#1824](https://github.com/dhall-lang/dhall-haskell/pull/1824)+    * [#1849](https://github.com/dhall-lang/dhall-haskell/pull/1849)+    * [#1851](https://github.com/dhall-lang/dhall-haskell/pull/1851)+* Fixes to haddocks+    * [#1815](https://github.com/dhall-lang/dhall-haskell/pull/1815)++1.32.0++* [Supports version 16.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v16.0.0)+    * BREAKING CHANGE: Change the precedence of `with` and `===`+        * The precedence change to `with` means that some old expressions that+          were valid now require explicit parentheses+    * BREAKING CHANGE: Use RFC7049bis encoding for `Double`s+        * This is a breaking change because the hashes of expressions with small+          `Double` literals will change now+    * Add support for unions mixing terms and types+        * For example, `< A : Bool | B : Type >` is legal now+        * You can now write `someRecord with a.b.c = x` to update a nested+          fields+* DEPRECATION: [Deprecate `Dhall.Parser.exprA`](https://github.com/dhall-lang/dhall-haskell/pull/1740)+    * `Dhall.Parser` module will eventually drop support for parsing custom+      import types+    * This is necessary in order to fix several parsing bugs and improve+      parsing error messages+* BUG FIX: [GHC Generics instance for `:+:` now uses `union`](https://github.com/dhall-lang/dhall-haskell/pull/1725)+    * This fixes a few subtle bugs in how Dhall unions are marshalled into+      Haskell types, and also improves the error messages+* Formatting improvements+    * [Change formatting of `if` expressions](https://github.com/dhall-lang/dhall-haskell/pull/1767)+    * [Change formatting for functions and their types](https://github.com/dhall-lang/dhall-haskell/pull/1759)+    * [Prefer puns when formatting record completions](https://github.com/dhall-lang/dhall-haskell/pull/1736)+* [Convert union alternatives to directory tree](https://github.com/dhall-lang/dhall-haskell/pull/1757)+    * `dhall to-directory-tree` now supports unions which are automatically+      unwrapped+* [Fix `dhall freeze --cache` to better handle protected imports](https://github.com/dhall-lang/dhall-haskell/pull/1772)+    * `dhall freeze --cache` will now also update imports that already have+      integrity checks+* [Don't normalized partially saturated `{List,Natural}/fold`](https://github.com/dhall-lang/dhall-haskell/pull/1742)+    * The behavior now matches the standard.  Previously, the Haskell+      implementation was not standards-compliant because it would normalize+      these partially saturated built-ins++1.31.1++* BUG FIX: [Allow whitespace after record pun entry](https://github.com/dhall-lang/dhall-haskell/pull/1733)+    * The record pun feature introduced in the previous release did not+      correctly parse record puns with trailing whitespace, which this change+      fixes.+* [Expose `{default,}InputNormalizer`](https://github.com/dhall-lang/dhall-haskell/pull/1727)+    * The previous version introduced a breaking change to the `autoWith` type+      that required access to the implementation of `InputNormalizer`, which was+      not exported.  This change fixes that.+* Build against latest dependencies+    * [`QuickCheck-2.14`](https://github.com/dhall-lang/dhall-haskell/pull/1721)+    * [`haskell-lsp-0.21`](https://github.com/dhall-lang/dhall-haskell/pull/1730)+    * [`repline-0.3` / `haskeline-0.8`](https://github.com/dhall-lang/dhall-haskell/pull/1717)+    * [`template-haskell-2.16`](https://github.com/dhall-lang/dhall-haskell/pull/1719)+* [Prefer to format using record puns when possible](https://github.com/dhall-lang/dhall-haskell/pull/1729)+    * `dhall format` will now reformat code to use record puns when applicable+* Fixes and improvements to error messages:+    * [#1721](https://github.com/dhall-lang/dhall-haskell/pull/1724)++1.31.0++* [Supports version 15.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v15.0.0)+    * [Implement `with` keyword](https://github.com/dhall-lang/dhall-haskell/pull/1685)+        * You can now write `someRecord with a.b.c = x` to update a nested+          fields+    * [Add support for record puns](https://github.com/dhall-lang/dhall-haskell/pull/1710)+        * You can now write `{ x, y }` as a shorthand for `{ x = x, y = y }`+* BREAKING CHANGE TO THE API: [Auto-derive `Generic`/`FromDhall`/`ToDhall` with Template Haskell](https://github.com/dhall-lang/dhall-haskell/pull/1682)+    * Now the `Dhall.TH.makeHaskell*` utilities will include these derived+      instances in the generated declarations+    * This is a breaking change since users were likely already generating these+      instances separately, which will now conflict with the included instances+* BREAKING CHANGE TO THE API: [`From/ToDhall` no longer takes `InterpretOptions` argument](https://github.com/dhall-lang/dhall-haskell/pull/1696)+    * The types of the `autoWith` and `injectWith` methods have changed to+      take an `InputNormalizer` instead of an `InterpretOptions`+        * Note that `InputNormalizer` is a subset of `InterpretOptions`+    * This is a breaking change to how derived `FromDhall` / `ToDhall` instances+      are customized to more closely match how other Haskell packages customize+      derived instances (e.g. `aeson` with `FromJSON` / `ToJSON`)+        * Previously you would customize the behavior globally by passing in+          a top-level `InterpretOptions` record to `autoWith`+        * Now you can customize the behavior locally on a per-instance basis+    * This change enables the following change ...+* [Add `Dhall.Deriving` module for `deriving-via` helpers](https://github.com/dhall-lang/dhall-haskell/pull/1700)+    * Now you can take advantage of the `-XDerivingVia` language extension to+      customize derived `FromDhall`/`ToDhall` instances, like this:+        * `deriving (FromDhall, ToDhall) via Codec (SetSingletonConstructors Bare) Name`+* BREAKING CHANGE TO THE LANGUAGE: [Match standard with respect to `using toMap`](https://github.com/dhall-lang/dhall-haskell/pull/1673)+    * `https://example.com using toMap customHeaders` is now a parse error+      and needs to be explicitly parenthesized as+      `https://example.com using (toMap customHeaders)`+    * The language standard had always required the parentheses, but the Haskell+      implementation was not correctly matching the standard+* [Fix formatting of indented comments containing empty lines](https://github.com/dhall-lang/dhall-haskell/pull/1688)+    * `dhall format` was previously not idempotent when formatting indented+      comments with empty lines+    * Specifically, the formatter kept indenting things further with each+      format, which this change fixes+* [Fix pretty-printer to preserve original numeric literals](https://github.com/dhall-lang/dhall-haskell/pull/1674)+    * Now `dhall format` will preserve numeric literals exactly how you wrote+      them+    * For example, `0xFF` will no longer be reformatted as `255`+* [Add `dhall to-directory-tree` support for `Map`s](https://github.com/dhall-lang/dhall-haskell/pull/1705)+    * `Map`s are now converted to directories (just like records)+* [Add manpage](https://github.com/dhall-lang/dhall-haskell/pull/1677)+    * ... mainly for the benefit of people packaging Dhall for various+      distributions+* [Group commands in CLI](https://github.com/dhall-lang/dhall-haskell/pull/1692)+    * The command-line `--help` output now groups commands into useful+      sections+* [Fix numeric parsing for GHCJS](https://github.com/dhall-lang/dhall-haskell/pull/1681)+    * The GHCJS backend for Dhall was failing to parse numbers, which this+      change fixes+* Fixes and improvements to error messages:+    * [#1656](https://github.com/dhall-lang/dhall-haskell/pull/1656)+    * [#1698](https://github.com/dhall-lang/dhall-haskell/pull/1698)+    * [#1702](https://github.com/dhall-lang/dhall-haskell/pull/1702)+* Fixes and improvements to the haddocks:+    * [#1708](https://github.com/dhall-lang/dhall-haskell/pull/1708)+    * [#1712](https://github.com/dhall-lang/dhall-haskell/pull/1712)++1.30.0++* [Supports version 14.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0)+* BREAKING CHANGE TO THE API: [Add `--check` flag to `dhall {lint,freeze}`](https://github.com/dhall-lang/dhall-haskell/pull/1636)+    * You can now use the `--check` flag to verify that a file has already been+      linted or frozen+    * This is a breaking change to the types used by the `Dhall.Format` module+* BREAKING CHANGE TO THE LANGUAGE: [Disallow `Natural` literals with leading zeros](https://github.com/dhall-lang/dhall-haskell/pull/1658)+    * Now a literal like `042` is no longer valid+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* BUG FIX: [Fix parsing of `Double` literal trailing whitespace](https://github.com/dhall-lang/dhall-haskell/pull/1647)+    * Certain expressions using `Double` literals would fail to parse, which this+      change fixes+* BUG FIX: [Use `DeriveLift` instead of GHC Generics to derive `Lift` ](https://github.com/dhall-lang/dhall-haskell/pull/1640)+    * This fixes a build failure on GHC 8.10+* [Drop support for GHC 7.10.3](https://github.com/dhall-lang/dhall-haskell/pull/1649)+    * GHC 8.0.2 is now the earliest supported version+* [Add support for dotted field syntax](https://github.com/dhall-lang/dhall-haskell/pull/1651)+    * `{ x.y.z = 1 }` now legal syntax for nested fields+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* [Add support for duplicate record fields](https://github.com/dhall-lang/dhall-haskell/pull/1643)+    * This combines with the previous feature to let you write+      `{ x.y = 1, x.z = True }`, which is equivalent to+      `{ x = { y = 1, z = True } }`+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* [Add `dhall lint` support for deprecating `Optional/{fold,build}`](https://github.com/dhall-lang/dhall-haskell/pull/1628)+    * The `Optional/{fold,build}` built-ins are deprecated and can be implemented+      in terms of other language features+    * `Optional/fold` can be implemented in terms of `merge` (which now works on+      `Optional` values)+    * `Optional/build` could always be implemented using `Some`/`None`+    * `dhall lint` now transforms the deprecated built-ins to use their+      equivalent built-in-free versions+* [Support Template Haskell for multiple datatypes](https://github.com/dhall-lang/dhall-haskell/pull/1664)+    * This extends the Template Haskell support added in the previous release to+      work for datatypes that refer to one another+* [Add support for custom substitutions](https://github.com/dhall-lang/dhall-haskell/pull/1650)+    * You can now add custom substitutions, which are like `let` bindings that+      propagate to transitive imports+* [Small formatting fixes](https://github.com/dhall-lang/dhall-haskell/pull/1652)++1.29.0++* [Supports version 13.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0)+* BREAKING CHANGE: [Generate Haskell datatype declarations from Dhall types](https://github.com/dhall-lang/dhall-haskell/commit/b0280826790930d18a5498fb802120478fa11767#diff-a9729dccf50be61ce3d8c68c16f0fd50)+    * You can now use the `makeHaskellTypeFromUnion` Template Haskell utility+      to generate a Haskell datatype declaration from a Dhall union type+    * This helps ensure that your Haskell types and Dhall types stay in sync,+      when you want the Dhall type to be the source of truth+    * This is a breaking change because the default `InterpretOptions` changed+      the default handling of singleton constructors from `Wrapped` to `Smart`+    * You can preserve the old behavior using:+      `autoWith defaultInterpretOptions{ singletonConstructors = Wrapped }`+* BUG FIX: [Fix `dhall freeze --cache` and `dhall lint` to preserve `let`-related comments](https://github.com/dhall-lang/dhall-haskell/pull/1597)+    * Now they match the behavior of `dhall format` with regard to preserving+      these comments+* BUG FIX: [Fix escaping of significant leading whitespace when formatting code](https://github.com/dhall-lang/dhall-haskell/pull/1598)+    * The formatter would sometimes unnecessarily escape significant leading+      whitespace for the final line of multiline string literals, which this+      change fixes+* BUG FIX: [Fix `dhall encode --json` for `Double` values](https://github.com/dhall-lang/dhall-haskell/issues/1350)+* NEW FEATURE: [`dhall to-directory-tree` command](https://github.com/dhall-lang/dhall-haskell/pull/1606)+    * You can now generate a directory tree from a Dhall expression+    * Specifically:+        * records are converted to directories+        * `Text` fields are converted to files named after the field+        * `Optional` values are omitted if `None`+        * Everything else is rejected+* NEW FEATURE: [Hexadecimal literals](https://github.com/dhall-lang/dhall-haskell/pull/1607)+    * See the [changelog for standard version 13.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0) for more details+* NEW FEATURE: [`merge` works on `Optional` values](https://github.com/dhall-lang/dhall-haskell/pull/1608)+    * See the [changelog for standard version 13.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0) for more details+* [Improve formatter](https://github.com/dhall-lang/dhall-haskell/pull/1609)+    * `dhall format` will now render expressions nested inside record fields or+      alternatives more compactly, including:+        * Records+        * Record completion expressions+        * Expressions wrapped in `Some`+        * Lists+* [Exclude the `using ...` suffix from imports listed by `dhall resolve`](https://github.com/dhall-lang/dhall-haskell/pull/1603)+    * Specifically when using the `--{immediate,transitive}-dependencies` flags++1.28.0++* [Supports version 12.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0)+* BREAKING CHANGE: [Add `Integer/{clamp,negate}` built-ins](https://github.com/dhall-lang/dhall-haskell/pull/1486)+    * This is a technically breaking change API since this adds a new+      constructor to the `Expr` type+    * This is also a technically breaking change to the language.  See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* BREAKING CHANGE: [Remove support for fusion](https://github.com/dhall-lang/dhall-haskell/pull/1478)+    * This is also a technically breaking change to the language.  See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* BREAKING CHANGE: [Parse whitespace more precisely](https://github.com/dhall-lang/dhall-haskell/pull/1483)+    * The Haskell implementation now matches the official grammar much more+      closely, but as a result will now reject some programs that it used to+      accept+    * For example, `1:Natural` used to be valid and now is no longer valid as+      the standard requires mandatory whitespace after the `:`+    * Consult the [standard grammar](https://github.com/dhall-lang/dhall-lang/blob/master/standard/dhall.abnf) if you run into a new parsing error as a result of this change+    * This is also a parsing performance regression (specifically for parsing+      comments), but should not be noticeable in practice.  See [#1512](https://github.com/dhall-lang/dhall-haskell/pull/1512) for more details+* BREAKING CHANGE: Rename `Type` to `Decoder` and `InputType` to `Encoder` [#1483](https://github.com/dhall-lang/dhall-haskell/pull/1485) / [#1489](https://github.com/dhall-lang/dhall-haskell/pull/1489)+* BUG FIX: [Fix `dhall format --check`](https://github.com/dhall-lang/dhall-haskell/pull/1462)+    * Before this change `dhall format --check` would fail due to attempting to+      read all of standard input in twice+* BUG FIX: [Fix `dhall freeze` to always re-freeze an import](https://github.com/dhall-lang/dhall-haskell/pull/1471)+    * Before this fix, `dhall freeze` would not attempt to refreeze an already+      frozen import+* [Permit spaces around completion operator](https://github.com/dhall-lang/dhall-haskell/pull/1532)+    * See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* [Make `missing` referentially transparent](https://github.com/dhall-lang/dhall-haskell/pull/1509)+    * `missing` can now be imported transitively via a remote import+    * Normally resolving `missing` would still still fail, except for+      `missing as Location`, which is now a valid transitive import+    * See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* [Write cache files atomically](https://github.com/dhall-lang/dhall-haskell/pull/1544)+    * This is a resilience improvement so that the cache is not left in a+      corrupt state in the event of a power outage or exhausting disk/memory+* [New `Dhall.function` utility](https://github.com/dhall-lang/dhall-haskell/pull/1507)+    * This is provides the same functionality as the `Interpret` instance for+      `(->)`, except without the use of typeclasses+* [New `dhall haskell-syntax-tree` command](https://github.com/dhall-lang/dhall-haskell/pull/1553)+    * This command displays the Haskell syntax tree of an expression+      (primarily for debugging purposes)+    * Note that this is highly-volatile and subject to change, so don't depend+      on this programmatically.  We may break the output of this command without+      any notice.+* [Add `instance Show Ann`](https://github.com/dhall-lang/dhall-haskell/pull/1567)+* [Move normalization code from `Dhall.Core` to `Dhall.Normalize`](https://github.com/dhall-lang/dhall-haskell/pull/1452)+    * Note that this is not a breaking change.  The relocated utilities are+      still re-exported from `Dhall.Core`+* [Fix `dhall resolve --transitive-dependencies` to list dependencies in "post-order"](https://github.com/dhall-lang/dhall-haskell/pull/1539)+* Performance improvements+    * [#1500](https://github.com/dhall-lang/dhall-haskell/pull/1500)+    * [#1522](https://github.com/dhall-lang/dhall-haskell/pull/1522)+    * [#1568](https://github.com/dhall-lang/dhall-haskell/pull/1568)+    * [#1580](https://github.com/dhall-lang/dhall-haskell/pull/1578)+* Fixes and improvements to code formatting+    * [#1460](https://github.com/dhall-lang/dhall-haskell/pull/1460)+    * [#1466](https://github.com/dhall-lang/dhall-haskell/pull/1466)+    * [#1508](https://github.com/dhall-lang/dhall-haskell/pull/1508)+    * [#1527](https://github.com/dhall-lang/dhall-haskell/pull/1527)+    * [#1422](https://github.com/dhall-lang/dhall-haskell/pull/1422)+    * [#1552](https://github.com/dhall-lang/dhall-haskell/pull/1552)+    * [#1543](https://github.com/dhall-lang/dhall-haskell/pull/1543)+    * [#1554](https://github.com/dhall-lang/dhall-haskell/pull/1554)+    * [#1569](https://github.com/dhall-lang/dhall-haskell/pull/1569)+* Fixes and improvements to code linting+    * [#1518](https://github.com/dhall-lang/dhall-haskell/pull/1518)+    * [#1531](https://github.com/dhall-lang/dhall-haskell/pull/1531)+* Fixes and improvements to error messages+    * [#1443](https://github.com/dhall-lang/dhall-haskell/pull/1443)+    * [#1448](https://github.com/dhall-lang/dhall-haskell/pull/1448)+    * [#1482](https://github.com/dhall-lang/dhall-haskell/pull/1482)+    * [#1519](https://github.com/dhall-lang/dhall-haskell/pull/1519)+    * [#1556](https://github.com/dhall-lang/dhall-haskell/pull/1556)+    * [#1528](https://github.com/dhall-lang/dhall-haskell/pull/1528)+* Fixes and improvements to the parser+    * [#1473](https://github.com/dhall-lang/dhall-haskell/pull/1473)+    * [#1549](https://github.com/dhall-lang/dhall-haskell/pull/1549)+    * [#1563](https://github.com/dhall-lang/dhall-haskell/pull/1563)+    * [#1584](https://github.com/dhall-lang/dhall-haskell/pull/1584)+* Fixes and improvements to diffs+    * [#1585](https://github.com/dhall-lang/dhall-haskell/pull/1585)+* Fixes and improvements to the REPL+    * [#1573](https://github.com/dhall-lang/dhall-haskell/pull/1573)+* Fixes and improvements to documentation+    * [#1530](https://github.com/dhall-lang/dhall-haskell/pull/1530)++1.27.0++* [Supports version 11.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0)+* BREAKING CHANGE: Rename `Inject`/`Interpret` to `ToDhall`/`FromDhall`+    * This change `ConstraintKinds` to minimize disruption by keeping around+      `Inject`/`Interpret` as synonyms for `ToDhall`/`FromDhall`+    * In other words, constraints and derived instances using `Inject` or+      `Interpret` will still work+    * However, manual instances using `Inject` or `Interpret` won't work+      unless you rename them to `ToDhall`/`FromDhall` or enable the+      `TypeSynonymInstances` extension+* BREAKING CHANGE: Fix `Eq` instance for `Expr`s with special `Double`s+    * This fixes the `Eq` instance for `Expr`s to match the standard regarding+      `Double` comparisons+    * Specifically: `NaN == NaN` and `-0.0 /= 0.0`+    * This is a breaking change because the `DoubleLit` constructor of `Expr`+      now stores a `DhallDouble` instead of a `Double`+* BREAKING CHANGE: [Add `--file` option for `dhall hash`](https://github.com/dhall-lang/dhall-haskell/pull/1445)+    * This is a breaking change because it also removes the `Dhall.Hash` module,+      which wasn't really carrying its own weight+* [Add support for leading separators](https://github.com/dhall-lang/dhall-haskell/pull/1355)+    * See the [changelog for standard version 11.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0) for more details+* [Add record completion operator](https://github.com/dhall-lang/dhall-haskell/pull/1375)+    * See the [changelog for standard version 11.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0) for more details+* [Add `dhall tags` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/1398)+    * This generates an ETags file from an input file or directory+* [Add `dhall lint` support for fixing malformed assertions](https://github.com/dhall-lang/dhall-haskell/pull/1353)+    * `dhall lint` now fixes `let example = foo === bar` to be+       `let example = assert : foo === bar`+* Normalize inferred types [#1337](https://github.com/dhall-lang/dhall-haskell/pull/1337)+* New `FromDhall`/`ToDhall` (previously `Interpret`/`Inject`) instances for:+    * [`Void`](https://github.com/dhall-lang/dhall-haskell/pull/1382)+    * `Map` [#1391](https://github.com/dhall-lang/dhall-haskell/pull/1391) / [#1412](https://github.com/dhall-lang/dhall-haskell/pull/1412)+    * [`HashMap`](https://github.com/dhall-lang/dhall-haskell/pull/1426)+    * [`Set` and `HashSet`](https://github.com/dhall-lang/dhall-haskell/pull/1405)+    * [`()`](https://github.com/dhall-lang/dhall-haskell/pull/1388)+* [Add `--output` option to `dhall`](https://github.com/dhall-lang/dhall-haskell/pull/1399)+* [Move syntax things from `Dhall.Core` to a new `Dhall.Syntax` module](https://github.com/dhall-lang/dhall-haskell/pull/1440)+    * This is not a breaking change.  `Dhall.Core` still re-exports the same+      API as before+* Performance improvements+    * [#1362](https://github.com/dhall-lang/dhall-haskell/pull/1362)+    * [#1366](https://github.com/dhall-lang/dhall-haskell/pull/1366)+    * [#1368](https://github.com/dhall-lang/dhall-haskell/pull/1368)+    * [#1397](https://github.com/dhall-lang/dhall-haskell/pull/1397)+    * [#1401](https://github.com/dhall-lang/dhall-haskell/pull/1401)+* Fixes and improvements to code formatting+    * [#1360](https://github.com/dhall-lang/dhall-haskell/pull/1360)+    * [#1372](https://github.com/dhall-lang/dhall-haskell/pull/1372)+    * [#1380](https://github.com/dhall-lang/dhall-haskell/pull/1380)+    * [#1415](https://github.com/dhall-lang/dhall-haskell/pull/1415)++1.26.1++* TECHNICALLY BREAKING CHANGES: [Simplify `⫽` within projection](https://github.com/dhall-lang/dhall-haskell/pull/1283) / [Simplify nested record projections](https://github.com/dhall-lang/dhall-haskell/pull/1307)+    * These are technically breaking changes because you will need to update+      integrity checks that protect code simplified in this way+    * We're not bumping the major version since the likelihood that you're+      affected is quite low+* BUG FIX: [Fix performance regression](https://github.com/dhall-lang/dhall-haskell/pull/1335)+    * This change fixes the performance regression introduced in the previous+      release (version 1.26.0)+* BUG FIX: [Prevent REPL from inserting inferred `Sort`s into context](https://github.com/dhall-lang/dhall-haskell/pull/1318)+    * This protects the REPL from getting hosed if you define an expression+      using `:let` that has an inferred type of `Sort`+* NEW FEATURE: Improved `Inject`/`Interpret` support for 1-field constructors - ([#1315](https://github.com/dhall-lang/dhall-haskell/pull/1315) / [#1321](https://github.com/dhall-lang/dhall-haskell/pull/1321))+    * This adds a new `singletonConstructors` field to `InterpretOptions` that+      lets you control what Dhall type 1-field Haskell constructors correspond+      to+    * The default (`Wrapped`) is backwards compatible with the old behavior+    * The `Smart` option is probably what you want: it will strip the+      Haskell constructor from the Dhall type if the constructor has one+      anonymous field+    * The `Bare` option always strips 1-field Haskell constructors from the+      Dhall type+* NEW FEATURE: `--censor` flag that disables source code display ([#1312](https://github.com/dhall-lang/dhall-haskell/pull/1312) / [#1329](https://github.com/dhall-lang/dhall-haskell/pull/1329))+    * Use this flag when you don't want sensitive `Text` literals showing up in+      parsing or type-checking error messages+* [Format record fields more compactly if they fit on 1 line](https://github.com/dhall-lang/dhall-haskell/pull/1314)+    * The formatter will now format record fields on a field-by-field basis to+      avoid unnecessary vertical sprawl of formatted records+    * Specifically, record fields that fit on one line will now be formatted+      on one line+* [Add `--quiet` option to `dhall type`](https://github.com/dhall-lang/dhall-haskell/pull/1325)+    * This lets you use `dhall type` in "check only" mode (e.g. for CI for+      for development feedback)+* Improved GHCJS support - ([#1311](https://github.com/dhall-lang/dhall-haskell/pull/1311) / [#1330](https://github.com/dhall-lang/dhall-haskell/pull/1330))+* [Fix all executables to accept `--version`](https://github.com/dhall-lang/dhall-haskell/pull/1334)+    * Note that the `dhall version` subcommand is still supported, too+* [New `Dhall.Version` module](https://github.com/dhall-lang/dhall-haskell/pull/1332)+* [Don't normalize inferred types](https://github.com/dhall-lang/dhall-haskell/pull/1317)+    * This fixes `dhall type` to more accurately follow the standard+* [Initial changes for GHC 8.8 support](https://github.com/dhall-lang/dhall-haskell/pull/1324)+* [Fix Haddock formatting for `dhallFromJSON`](https://github.com/dhall-lang/dhall-haskell/pull/1316)+* [Improved Windows caching support](https://github.com/dhall-lang/dhall-haskell/pull/1272)+    * `dhall` will now prefer the `%LOCALAPPDATA%` directory for caching if it is+      available+* [Warn about missing cache directories](https://github.com/dhall-lang/dhall-haskell/pull/1320)++1.26.0++* [Supports version 10.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0)+* BREAKING CHANGE TO THE LANGUAGE: [Remove old union literal syntax](https://github.com/dhall-lang/dhall-haskell/pull/1176)+    * Union literals of the form `< x = e | ... >` are no longer valid+    * For more details, see: [Migration: Deprecation of old union literal syntax](https://github.com/dhall-lang/dhall-lang/wiki/Migration%3A-Deprecation-of-old-union-literal-syntax)+    * Also see the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* BREAKING CHANGE TO THE API: [Change `X` to be a type synonym for `Data.Void`](https://github.com/dhall-lang/dhall-haskell/pull/1172)+    * This is a breaking change if you were previously pattern matching on the+      `X` constructor.  You can replace that with the use of `Data.Void.absurd`+* BREAKING CHANGE TO THE API: [Treat multi-`let`s as syntactic sugar](https://github.com/dhall-lang/dhall-haskell/pull/1242)+    * This is a breaking change because the `Let` constructor now only stores+      one `Binding` instead of a `NonEmpty` list of `Binding`s+* PERFORMANCE REGRESSION & TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Dependent types](https://github.com/dhall-lang/dhall-haskell/pull/1164)+    * You can now write functions from terms to types+    * There is also now language support for tests of the form+      `assert : x === y`+    * This deteriorates the performance of large multi-`let` expressions+      (See: [#1306](https://github.com/dhall-lang/dhall-haskell/issues/1306))+    * Splitting large multi-`let` expressions into smaller files may mitigate+      the problem as a work-around for now+    * Follow [#1129](https://github.com/dhall-lang/dhall-haskell/issues/1129)+      for work to fix this performance regression+    * This is also a technically breaking change because `assert` is now a+      reserved keyword+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Add `Natural/subtract` built-in](https://github.com/dhall-lang/dhall-haskell/pull/1133)+    * The language now supports machine subtraction, which can be used to+      support several other high-performance operations (like `Natural`+      comparisons)+    * This is a technically breaking change if you used `Natural/subtract` as an+      identifier in your code+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [More simplifications for field selection](https://github.com/dhall-lang/dhall-haskell/pull/1174)+    * Now the interpreter will more intelligently simplify certain field+      projections+    * For example: `λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).{ a, c }.c`+      will now simplify to `λ(x : { a : Bool, b : Bool }) → 0 `+    * This is a technically breaking change because you will need to update+      integrity checks that protect code simplified in this way+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Simplify `⫽` when its arguments are equivalent](https://github.com/dhall-lang/dhall-haskell/pull/1196)+    * This is a technically breaking change for the same reason: this will+      perturb semantic integrity checks for affected code+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* NEW FEATURE: [Restore support for records containing both types and terms](https://github.com/dhall-lang/dhall-haskell/pull/1173)+    * In other words `{ foo = 1, bar = Bool }` is now valid again+    * This means that you now can export a single package containing both types+      and terms+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* [`dhall format` now preserves `let` comments](https://github.com/dhall-lang/dhall-haskell/pull/1273)+    * `dhall` format will now preserve comments in the following locations of+      a `let` binding:+    * `let {- HERE -} x {- HERE -} : {- HERE -} Bool = {- HERE -} True in x`+    * This support handles both single-line and multi-line comments and also+      takes care of correctly indenting/dedenting them+    * Note that comments before the `let` keyword are still not preserved+      (unless it is the beginning of the file)+* [Add API support for marshalling recursive types](https://github.com/dhall-lang/dhall-haskell/pull/1195)+    * You can now marshal recursive types from Dhall into Haskell using the+      newly-added utilities+    * See also: [#1298](https://github.com/dhall-lang/dhall-haskell/pull/1298)+* [New `:help` command for `dhall repl`](https://github.com/dhall-lang/dhall-haskell/pull/1237)+* New `--no-cache` flag [#1290](https://github.com/dhall-lang/dhall-haskell/pull/1290) / [#1434](https://github.com/dhall-lang/dhall-haskell/pull/1434) / [#1436](https://github.com/dhall-lang/dhall-haskell/pull/1436)+    * You can now disable use of the cache with this flag+    * This comes in handy if you want to disable α-normalization for imports+      protected by a semantic integrity check+* Bug fixes+    * [Fix `isNormalized` for field selections](https://github.com/dhall-lang/dhall-haskell/pull/1210)+    * [Simplify `Natural/subtract` when its arguments are equivalent](https://github.com/dhall-lang/dhall-haskell/pull/1220)+    * [Fix `NaN` to be judgmentally equivalent to itself](https://github.com/dhall-lang/dhall-haskell/pull/1231)+    * [Fix `Inject` instance for lists](https://github.com/dhall-lang/dhall-haskell/pull/1261)+    * [Fix typechecking of `toMap`](https://github.com/dhall-lang/dhall-haskell/pull/1279)+* Performance optimizations+    * [Optimize a few `Set` instances](https://github.com/dhall-lang/dhall-haskell/pull/1184)+    * [Remove some redundant sorting during normalization](https://github.com/dhall-lang/dhall-haskell/pull/1228)+* Improvements to error messages+    * [Improve error reporting for failed remote imports](https://github.com/dhall-lang/dhall-haskell/pull/1188)+    * [Improve HTTP errors](https://github.com/dhall-lang/dhall-haskell/pull/1253)+* Improvements to formatting+    * [Indent function arguments when formatting](https://github.com/dhall-lang/dhall-haskell/pull/1167)+    * [Prefer unquoted URLs](https://github.com/dhall-lang/dhall-haskell/pull/1235)+    * [Strip leading whitespace](https://github.com/dhall-lang/dhall-haskell/pull/1270)+* Improvements to diffs+    * [Fix diffs for lists](https://github.com/dhall-lang/dhall-haskell/pull/1213)+    * [Improve diff for non-empty lists](https://github.com/dhall-lang/dhall-haskell/pull/1244)+    * [Small fixes to `dhall diff`](https://github.com/dhall-lang/dhall-haskell/pull/1263)+* Improvements to documentation+    * [Fix documentation for `UnionInputType`](https://github.com/dhall-lang/dhall-haskell/pull/1230)+    * [Document support for caching protected imports](https://github.com/dhall-lang/dhall-haskell/pull/1247)+* Improvements to command-line interface+    * [Improve description of `dhall lint`](https://github.com/dhall-lang/dhall-haskell/pull/1264)+    * [Change `dhall type` to resolve imports](https://github.com/dhall-lang/dhall-haskell/pull/1281)++1.25.0++* Supports version 9.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v9.0.0+* BREAKING CHANGE: Remove support for old-style `List`-like `Optional` literals+    * List-like `Optional` Literals (i.e. `[ 1 ] : Optional Natural`) are no+      longer valid+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1002+* BREAKING CHANGE: Add support for semi-semantic caching+    * This change significantly improves the performance of imports+    * This change also automatically caches imports without an integrity check+    * This changes several types in `Dhall.Import` to support this new+      feature+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1113+* BREAKING CHANGE: Implement new Unicode braced escape sequence+    * Escape sequences encoding surrogate pairs are no longer valid+    * Instead, characters previously encoded as surrogate pairs can instead be+      encoded as a braced sequence+    * For example: "\uD834\uDD1E" must now be written as "\u{1D11E}"+    * See: https://github.com/dhall-lang/dhall-haskell/pull/987+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1104+* BREAKING CHANGE: Make the type of extract richer:+    * `Dhall.extract` can now return a detailed error instead of just a `Maybe`+    * This is a breaking chnage because the type of `extract` changed+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1011+* BREAKING CHANGE: Add support for importing expressions `as Location`+    * This is a breaking change because a new `Location` constructor was added+      to `ImportMode`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1019+* BREAKING CHANGE: Switch `Var` to use an `Int`+    * This is a performance improvement, but also a breaking change since the+      `Integer` in the `Var` constructor was changed to an `Int`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1044+* BREAKING CHANGE: Add new `toMap` keyword+    * This is a breaking change to the API because a new `ToMap` constructor+      was added to the `Expr` type+    * This is also a technically breaking change to the language because `toMap`+      is now a reserved keyword, although most code should be unaffected in+      practice+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1041+* BREAKING CHANGE: Sort the fields of a record projection during normalization+    * This is a technically breaking change to the language because any+      expressions with an uninterpreted record projection will have a different+      semantic integrity check.  However, most could should be unaffected in+      practice+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1111+* BUG FIX: Fix substitution into record projection by type+    * An expression like this one was being incorrectly rejected:+      `let e = { a = 10, b = "Text" } let s = { a : Natural } in e.(s)`, which+      this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1012+* BUG FIX: Reject record projection when there is a field type mismatch+    * Record projection by type was previously not checking the expected+      field types, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1027+* BUG FIX: Fix linting of unused let bindings+    * Certain let bindings were not correctly detected as unused, which this+      change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1001+* BUG FIX: Fix `--file` option+    * The `--file` option from the previous release did not work, due to not+      computing relative paths correctly, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1004+* BUG FIX: Minor fix to `dhall diff`+    * `dhall diff` was incorrectly displaying spurious differences for+      identical lists that were function arguments, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1006+* BUG FIX: Allow `Sort` as type annotation+    * This should have been implemented in the previous release as part of+      supporting version 8.0.0 of the standard, but was missed+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1024+* BUG FIX: `Dhall.Map`: Reflect original key ordering in `Ord` instance+    * `Dhall.Map` now considers key order when comparing `Map`s, which it should+      have done before, but didn't+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1050+* BUG FIX: Consistently format multi-line strings+    * The formatter now formats naked multi-line strings the same as nested+      multi-line strings+    * Specifically, naked multi-line strings can now be formatted on a single+      (just like nested multi-line strings)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1056+* BUG FIX: Make `isNormalized` consistent with `normalize`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1115+* BUG FIX: Make `normalizeWithM` consistent with `normalize`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1126+* BUG FIX: Fix import alternatives to recover from type errors+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1152+* Feature: Semi-semantic caching+    * The Haskell implementation now implicitly caches *all* local imports, not+      just imports frozen by integrity checks, so that you don't have to freeze+      them when doing local development+    * These cached imports are still correctly invalidated if they or any of+      their dependencies change+    * This new implicit cache is stored underneath `~/.cache/dhall-haskell` by+      default+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1154+* Feature: New `dhall text` subcommand+    * This new subcommand supersedes the old `dhall-to-text` executable+* Feature: Add `instance Lift (Expr s a)`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1119+* Fixes and improvements to error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1030+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1137+* Fixes and improvements to tests:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1155+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1159+* Performance improvements+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1036+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1051+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1048+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1057+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1065+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1066+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1085++1.24.0++* Supports version 8.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v8.0.0+* BREAKING CHANGE: Allow tabs and blank lines in multi-line strings+    * Blank lines are now ignored for the purpose of dedenting multiline strings+    * Lines with leading tabs (or mixed tabs and spaces) are now dedented, too,+      so long as they all share the same prefix+    * This is technically a breaking change, but unlikely to affect programs+      in practice, especially if they were formatted with `dhall format`.  This+      change mainly affects programs that were not indented correctly.+    * See the changelog for standard version 8.0.0 for more details+* BREAKING CHANGE: Simplify bare interpolations+    * Expressions like `λ(x : Text) → "${x}"` now simplify to `λ(x : Text) → x`+    * This is a technically breaking change because it changes how these sorts+      of expressions are serialized.  This does not affect semantic integrity+      checks and the new simplified expressions are extensionally equivalent to+      their older counterpart expressions.+    * See the changelog for standard version 8.0.0 for more details+* BREAKING CHANGE: Encode integrity check as multihash+    * Semantic integrity checks are now encoded using the multihash spec+    * This is a technically breaking change that does not perturb the hash for+      user-facing semantic integrity checks.  This only affects how expressions+      with unresolved imports are serialized, but semantic integrity checks are+      only computed for fully-resolved imports.+    * See the changelog for standard version 8.0.0 for more details+* BUG FIX: Fix type-checker to reject invalid record type annotations+    * e.g. `{ x = 1 } : { x : Text }` was not properly rejected by the type+      checker+    * See: https://github.com/dhall-lang/dhall-haskell/pull/965+* BUG FIX: Custom header forwarding fixed+    * Forwarding custom headers could previously fail in various ways, such as:+        * Cyclic imports leading to endless network requests+        * Resolving a non-existent import for the custom headers+        * Resolving an existing but incorrect import for the custom headers+    * This change fixes that by forwarding custom headers by value instead of+      by reference+    * See: https://github.com/dhall-lang/dhall-haskell/pull/967+* BUG FIX: Fix GHCJS support+    * `Natural/fold` was broken in version 1.22, which this change fixes+    * Specifically, it would hang for `Natural` numbers greater than 1+    * See: https://github.com/dhall-lang/dhall-haskell/pull/985+* BUG FIX: `dhall diff` no longer double-prints key-value separators+    * See: https://github.com/dhall-lang/dhall-haskell/pull/952+* Feature: Record projection by expression+    * You can now project out a subset of record fields by the expected type+    * `let t = { x : Natural } let p = { x = 1, y = 2 } in p.(t) = { x = 1 }`+    * See the changelog for standard version 8.0.0 for more details+* Feature: Inline headers+    * You no longer need to specify custom headers in a separate import.  You+      can now specify them inline within the same file.+    * e.g.: `https://example.com/x using [ { header = "Foo", value = "Bar" } ]`+    * See the changelog for standard version 8.0.0 for more details+* Feature: Allow `Sort` as a type annotation+    * An expression such as `Kind → Kind : Sort` will now type-check+    * `Sort` is still disallowed outside of a type annotation+    * See the changelog for standard version 8.0.0 for more details+* Feature: Allow self-describe-cbor when decoding+    * Dhall expressions serialized as CBOR can be tagged to describe themselves+      as CBOR without affecting decoding+    * See the changelog for standard version 8.0.0 for more details+* Feature: New `--file` option for `dhall` commands+    * In other words, instead of `dhall <<< './some/file` you can now use+      `dhall --file some/file`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/949+* Feature: New `--cache` flag for `dhall freeze` command+    * This automates the idiom used by the Prelude to optimistically cache+      imports but gracefully degrade if the semantic integrity check fails+    * See: https://github.com/dhall-lang/dhall-haskell/pull/980+* Feature: Add `:clear` command to `dhall repl`+    * This deletes previous bindings from the history so that they can be+      garbage collected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/966+* Feature: New `chunkExprs` `Traversal` added to `Dhall.Core`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/954+* Feature: New `Dhall.Optics` module+    * This re-exports some convenient @lens@ utilities used internally for+      packages trying to avoid a @lens@ dependency+    * See: https://github.com/dhall-lang/dhall-haskell/pull/986+* More GHC 8.8 support+    * See: https://github.com/dhall-lang/dhall-haskell/pull/961++1.23.0++* BREAKING CHANGE: Fix marshaling union literals+    * 1.22.0 introduced two separate bugs in marshaling union literals between+      Dhall and Haskell, which this release fixes:+        * Dhall enums did not correctly map onto Haskell enums+        * New-style union literals (i.e. `< A : T >.A x`) were not correctly+          supported+    * See: https://github.com/dhall-lang/dhall-haskell/pull/918+    * See: https://github.com/dhall-lang/dhall-haskell/pull/927+    * See: https://github.com/dhall-lang/dhall-haskell/pull/936+* BUG FIX: Fix α-normalization+    * Version 1.22.0 introduced a new faster evaluation algorithm, but the new+      algorithm introduced two α-normalization regression, which this release+      fixes+    * The primary effect of this bug was that semantic integrity checks would+      fail for expressions that contain an `if`/`then`/else` expression in their+      normal form+    * See: https://github.com/dhall-lang/dhall-haskell/pull/931+    * See: https://github.com/dhall-lang/dhall-haskell/pull/938+* BUG FIX: Fix merging of sort-level record types+    * The language standard requires that `{ a : Kind } ⩓ { b : Kind }` is+      valid, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/891+* BUG FIX: `dhall freeze` respects the `--ascii` flag+    * See: https://github.com/dhall-lang/dhall-haskell/pull/934+* BUG FIX: Don't autocomplete fields for record types+    * This prevents the REPL from expanding `{ x : T }.<TAB>` to `{ x : T }.x`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/937+* Support `MonadFail`-related changes in GHC 8.8+    * See: https://github.com/dhall-lang/dhall-haskell/pull/912+* Add `cross` flag to simplify cross-compilation+    * This allows the `dhall` package to be built without using+      `TemplateHaskell`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/928+* Increase lines of context for error messages+    * Error messages now provide at least 20 lines of context instead of 3+      before truncating large expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/916+* Add line numbers to error messages+    * The bottom of every Dhall type error includes the original source code,+      which now has line numbers on the left margin+    * See: https://github.com/dhall-lang/dhall-haskell/pull/919+* Expand lower bounds on `megaparsec`/`transformers-compat` dependencies+    * This is to support `dhall` on Debian Sid+    * See: https://github.com/dhall-lang/dhall-haskell/pull/939++1.22.0++* Supports version 7.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v7.0.0+* BREAKING CHANGE: Add support for empty alternatives+    * The `Union` type now has an optional (`Maybe`) type for each alternative+    * See the changelog for standard version 7.0.0 for more details+    * See: https://github.com/dhall-lang/dhall-haskell/pull/863+* BREAKING CHANGE: Remove support for URL fragments+    * The `URL` type no longer has a field for a URL fragment since the language+      no longer supports fragments+    * See the changelog for standard version 7.0.0 for more details+    * See: https://github.com/dhall-lang/dhall-haskell/pull/851+* BREAKING CHANGE: Remove deprecated `Path` type synonym+    * See: https://github.com/dhall-lang/dhall-haskell/pull/858+* BUG FIX: Correctly parse identifiers beginning with `http`+    * i.e. `httpPort` was supposed to be a valid identifier name and now is+    * See: https://github.com/dhall-lang/dhall-haskell/pull/870+* BUG FIX: Fix `dhall encode` bug+    * `dhall encode` bug was generating binary expressions that were valid+      (i.e. they would decode correctly) but were non-standard (i.e. hashing+      them would not match the hash you would normally get from a semantic+      integrity check)+    * Semantic integrity checks were not affected by this bug since they used+      a slightly different code path that generated the correct binary input to+      the hash.  Only the `dhall decode` subcommand was affected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/859+* BUG FIX: Fix for `Dhall.UnionType`+    * This fixes some expressions that would previously fail to marshal into+      Haskell, specifically those were the marshalling logic was built using+      the `UnionType` utilities+    * See: https://github.com/dhall-lang/dhall-haskell/pull/857+* Feature: New `--alpha` flag to α-normalize command-line output+    * See: https://github.com/dhall-lang/dhall-haskell/pull/855+* Performance improvements+    * The normalizer is now *much* faster+    * See: https://github.com/dhall-lang/dhall-haskell/pull/876++1.21.0++* Supports version 6.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v6.0.0+* BREAKING CHANGE: Remove the `constructors` keyword+    * ... as standardized in version 6.0.0 of the language standard+    * The deprecation cycle is over, so the keyword is no longer supported+    * For more details, see: https://github.com/dhall-lang/dhall-lang/wiki/Migration%3A-Deprecation-of-constructors-keyword+    * See: https://github.com/dhall-lang/dhall-haskell/pull/829+* BREAKING CHANGE: CBOR-encode only special `Double`s as half-floats+    * ... as standardized in version 6.0.0 of the language standard+    * CBOR `Double`s except `Infinity`/`-Infinity`/`NaN`/`0.0` are now encoded in at+      least 32 bits+    * See: https://github.com/dhall-lang/dhall-haskell/pull/822+* BREAKING CHANGE: Sort record and union fields when CBOR-encoding+    * Fields and alternatives are now sorted when serialized+    * This does not affect semantic integrity checks, which already sorted these+      fields/alternatives before hashing expressions+    * This does affect the serialization of expressions that have not been+      normalized (e.g. uninterpreted expressions transmitted over the wire)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/835+* BUG FIX: Fix non-exhaustive pattern match in `dhall lint`+    * This fixes: `Irrefutable pattern failed for pattern Let (l' :| ls') d'`+    * This bug would cause `dhall lint` to fail on some nested `let`/`in`+      expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/780+    * See: https://github.com/dhall-lang/dhall-haskell/pull/784+* BUG FIX: Don't fail if `$HOME` environment variable is unset+    * The interpreter was incorrectly throwing an exception if `HOME` was unset+    * The standard requires that implementations should handle the `HOME`+      environment variable being missing+    * See: https://github.com/dhall-lang/dhall-haskell/pull/789+* Feature: Remove version tag from semantic integrity check+    * ... as standardized in version 6.0.0 of the language standard+    * This is not a breaking change because this change also includes+      backwards-compatible support for semantic integrity checks produced by+      older versions of the interpreter+* Feature: Support Unicode path components+    * ... as standardized in version 6.0.0 of the language standard+    * You can now use Unicode in path components if they are quoted+    * i.e. `./families/"禺.dhall"` is now legal+* Feature: Add `Text/show` built-in+    * ... as standardized in version 6.0.0 of the language standard+    * You can now convert a `Text` literal to its equivalent Dhall source code+      (which is itself a `Text` literal)+    * This comes in handy when using Dhall code to generate JSON or Dhall code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/811+* Feature: Add `--immediate-dependencies`/`--transitive-dependencies` flags for+  `dhall resolve`+    * You can now retrieve all of your immediate or transitive dependencies as a+      textual list+    * This simplifies integration with other command-line tools (such as file+      watchers)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/795+    * See: https://github.com/dhall-lang/dhall-haskell/pull/803+* Feature: `dhall freeze` now only freezes remote imports by default+    * `dhall freeze` used to freeze all imports (including local imports and+      environment variables)+    * Now `dhall freeze` only freezes remote imports by default, which is what+      most users want+    * You can install freeze all imports using the `--all` flag+    * See: https://github.com/dhall-lang/dhall-haskell/pull/808+* Feature: `:save` and `:load` REPL state+    * `:save` with no arguments now saves the REPL state to a `.dhall-repl-N`+       file+    * The file format is a list of `dhall repl` commands+    * You can use `:load` to load the saved state back into the REPL+    * See: https://github.com/dhall-lang/dhall-haskell/pull/807+* Feature: Add `:hash` command to `dhall repl`+    * This lets you conveniently hash expressions within the `dhall repl`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/806+* Feature: Add `--check` flag to `dhall format`+    * Use this to check if the input is already formatted+    * Useful for continuous integration when you want to ensure that all code+      under version control remains formatted+    * See: https://github.com/dhall-lang/dhall-haskell/pull/810+* Feature: Add  `UnionInputType` builder for `InputType`s+    * This is the union analog of `RecordInputType`, letting you build a+      record explicitly instead of deriving the instance using GHC generics+    * See: https://github.com/dhall-lang/dhall-haskell/pull/775+* Feature: Add `:set`/`:unset` commands to `dhall repl`+    * You can use these commands to set or unset command-line options+    * Currently only setting/unsetting `--explain` is supported+* Standards-compliance fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/779+    * See: https://github.com/dhall-lang/dhall-haskell/pull/804+    * See: https://github.com/dhall-lang/dhall-haskell/pull/833+* Documentation fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/792+    * See: https://github.com/dhall-lang/dhall-haskell/pull/825+* Test fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/782+    * See: https://github.com/dhall-lang/dhall-haskell/pull/836+* Improved error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/812+    * See: https://github.com/dhall-lang/dhall-haskell/pull/815+    * See: https://github.com/dhall-lang/dhall-haskell/pull/824+* Formatting fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/831+* REPL fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/837++1.20.1++* BUG FIX: Fix binary encoding to use correct standard version+    * This fixes computed hashes to correctly match standard version 5.0.0+    * This is not marked as a breaking change since it is a bug fix.  The+      1.20.0 release will be blacklisted on Hackage and users should upgrade+      from 1.19.* directly to 1.20.1+    * See: https://github.com/dhall-lang/dhall-haskell/pull/771++1.20.0++* Supports version 5.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v5.0.0+* BREAKING CHANGE TO THE LANGUAGE: Implement standardized support for multi-line+  literals+    * This updates the multi-line support to match the standard+    * This is a breaking change because empty lines within the multi-line+      literal now require leading whitespace whereas previously they did not+    * This is also a breaking change because now a newline is required after+      the opening `''` quotes whereas previously it was not required+    * If you use `dhall format` then your multi-line literals already have the+      necessary leading whitespace+* BREAKING CHANGE TO THE LANGUAGE: `constructors x = x`+    * Now the `constructors` keyword behaves like an identity function, since+      constructors can already be accessed as fields off the original union+      type.+    * This is a breaking change since any record of terms that contains a+      `constructors` field will now be a forbidden mixed record of types and+      terms.+    * This is also a breaking change if you annotated the type of what used to+      be a `constructors` record.+    * `dhall lint` will now remove the obsolete `constructors` keyword for you+    * See: https://github.com/dhall-lang/dhall-haskell/pull/693+    * See: https://github.com/dhall-lang/dhall-haskell/pull/701+* BREAKING CHANGE TO THE API: Restore `Parent` constructor for `Local` type+    * This more closely matches the standard and also enables `dhall format` to+      produce a leading `../` for imports instead of `./../`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/718+* BUG FIX: Fix type-checking bug for unions+    * The first fix was that the inferred type was wrong for unions where+      alternatives were types or kinds+    * The second fix was that unions that mixed terms/types/kinds were not+      properly rejected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/763+* BUG FIX: Change how `dhall repl` handles prior definitions+    * This changes the REPL to handle previous bindings as if they were+      defined using a large `let` expression instead of adding them to the+      context+    * This fixes some type-checking false negatives+    * See: https://github.com/dhall-lang/dhall-haskell/pull/729+* Feature: Autocomplete for `dhall repl`+    * You can now auto-complete record fields, union constructors, and+      identifiers that are in scope+    * See: https://github.com/dhall-lang/dhall-haskell/pull/727+* Feature: GHCJS support+    * `dhall` can now be built using GHCJS, although some features are still+      not supported for GHCJS, such as:+        * Semantic integrity checks+        * Custom HTTP headers+    * Also, HTTP imports only work for URLs that support CORS+    * See: https://github.com/dhall-lang/dhall-haskell/pull/739+* Feature: Add support for records of records of types+    * You can now nest records of types+    * See: https://github.com/dhall-lang/dhall-haskell/pull/700+* Feature: Add `:quit` command for `dhall repl`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/719+* Feature: Add `--json` flag for `dhall {encode,decode}`+    * You can now produce/consume CBOR expressions via JSON instead of binary+    * See: https://github.com/dhall-lang/dhall-haskell/pull/717+* Feature: Add decoding logic for `as Text`+    * You can now preserve the `as Text` qualifier on imports when serializing+      them+    * See: https://github.com/dhall-lang/dhall-haskell/pull/712+* Prenormalize substituted expressions+    * This is a performance improvement that reduces the time and memory+      consumption when normalizing expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/765++1.19.1+++* BUG FIX: Fix serious `dhall lint` bug+    * `dhall lint` would sometimes remove `let` expressions that were still+      in use+    * See: https://github.com/dhall-lang/dhall-haskell/pull/703+* BUG FIX: Fix import caching efficiency bug+    * Some imports were being wastefully fetched multiple times+    * See: https://github.com/dhall-lang/dhall-haskell/pull/702+* Feature: Generate dot graph to visualize import graph+    * Use the `dhall resolve --dot` command+    * See: https://github.com/dhall-lang/dhall-haskell/pull/698+    * See: https://github.com/dhall-lang/dhall-haskell/pull/713+* Improve HTTP error messages+    * See: https://github.com/dhall-lang/dhall-haskell/pull/710++1.19.0++* Supports version 4.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v4.0.0+* BREAKING CHANGE TO THE LANGUAGE AND API: Prevent Hurkens' paradox+    * This fixes a type-checking soundness bug which permitted infinite loops+    * This is a breaking change because infinite loops are no longer possible+    * This is also a breaking change because a record of types is now treated as+      a kind instead of a type+    * See: https://github.com/dhall-lang/dhall-haskell/pull/680+* BREAKING CHANGE TO THE LANGUAGE AND API: `Double`s are now double-precision+  floating point numbers+    * This restricts the range of `Double`s to IEEE 754 double-precision+      floating point+    * This also implies that you can no longer convert `Scientific` values to+      `Dhall` expressions (i.e. no `Inject` instance for `Scientific`)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/667+* BREAKING CHANGE TO THE API: Preserve field order for record projection+    * The API uses a new `Dhall.Set.Set` type instead of `Data.Set.Set`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/670+* BREAKING CHANGE TO THE API: Add support for multi-`let` expressions+    * This changes the `Let` constructor to now support storing multiple+      bindings per `let` expression+    * See: https://github.com/dhall-lang/dhall-haskell/pull/675+* Access constructors as if they were fields of the union type+    * In other words: `< Left : Bool | Right : Natural >.Left`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/657+* Support GHC 8.6+    * See: https://github.com/dhall-lang/dhall-haskell/pull/669+* Add support for quoted path components+    * i.e. `/"foo"/bar/"baz qux"` or `https://example.com/foo/"bar?baz"?qux`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/690+* Fix parsing of `//\\` operator+    * See: https://github.com/dhall-lang/dhall-haskell/commit/9d0fd42d95ab69fa64da4afd8b60d69aca8e65a6+* Preserve Unicode characters when formatting code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/679+* Allow identifier names to begin with `Some`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/658+* Add `subExpressions` `Traversal`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/660+* Add `normalizeWithM` for monadic normalization+    * See: https://github.com/dhall-lang/dhall-haskell/pull/371+* Custom normalizers now take precedence over default normalization logic+    * This allows one to override the implementation of built-in operators+    * See: https://github.com/dhall-lang/dhall-haskell/pull/684++1.18.0++* Supports version 3.0.0 of the language standard:+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v3.0.0+* BREAKING CHANGE TO THE LANGUAGE AND API: New `Some`/`None` constructors for+  `Optional` values+    * Example: `[ Some 1, None Natural ]`+    * This is a breaking change to the language because `Some` and `None` are+      now reserved keywords+    * This is a breaking change to the API because `Some` and `None` are new+      constructors for the `Expr` type+* BREAKING CHANGE TO THE LANGUAGE AND API: Support for kind polymorphism+    * This adds a new `Sort` constant above `Kind` in the hierarchy+    * i.e. `Type : Kind : Sort`+    * This is a breaking change to the language because `Sort` is now a+      reserved keyword+    * This is a breaking change to the API because `Sort` is a new+      constructor for the `Expr` type+* BREAKING CHANGE TO THE API: New `Dhall.Map` module+    * This replaces `InsOrdHashMap` in the API+    * The primary motivation is to improve performance and to remove the+      dependency on `insert-ordered-containers`+* BREAKING CHANGE TO THE API: Use standard version instead of protocol version+    * The binary protocol is now versioned alongside the standard+    * The `ProtocolVersion` type is renamed to `StandardVersion` and the+    * `--protocol-version` option is renamed to `--standard-version`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/634+* BUG FIX: Fix import chaining for custom header imports+    * See: https://github.com/dhall-lang/dhall-haskell/pull/618+* BUG FIX: Fix import chaining for imports protected by semantic integrity+  checks+    * See: https://github.com/dhall-lang/dhall-haskell/pull/584+* BUG FIX: Record literals and types produced by `∧`/`⫽`/`⩓` are now sorted+    * This ensures that β-normalization is idempotent+    * See: https://github.com/dhall-lang/dhall-haskell/pull/572+* BUG FIX: `dhall freeze` now correctly handles the starting file being+  located outside the current working directory+    * See: https://github.com/dhall-lang/dhall-haskell/commit/a22aa79d1957be9ecf166ea066e2a9a5b309e1ae+* BUG FIX: Fix parsing of IPv4-mapped IPv6 addresses+    * See: https://github.com/dhall-lang/dhall-haskell/pull/632+* FEATURE: New `--ascii` flag for ASCII output+    * See: https://github.com/dhall-lang/dhall-haskell/pull/570+* FEATURE: New `dhall encode` and `dhall decode` subcommands+    * These allow you to transform Dhall source code to and from its binary+      representation+    * See: https://github.com/dhall-lang/dhall-haskell/pull/588+* LARGE parsing performance improvements+    * Parsing is about 10x-100x faster on most code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/591+    * See: https://github.com/dhall-lang/dhall-haskell/pull/592+    * See: https://github.com/dhall-lang/dhall-haskell/pull/597+    * See: https://github.com/dhall-lang/dhall-haskell/pull/601+    * See: https://github.com/dhall-lang/dhall-haskell/pull/602+    * See: https://github.com/dhall-lang/dhall-haskell/pull/604+    * See: https://github.com/dhall-lang/dhall-haskell/pull/606+* Type-checking performance improvements:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/566+* Normalization performance improvements:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/610+* `dhall freeze` now caches the imports as it freezes them+    * See: https://github.com/dhall-lang/dhall-haskell/pull/587+* `dhall freeze` now refreezes imports with invalid semantic integrity checks+    * See: https://github.com/dhall-lang/dhall-haskell/pull/637+* `dhall freeze` now adds a trailing newline+    * See: https://github.com/dhall-lang/dhall-haskell/pull/629+* Build against `megaparsec-7.0.*`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/565+* Support GHC 8.6+    * See: https://github.com/dhall-lang/dhall-haskell/pull/599+    * See: https://github.com/dhall-lang/dhall-haskell/pull/623+* Support GHC all the way back to 7.10.3+    * See: https://github.com/dhall-lang/dhall-haskell/pull/595+    * See: https://github.com/dhall-lang/dhall-haskell/pull/621+* Improvements to error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/563+    * See: https://github.com/dhall-lang/dhall-haskell/pull/576+    * See: https://github.com/dhall-lang/dhall-haskell/pull/583+    * See: https://github.com/dhall-lang/dhall-haskell/pull/589+++1.17.0++* This release corresponds to version 2.0.0 of the language standard+* BREAKING CHANGE TO THE LANGUAGE AND API: Binary serialization support+    * This is a breaking change to the hash for all semantic integrity checks+    * The hash used by the semantic integrity check is now based on the+      binary representation instead of a text representation of the+      expression+    * You can pin the new hashes by supplying the `--protocol-version 1.0`+      option on the command line until you need support for newer language+      features+    * This also includes a breaking change to `ImportType` in the API+* BREAKING CHANGE TO THE LANGUAGE: Disallow combining records of terms and+  types+    * This is mainly for consistency and to improve type errors that would+      have otherwise happened further downstream+    * This should not affect the vast majority of code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/538+* BUG FIX: Semantic integrity checks now work for imported expression using+  the `constructors` keyword+    * See: https://github.com/dhall-lang/dhall-haskell/pull/554+* BUG FIX: Fix α-normalization of expressions with bound variables named `_`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/524+* BUG FIX: Fix `isNormalized` to match `normalize`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/522+* BUG FIX: `dhall lint` now correctly handles nested `let` expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/555+* FEATURE: Imports protected by a semantic integrity check are now cached+    * See: https://github.com/dhall-lang/dhall-haskell/pull/533+* The default `dhall` command no longer outputs the type to `stderr`+    * You can add back the type as a type annotation using the+      `--annotate` switch+    * See: https://github.com/dhall-lang/dhall-haskell/pull/544+* New utilities for building `InputTypes`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/530+* Improve parsing performance for long variable names+    * See: https://github.com/dhall-lang/dhall-haskell/pull/526+* More succinct type diffs for function types+    * See: https://github.com/dhall-lang/dhall-haskell/pull/540+* Identifier names can now begin with keywords+    * i.e. `ifChanged` and `lettuce` are now legal identifiers+    * See: https://github.com/dhall-lang/dhall-haskell/pull/551++1.16.1++* Fix test failure due to missing test data file++1.16.0++* BREAKING CHANGE: Consolidate `input` family of functions+    * These now take a record of options+    * This also `_stack` field of the `Status` type from `[Import]` to+      `NonEmpty Import`+* Permit `$` in quoted variable names+    * See: https://github.com/dhall-lang/dhall-haskell/pull/510++1.15.1++* Fix infinite loop when formatting expressions containing `?`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/491++1.15.0++* BREAKING CHANGE TO THE API: Support alternative imports using new `?` operator+    * This adds a new constructor which affects exhaustive pattern matches+    * See: https://github.com/dhall-lang/dhall-haskell/pull/473+* BREAKING CHANGE TO THE API: Add `Integer/toDouble` built-in function+    * This adds a new constructor which affects exhaustive pattern matches+    * See: https://github.com/dhall-lang/dhall-haskell/pull/434+* BREAKING CHANGE TO THE API: Use strict `Text` instead of lazy `Text`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/455+* BREAKING CHANGE TO THE API: Remove `Buildable` in favor of `Pretty`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/459+* BREAKING CHANGE TO THE API: Removed the `Parent` constructor from `FilePrefix`+    * Instead, use `Here` with a `".."` prefix.+    * See: https://github.com/dhall-lang/dhall-haskell/pull/407+* BUG FIX: Disallow duplicate fields in records+    * See: https://github.com/dhall-lang/dhall-haskell/pull/430+* BUG FIX: Fix stripping of leading whitespace in multi-line strings+    * See: https://github.com/dhall-lang/dhall-haskell/pull/469+* BUG FIX: Fix formatting field access of an import+    * See: https://github.com/dhall-lang/dhall-haskell/pull/471+* Add `dhall freeze` command+    * See: https://github.com/dhall-lang/dhall-haskell/pull/486+* Add `dhall diff` command+    * See: https://github.com/dhall-lang/dhall-haskell/pull/442+* Add `dhall lint` command+    * See: https://github.com/dhall-lang/dhall-haskell/pull/484+* Change `dhall-repl`/`dhall-hash`/`dhall-format` to `dhall` subcommands+    * i.e. `dhall repl`/`dhall hash`/`dhall format`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/435+    * See: https://github.com/dhall-lang/dhall-haskell/pull/452+* Add `with-http` cabal flag to disable support for remote imports+    * See: https://github.com/dhall-lang/dhall-haskell/pull/482+* Added `inputFrom` and `inputFromWith`+    * These allow naming the file that the expression is coming from for better+      error messages+    * See: https://github.com/dhall-lang/dhall-haskell/pull/464+* Performance improvements+    * See: https://github.com/dhall-lang/dhall-haskell/pull/420+* Tutorial recommends GitHub for Prelude instead of IPFS+    * See: https://github.com/dhall-lang/dhall-haskell/pull/479+* Pretty-print expressions in type errors+    * See: https://github.com/dhall-lang/dhall-haskell/pull/429+* Formatting improvements+    * See: https://github.com/dhall-lang/dhall-haskell/pull/398+    * See: https://github.com/dhall-lang/dhall-haskell/pull/458+* Diff improvements+    * See: https://github.com/dhall-lang/dhall-haskell/pull/455+    * See: https://github.com/dhall-lang/dhall-haskell/pull/470+    * See: https://github.com/dhall-lang/dhall-haskell/pull/478++1.14.0++* BREAKING CHANGE TO THE LANGUAGE: Switch grammar of `Natural` and `Integer`+    * `Natural` number literals are now unsigned and `Integer` literals always+      require a sign+    * This is a **VERY** disruptive change to most Dhall code in the wild but+      was unanimously agreed upon here:+      https://github.com/dhall-lang/dhall-lang/issues/138+    * See also: https://github.com/dhall-lang/dhall-haskell/pull/381+* BREAKING CHANGE TO THE LANGUAGE: Drop support for importing directories+    * Importing `dir/` used to resolve to `dir/@`, which is no longer supported+    * See: https://github.com/dhall-lang/dhall-haskell/pull/384+* BREAKING CHANGE TO THE LANGUAGE: Change to the grammar for imports+    * File path components can no longer contain `#` or `?` characters+    * URL imports must now contain at least one path component+    * URL path components must match the grammar for file path components+    * See: https://github.com/dhall-lang/dhall-haskell/pull/390+* BREAKING CHANGE TO THE API: Rename `Path{,Mode,Hashed,Type}` to+  `Import{,Mode,Hashed,Type}`+    * In practice this change is not breaking for the most common use cases+      since this also provides a `Path` type synonym for backwards compatibility+    * See: https://github.com/dhall-lang/dhall-haskell/pull/376+* BUG FIX: Fix α-equivalence bug when type-checking `merge`+    * `merge` expressions would sometimes reject valid code due to a+       type-checking bug+    * See: https://github.com/dhall-lang/dhall-haskell/pull/394+* Improve import caching+    * See: https://github.com/dhall-lang/dhall-haskell/pull/388+    * See: https://github.com/dhall-lang/dhall-haskell/pull/392+* Increase upper bound on `tasty`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/382+* Fix lower bound on `insert-ordered-containers`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/377++1.13.1++* Increase upper bound on `ansi-terminal` and `megaparsec`++1.13.0++* BUG FIX: Fix semantic integrity hashing support+    * Both parsing and pretty-printing semantic hashes were broken since version+      1.11.0+    * See: https://github.com/dhall-lang/dhall-haskell/pull/345+* BUG FIX: Allow leading whitespace in interpolated expresssions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/369+* BUG FIX: Fix `deriving (Interpret)` for sum types+    * The types of alternatives were not correctly included in the corresponding+      Dhall type+    * See: https://github.com/dhall-lang/dhall-haskell/pull/348+* BREAKING CHANGE TO LANGUAGE: Records cannot store both types and terms+    * Records can also not store type-level functions (like `List`)+        * Records might be allowed to store type-level functions again in the+          future+    * This fixes a potential soundness bug+    * The primarily practical consequence of this change is that if you are+      hosting a "package" then you will need to split terms and types from your+      package into different records for your users to import+    * This also implies removing the `./Monoid` type-level function from the+      `./Prelude/package.dhall` record+    * See: https://github.com/dhall-lang/dhall-haskell/pull/335+* BREAKING CHANGE TO THE API: Replace `trifecta` with `megaparsec`+    * This change the API to use the `Parser` type from `megaparsec`+    * This also slightly changes the type of `exprFromText`+    * If you program using the type classes provided by the `parsers` library+      then this is not a breaking change as that interface is preserved+    * See: https://github.com/dhall-lang/dhall-haskell/pull/268+* BREAKING CHANGE TO THE API: New `⩓` operator for merging record types+    * Example: `{ foo : Text } ⩓ { bar : Bool } = { foo : Text, bar : Bool }`+    * This is breaking because it adds a new constructor to the `Expr` type+    * See: https://github.com/dhall-lang/dhall-haskell/pull/342+* BREAKING CHANGE TO THE API: New support for projecting a subset of fields+    * Example: `{ x = 1, y = 2, z = 3 }.{ x, y } = { x = 1, y = 2 }`+    * This is breaking because it adds a new constructor to the `Expr` type+    * See: https://github.com/dhall-lang/dhall-haskell/pull/350+* API+UX feature: New support for pretty-printing diffs of Dhall expressions+    * Error messages also use this feature to simplify large type mismatches+    * There is also a new `Dhall.Diff` module+    * See: https://github.com/dhall-lang/dhall-haskell/pull/336+* Add `version`, `resolve`, `type`, and `normalize` sub-commands to interpreter+    * See: https://github.com/dhall-lang/dhall-haskell/pull/352+* Support GHC 7.10.3+    * See: https://github.com/dhall-lang/dhall-haskell/pull/340+* `:type` command in `dhall-repl` now only displays the type+    * Before it would also display the original expression+    * See: https://github.com/dhall-lang/dhall-haskell/pull/344+* Trim dependency tree+    * See: https://github.com/dhall-lang/dhall-haskell/pull/351+    * See: https://github.com/dhall-lang/dhall-haskell/pull/268+    * See: https://github.com/dhall-lang/dhall-haskell/pull/355++1.12.0++* Additional changes to support GHC 8.4+    * See: https://github.com/dhall-lang/dhall-haskell/pull/331+* BREAKING CHANGE TO API: Replace dependency on `text-format` with `formatting`+    * This replace the `Data.Text.Buildable.Buildable` instances with+      `Formatting.Buildable.Buildable` instances, which is why this is a+       breaking change+    * `text-format` is no longer maintained and blocking GHC 8.4 support+    * See: https://github.com/dhall-lang/dhall-haskell/pull/330+ 1.11.1  * Support GHC 8.4
LICENSE view
@@ -1,24 +1,27 @@-Copyright (c) 2017 Gabriel Gonzalez+Copyright (c) 2020 Gabriella Gonzalez All rights reserved. -Redistribution and use in source and binary forms, with or without modification,-are permitted provided that the following conditions are met:-    * Redistributions of source code must retain the above copyright notice,-      this list of conditions and the following disclaimer.-    * Redistributions in binary form must reproduce the above copyright notice,-      this list of conditions and the following disclaimer in the documentation-      and/or other materials provided with the distribution.-    * Neither the name of Gabriel Gonzalez nor the names of other contributors-      may be used to endorse or promote products derived from this software-      without specific prior written permission.+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met: -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+1. Redistributions of source code must retain the above copyright notice, this+list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of its contributors may be+used to endorse or promote products derived from this software without+specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
− Prelude/Bool/and
@@ -1,18 +0,0 @@-{--The `and` function returns `False` if there are any `False` elements in the-`List` and returns `True` otherwise--Examples:--```-./and [ True, False, True ] = False--./and ([] : List Bool) = True-```--}-    let and-        : List Bool → Bool-        =   λ(xs : List Bool)-          → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l && r) True--in  and
− Prelude/Bool/build
@@ -1,17 +0,0 @@-{--`build` is the inverse of `fold`--Examples:--```-./build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true) = True--./build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false) = False-```--}-    let build-        : (∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool-        =   λ(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool)-          → f Bool True False--in  build
− Prelude/Bool/even
@@ -1,22 +0,0 @@-{--Returns `True` if there are an even number of `False` elements in the list and-returns `False` otherwise--Examples:--```-./even [ False, True, False ] = True--./even [ False, True ] = False--./even [ False ] = False--./even ([] : List Bool) = True-```--}-    let even-        : List Bool → Bool-        =   λ(xs : List Bool)-          → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x == y) True--in  even
− Prelude/Bool/fold
@@ -1,20 +0,0 @@-{--`fold` is essentially the same as `if`/`then`/else` except as a function--Examples:--```-./fold True Integer 0 1 = 0--./fold False Integer 0 1 = 1-```--}-    let fold-        : ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool-        =   λ(b : Bool)-          → λ(bool : Type)-          → λ(true : bool)-          → λ(false : bool)-          → if b then true else false--in  fold
− Prelude/Bool/not
@@ -1,12 +0,0 @@-{--Flip the value of a `Bool`--Examples:--```-./not True = False--./not False = True-```--}-let not : Bool → Bool = λ(b : Bool) → b == False in not
− Prelude/Bool/odd
@@ -1,22 +0,0 @@-{--Returns `True` if there are an odd number of `True` elements in the list and-returns `False` otherwise--Examples:--```-./odd [ True, False, True ] = False--./odd [ True, False ] = True--./odd [ True ] = True--./odd ([] : List Bool) = False-```--}-    let odd-        : List Bool → Bool-        =   λ(xs : List Bool)-          → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x != y) False--in  odd
− Prelude/Bool/or
@@ -1,18 +0,0 @@-{--The `or` function returns `True` if there are any `True` elements in the `List`-and returns `False` otherwise--Examples:--```-./or [ True, False, True ] = True--./or ([] : List Bool) = False-```--}-    let or-        : List Bool → Bool-        =   λ(xs : List Bool)-          → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l || r) False--in  or
− Prelude/Bool/show
@@ -1,13 +0,0 @@-{--Render a `Bool` as `Text` using the same representation as Dhall source code-(i.e. beginning with a capital letter)--Examples:--```-./show True  = "True"--./show False = "False"-```--}-let show : Bool → Text = λ(b : Bool) → if b then "True" else "False" in show
− Prelude/Double/show
@@ -1,13 +0,0 @@-{--Render a `Double` as `Text` using the same representation as Dhall source-code (i.e. a decimal floating point number with a leading `-` sign if negative)--Examples:--```-./show -3.1 = "-3.1"--./show  0.4 =  "0.4"-```--}-let show : Double → Text = Double/show in show
− Prelude/Integer/show
@@ -1,13 +0,0 @@-{--Render an `Integer` as `Text` using the same representation as Dhall source-code (i.e. a decimal number with a leading `-` sign if negative)--Examples:--```-./show -3 = "-3"--./show  0 =  "0"-```--}-let show : Integer → Text = Integer/show in show
− Prelude/List/all
@@ -1,20 +0,0 @@-{--Returns `True` if the supplied function returns `True` for all elements in the-`List`--Examples:--```-./all Natural Natural/even [ +2, +3, +5 ] = False--./all Natural Natural/even ([] : List Natural) = True-```--}-    let all-        : ∀(a : Type) → (a → Bool) → List a → Bool-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : List a)-          → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x && r) True--in  all
− Prelude/List/any
@@ -1,20 +0,0 @@-{--Returns `True` if the supplied function returns `True` for any element in the-`List`--Examples:--```-./any Natural Natural/even [ +2, +3, +5 ] = True--./any Natural Natural/even ([] : List Natural) = False-```--}-    let any-        : ∀(a : Type) → (a → Bool) → List a → Bool-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : List a)-          → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False--in  any
− Prelude/List/build
@@ -1,32 +0,0 @@-{--`build` is the inverse of `fold`--Examples:--```-./build-Text-(   λ(list : Type)-→   λ(cons : Text → list → list)-→   λ(nil : list)-→   cons "ABC" (cons "DEF" nil)-)-= [ "ABC", "DEF" ]--./build-Text-(   λ(list : Type)-→   λ(cons : Text → list → list)-→   λ(nil : list)-→   nil-)-= [] : List Text-```--}-    let build-        :   ∀(a : Type)-          → (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list)-          → List a-        = List/build--in  build
− Prelude/List/concat
@@ -1,42 +0,0 @@-{--Concatenate a `List` of `List`s into a single `List`--Examples:--```-./concat Integer-[   [0, 1, 2]-,   [3, 4]-,   [5, 6, 7, 8]-]-= [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]--./concat Integer-(   [   [] : List Integer-    ,   [] : List Integer-    ,   [] : List Integer-    ]-)-= [] : List Integer--./concat Integer ([] : List (List Integer)) = [] : List Integer-```--}-    let concat-        : ∀(a : Type) → List (List a) → List a-        =   λ(a : Type)-          → λ(xss : List (List a))-          → List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → λ(nil : list)-              → List/fold-                (List a)-                xss-                list-                (λ(xs : List a) → λ(ys : list) → List/fold a xs list cons ys)-                nil-            )--in  concat
− Prelude/List/concatMap
@@ -1,28 +0,0 @@-{--Transform a list by applying a function to each element and flattening the-results--Examples:--```-./concatMap Natural Natural (λ(n : Natural) → [n, n]) [+2, +3, +5]-= [ +2, +2, +3, +3, +5, +5 ]--./concatMap Natural Natural (λ(n : Natural) → [n, n]) ([] : List Natural)-= [] : List Natural-```--}-    let concatMap-        : ∀(a : Type) → ∀(b : Type) → (a → List b) → List a → List b-        =   λ(a : Type)-          → λ(b : Type)-          → λ(f : a → List b)-          → λ(xs : List a)-          → List/build-            b-            (   λ(list : Type)-              → λ(cons : b → list → list)-              → List/fold a xs list (λ(x : a) → List/fold b (f x) list cons)-            )--in  concatMap
− Prelude/List/filter
@@ -1,30 +0,0 @@-{--Only keep elements of the list where the supplied function returns `True`--Examples:--```-./filter Natural Natural/even [+2, +3, +5]-= [ +2 ]--./filter Natural Natural/odd [+2, +3, +5]-= [ +3, +5 ]-```--}-    let filter-        : ∀(a : Type) → (a → Bool) → List a → List a-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : List a)-          → List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → List/fold-                a-                xs-                list-                (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)-            )--in  filter
− Prelude/List/fold
@@ -1,46 +0,0 @@-{--`fold` is the primitive function for consuming `List`s--If you treat the list `[ x, y, z ]` as `cons x (cons y (cons z nil))`, then a-`fold` just replaces each `cons` and `nil` with something else--Examples:--```-    ./fold-    Natural-    [ +2, +3, +5 ]-    Natural-    (λ(x : Natural) → λ(y : Natural) → x + y)-    +0-=   +10--    λ(nil : Natural)-→   ./fold-    Natural-    [ +2, +3, +5 ]-    Natural-    (λ(x : Natural) → λ(y : Natural) → x + y)-    nil-=   λ(nil : Natural) → +2 + +3 + +5 + nil--    λ(list : Type)-→   λ(cons : Natural → list → list)-→   λ(nil : list)-→   ./fold Natural [ +2, +3, +5 ] list cons nil-=   λ(list : Type)-→   λ(cons : Natural → list → list)-→   λ(nil : list)-→   cons +2 (cons +3 (cons +5 nil))-```--}-    let fold-        :   ∀(a : Type)-          → List a-          → ∀(list : Type)-          → ∀(cons : a → list → list)-          → ∀(nil : list)-          → list-        = List/fold--in  fold
− Prelude/List/generate
@@ -1,38 +0,0 @@-{--Build a list by calling the supplied function on all `Natural` numbers from `+0`-up to but not including the supplied `Natural` number--Examples:--```-./generate +5 Bool Natural/even = [ True, False, True, False, True ]--./generate +0 Bool Natural/even = [] : List Bool-```--}-    let generate-        : Natural → ∀(a : Type) → (Natural → a) → List a-        =   λ(n : Natural)-          → λ(a : Type)-          → λ(f : Natural → a)-          → List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → List/fold-                { index : Natural, value : {} }-                ( List/indexed-                  {}-                  ( List/build-                    {}-                    (   λ(list : Type)-                      → λ(cons : {} → list → list)-                      → Natural/fold n list (cons {=})-                    )-                  )-                )-                list-                (λ(x : { index : Natural, value : {} }) → cons (f x.index))-            )--in  generate
− Prelude/List/head
@@ -1,12 +0,0 @@-{--Retrieve the first element of the list--Examples:--```-./head Integer [ 0, 1, 2 ] = [ 0 ] : Optional Integer--./head Integer ([] : List Integer) = [] : Optional Integer-```--}-let head : ∀(a : Type) → List a → Optional a = List/head in head
− Prelude/List/indexed
@@ -1,21 +0,0 @@-{--Tag each element of the list with its index--Examples:--```-./indexed Bool [ True, False, True ]-=   [   { index = +0, value = True  }-    ,   { index = +1, value = False }-    ,   { index = +2, value = True  }-    ] : List { index : Natural, value : Bool }--./indexed Bool ([] : List Bool)-= [] : List { index : Natural, value : Bool }-```--}-    let indexed-        : ∀(a : Type) → List a → List { index : Natural, value : a }-        = List/indexed--in  indexed
− Prelude/List/iterate
@@ -1,43 +0,0 @@-{--Generate a list of the specified length given a seed value and transition-function--Examples:--```-./iterate +10 Natural (λ(x : Natural) → x * +2) +1-= [ +1, +2, +4, +8, +16, +32, +64, +128, +256, +512 ]--./iterate +0 Natural (λ(x : Natural) → x * +2) +1-= [] : List Natural-```--}-    let iterate-        : Natural → ∀(a : Type) → (a → a) → a → List a-        =   λ(n : Natural)-          → λ(a : Type)-          → λ(f : a → a)-          → λ(x : a)-          → List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → List/fold-                { index : Natural, value : {} }-                ( List/indexed-                  {}-                  ( List/build-                    {}-                    (   λ(list : Type)-                      → λ(cons : {} → list → list)-                      → Natural/fold n list (cons {=})-                    )-                  )-                )-                list-                (   λ(y : { index : Natural, value : {} })-                  → cons (Natural/fold y.index a f x)-                )-            )--in  iterate
− Prelude/List/last
@@ -1,12 +0,0 @@-{--Retrieve the last element of the list--Examples:--```-./last Integer [ 0, 1, 2 ] = [ 2 ] : Optional Integer--./last Integer ([] : List Integer) = [] : Optional Integer-```--}-let last : ∀(a : Type) → List a → Optional a = List/last in last
− Prelude/List/length
@@ -1,12 +0,0 @@-{--Returns the number of elements in a list--Examples:--```-./length Integer [ 0, 1, 2 ] = +3--./length Integer ([] : List Integer) = +0-```--}-let length : ∀(a : Type) → List a → Natural = List/length in length
− Prelude/List/map
@@ -1,27 +0,0 @@-{--Transform a list by applying a function to each element--Examples:--```-./map Natural Bool Natural/even [ +2, +3, +5 ]-= [ True, False, False ]--./map Natural Bool Natural/even ([] : List Natural)-= [] : List Bool-```--}-    let map-        : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b-        =   λ(a : Type)-          → λ(b : Type)-          → λ(f : a → b)-          → λ(xs : List a)-          → List/build-            b-            (   λ(list : Type)-              → λ(cons : b → list → list)-              → List/fold a xs list (λ(x : a) → cons (f x))-            )--in  map
− Prelude/List/null
@@ -1,16 +0,0 @@-{--Returns `True` if the `List` is empty and `False` otherwise--Examples:--```-./null Integer [ 0, 1, 2 ] = False--./null Integer ([] : List Integer) = True-```--}-    let null-        : ∀(a : Type) → List a → Bool-        = λ(a : Type) → λ(xs : List a) → Natural/isZero (List/length a xs)--in  null
− Prelude/List/replicate
@@ -1,24 +0,0 @@-{--Build a list by copying the given element the specified number of times--Examples:--```-./replicate +9 Integer 1 = [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]--./replicate +0 Integer 1 = [] : List Integer-```--}-    let replicate-        : Natural → ∀(a : Type) → a → List a-        =   λ(n : Natural)-          → λ(a : Type)-          → λ(x : a)-          → List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → Natural/fold n list (cons x)-            )--in  replicate
− Prelude/List/reverse
@@ -1,12 +0,0 @@-{--Reverse a list--Examples:--```-./reverse Integer [ 0, 1, 2 ] = [ 2, 1, 0 ] : List Integer--./reverse Integer ([] : List Integer) = [] : List Integer-```--}-let reverse : ∀(a : Type) → List a → List a = List/reverse in reverse
− Prelude/List/shifted
@@ -1,87 +0,0 @@-{--Combine a `List` of `List`s, offsetting the `index` of each element by the-number of elements in preceding lists--Examples:--```-./shifted-Bool-[   [   { index = +0, value = True  }-    ,   { index = +1, value = True  }-    ,   { index = +2, value = True  }-    ]-,   [   { index = +0, value = False }-    ,   { index = +1, value = False }-    ]-,   [   { index = +0, value = True  }-    ,   { index = +1, value = True  }-    ,   { index = +2, value = True  }-    ,   { index = +3, value = True  }-    ]-]-=   [   { index = +0, value = True  }-    ,   { index = +1, value = True  }-    ,   { index = +2, value = True  }-    ,   { index = +3, value = False }-    ,   { index = +4, value = False }-    ,   { index = +5, value = True  }-    ,   { index = +6, value = True  }-    ,   { index = +7, value = True  }-    ,   { index = +8, value = True  }-    ]--./shifted Bool ([] : List (List { index : Natural, value : Bool }))-= [] : List { index : Natural, value : Bool }-```--}-    let shifted-        :   ∀(a : Type)-          → List (List { index : Natural, value : a })-          → List { index : Natural, value : a }-        =   λ(a : Type)-          → λ(kvss : List (List { index : Natural, value : a }))-          → List/build-            { index : Natural, value : a }-            (   λ(list : Type)-              → λ(cons : { index : Natural, value : a } → list → list)-              → λ(nil : list)-              →     let result =-                          List/fold-                          (List { index : Natural, value : a })-                          kvss-                          { count : Natural, diff : Natural → list }-                          (   λ(kvs : List { index : Natural, value : a })-                            → λ(y : { count : Natural, diff : Natural → list })-                            →     let length =-                                        List/length-                                        { index : Natural, value : a }-                                        kvs-                              -                              in  { count = y.count + length-                                  , diff  =-                                        λ(n : Natural)-                                      → List/fold-                                        { index : Natural, value : a }-                                        kvs-                                        list-                                        (   λ ( kvOld-                                              : { index : Natural, value : a }-                                              )-                                          → λ(z : list)-                                          →     let kvNew =-                                                      { index = kvOld.index + n-                                                      , value = kvOld.value-                                                      }-                                            -                                            in  cons kvNew z-                                        )-                                        (y.diff (n + length))-                                  }-                          )-                          { count = +0, diff = λ(_ : Natural) → nil }-                -                in  result.diff +0-            )--in  shifted
− Prelude/List/unzip
@@ -1,55 +0,0 @@-{--Unzip a `List` into two separate `List`s--Examples:--```-./unzip-Text-Bool-(   [   { _1 = "ABC", _2 = True  }-    ,   { _1 = "DEF", _2 = False }-    ,   { _1 = "GHI", _2 = True  }-    ]-)-=   { _1 = [ "ABC", "DEF", "GHI" ]-    , _2 = [ True, False, True ]-    }--./unzip Text Bool ([] : List { _1 : Text, _2 : Bool })-= { _1 = [] : List Text, _2 = [] : List Bool }-```--}-    let unzip-        :   ∀(a : Type)-          → ∀(b : Type)-          → List { _1 : a, _2 : b }-          → { _1 : List a, _2 : List b }-        =   λ(a : Type)-          → λ(b : Type)-          → λ(xs : List { _1 : a, _2 : b })-          → { _1 =-                List/build-                a-                (   λ(list : Type)-                  → λ(cons : a → list → list)-                  → List/fold-                    { _1 : a, _2 : b }-                    xs-                    list-                    (λ(x : { _1 : a, _2 : b }) → cons x._1)-                )-            , _2 =-                List/build-                b-                (   λ(list : Type)-                  → λ(cons : b → list → list)-                  → List/fold-                    { _1 : a, _2 : b }-                    xs-                    list-                    (λ(x : { _1 : a, _2 : b }) → cons x._2)-                )-            }--in  unzip
− Prelude/Monoid
@@ -1,39 +0,0 @@-{--Any function `f` that is a `Monoid` must satisfy the following law:--```-t  : Type-f  : ./Monoid t-xs : List (List t)--f (./List/concat t xs) = f (./map (List t) t f xs)-```--Examples:--```-./Bool/and-    : ./Monoid Bool-./Bool/or-    : ./Monoid Bool-./Bool/even-    : ./Monoid Bool-./Bool/odd-    : ./Monoid Bool-./List/concat-    : ∀(a : Type) → ./Monoid (List a)-./List/shifted-    : ∀(a : Type) → ./Monoid (List { index : Natural, value : a })-./Natural/sum-    : ./Monoid Natural-./Natural/product-    : ./Monoid Natural-./Optional/head-    : ∀(a : Type) → ./Monoid (Optional a)-./Optional/last-    : ∀(a : Type) → ./Monoid (Optional a)-./Text/concat-    : ./Monoid Text-```--}-let Monoid : ∀(m : Type) → Type = λ(m : Type) → List m → m in Monoid
− Prelude/Natural/build
@@ -1,33 +0,0 @@-{--`build` is the inverse of `fold`--Examples:--```-./build-(   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   succ (succ (succ zero))-)-= +3--./build-(   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   zero-)-= +0-```--}-    let build-        :   (   ∀(natural : Type)-              → ∀(succ : natural → natural)-              → ∀(zero : natural)-              → natural-            )-          → Natural-        = Natural/build--in  build
− Prelude/Natural/enumerate
@@ -1,36 +0,0 @@-{--Generate a list of numbers from `+0` up to but not including the specified-number--Examples:--```-./enumerate +10 = [ +0, +1, +2, +3, +4, +5, +6, +7, +8, +9 ]--./enumerate +0 = [] : List Natural-```--}-    let enumerate-        : Natural → List Natural-        =   λ(n : Natural)-          → List/build-            Natural-            (   λ(list : Type)-              → λ(cons : Natural → list → list)-              → List/fold-                { index : Natural, value : {} }-                ( List/indexed-                  {}-                  ( List/build-                    {}-                    (   λ(list : Type)-                      → λ(cons : {} → list → list)-                      → Natural/fold n list (cons {=})-                    )-                  )-                )-                list-                (λ(x : { index : Natural, value : {} }) → cons x.index)-            )--in  enumerate
− Prelude/Natural/even
@@ -1,12 +0,0 @@-{--Returns `True` if a number if even and returns `False` otherwise--Examples:--```-./even +3 = False--./even +0 = True-```--}-let even : Natural → Bool = Natural/even in even
− Prelude/Natural/fold
@@ -1,33 +0,0 @@-{--`fold` is the primitive function for consuming `Natural` numbers--If you treat the number `+3` as `succ (succ (succ zero))` then a `fold` just-replaces each `succ` and `zero` with something else--Examples:--```-./fold +3 Natural (λ(x : Natural) → +5 * x) +1 = +125--λ(zero : Natural) → ./fold +3 Natural (λ(x : Natural) → +5 * x) zero-= λ(zero : Natural) → +5 * +5 * +5 * zero--    λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   ./fold +3 natural succ zero-=   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   succ (succ (succ zero))-```--}-    let fold-        :   Natural-          → ∀(natural : Type)-          → ∀(succ : natural → natural)-          → ∀(zero : natural)-          → natural-        = Natural/fold--in  fold
− Prelude/Natural/isZero
@@ -1,12 +0,0 @@-{--Returns `True` if a number is `+0` and returns `False` otherwise--Examples:--```-./isZero +2 = False--./isZero +0 = True-```--}-let isZero : Natural → Bool = Natural/isZero in isZero
− Prelude/Natural/odd
@@ -1,12 +0,0 @@-{--Returns `True` if a number is odd and returns `False` otherwise--Examples:--```-./odd +3 = True--./odd +0 = False-```--}-let odd : Natural → Bool = Natural/odd in odd
− Prelude/Natural/product
@@ -1,22 +0,0 @@-{--Multiply all the numbers in a `List`--Examples:--```-./product [ +2, +3, +5 ] = +30--./product ([] : List Natural) = +1-```--}-    let product-        : List Natural → Natural-        =   λ(xs : List Natural)-          → List/fold-            Natural-            xs-            Natural-            (λ(l : Natural) → λ(r : Natural) → l * r)-            +1--in  product
− Prelude/Natural/show
@@ -1,13 +0,0 @@-{--Render a `Natural` number as `Text` using the same representation as Dhall-source code (i.e. a decimal number with a leading `+` sign)--Examples:--```-./show +3 = "+3"--./show +0 = "+0"-```--}-let show : Natural → Text = Natural/show in show
− Prelude/Natural/sum
@@ -1,22 +0,0 @@-{--Add all the numbers in a `List`--Examples:--```-./sum [ +2, +3, +5 ] = +10--./sum ([] : List Natural) = +0-```--}-    let sum-        : List Natural → Natural-        =   λ(xs : List Natural)-          → List/fold-            Natural-            xs-            Natural-            (λ(l : Natural) → λ(r : Natural) → l + r)-            +0--in  sum
− Prelude/Natural/toInteger
@@ -1,12 +0,0 @@-{--Convert a `Natural` number to the corresponding `Integer`--Examples:--```-./toInteger +3 = 3--./toInteger +0 = 0-```--}-let toInteger : Natural → Integer = Natural/toInteger in toInteger
− Prelude/Optional/all
@@ -1,20 +0,0 @@-{--Returns `False` if the supplied function returns `False` for a present element-and `True` otherwise:--Examples:--```-./all Natural Natural/even ([ +3 ] : Optional Natural) = False--./all Natural Natural/even ([] : Optional Natural) = True-```--}-    let all-        : ∀(a : Type) → (a → Bool) → Optional a → Bool-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : Optional a)-          → Optional/fold a xs Bool f True--in  all
− Prelude/Optional/any
@@ -1,20 +0,0 @@-{--Returns `True` if the supplied function returns `True` for a present element and-`False` otherwise--Examples:--```-./any Natural Natural/even ([ +2 ] : Optional Natural) = True--./any Natural Natural/even ([] : Optional Natural) = False-```--}-    let any-        : ∀(a : Type) → (a → Bool) → Optional a → Bool-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : Optional a)-          → Optional/fold a xs Bool f False--in  any
− Prelude/Optional/build
@@ -1,36 +0,0 @@-{--`build` is the inverse of `fold`--Examples:--```-./build-Integer-(   λ(optional : Type)-→   λ(just : Integer → optional)-→   λ(nothing : optional)-→   just 1-)-= [ 1 ] : Optional Integer--./build-Integer-(   λ(optional : Type)-→   λ(just : Integer → optional)-→   λ(nothing : optional)-→   nothing-)-= [] : Optional Integer-```--}-    let build-        :   ∀(a : Type)-          → (   ∀(optional : Type)-              → ∀(just : a → optional)-              → ∀(nothing : optional)-              → optional-            )-          → Optional a-        = Optional/build--in  build
− Prelude/Optional/concat
@@ -1,28 +0,0 @@-{--Flatten two `Optional` layers into a single `Optional` layer--Examples:--```-./concat Integer ([ [ 1 ] : Optional Integer ] : Optional (Optional Integer))-= [ 1 ] : Optional Integer--./concat Integer ([ [] : Optional Integer ] : Optional (Optional Integer))-= [] : Optional Integer--./concat Integer ([] : Optional (Optional Integer))-= [] : Optional Integer-```--}-    let concat-        : ∀(a : Type) → Optional (Optional a) → Optional a-        =   λ(a : Type)-          → λ(x : Optional (Optional a))-          → Optional/fold-            (Optional a)-            x-            (Optional a)-            (λ(y : Optional a) → y)-            ([] : Optional a)--in  concat
− Prelude/Optional/filter
@@ -1,32 +0,0 @@-{--Only keep an `Optional` element if the supplied function returns `True`--Examples:--```-./filter Natural Natural/even ([ +2 ] : Optional Natural)-= [ +2 ] : Optional Natural--./filter Natural Natural/odd ([ +2 ] : Optional Natural)-= [] : Optional Natural-```--}-    let filter-        : ∀(a : Type) → (a → Bool) → Optional a → Optional a-        =   λ(a : Type)-          → λ(f : a → Bool)-          → λ(xs : Optional a)-          → Optional/build-            a-            (   λ(optional : Type)-              → λ(just : a → optional)-              → λ(nil : optional)-              → Optional/fold-                a-                xs-                optional-                (λ(x : a) → if f x then just x else nil)-                nil-            )--in  filter
− Prelude/Optional/fold
@@ -1,21 +0,0 @@-{--`fold` is the primitive function for consuming `Optional` values--Examples:--```-./fold Integer ([ 2 ] : Optional Integer) Integer (λ(x : Integer) → x) 0 = 2--./fold Integer ([] : Optional Integer) Integer (λ(x : Integer) → x) 0 = 0-```--}-    let fold-        :   ∀(a : Type)-          → Optional a-          → ∀(optional : Type)-          → ∀(just : a → optional)-          → ∀(nothing : optional)-          → optional-        = Optional/fold--in  fold
− Prelude/Optional/head
@@ -1,38 +0,0 @@-{--Returns the first non-empty `Optional` value in a `List`--Examples:--```-./head-Integer-[ [   ] : Optional Integer-, [ 1 ] : Optional Integer-, [ 2 ] : Optional Integer-]-= [ 1 ] : Optional Integer--./head-Integer-[ [] : Optional Integer, [] : Optional Integer ]-= [] : Optional Integer--./head Integer ([] : List (Optional Integer))-= [] : Optional Integer-```--}-    let head-        : ∀(a : Type) → List (Optional a) → Optional a-        =   λ(a : Type)-          → λ(xs : List (Optional a))-          → List/fold-            (Optional a)-            xs-            (Optional a)-            (   λ(l : Optional a)-              → λ(r : Optional a)-              → Optional/fold a l (Optional a) (λ(x : a) → [ x ] : Optional a) r-            )-            ([] : Optional a)--in  head
− Prelude/Optional/last
@@ -1,38 +0,0 @@-{--Returns the last non-empty `Optional` value in a `List`--Examples:--```-./last-Integer-[ [   ] : Optional Integer-, [ 1 ] : Optional Integer-, [ 2 ] : Optional Integer-]-= [ 2 ] : Optional Integer--./last-Integer-[ [] : Optional Integer, [] : Optional Integer ]-= [] : Optional Integer--./last Integer ([] : List (Optional Integer))-= [] : Optional Integer-```--}-    let last-        : ∀(a : Type) → List (Optional a) → Optional a-        =   λ(a : Type)-          → λ(xs : List (Optional a))-          → List/fold-            (Optional a)-            xs-            (Optional a)-            (   λ(l : Optional a)-              → λ(r : Optional a)-              → Optional/fold a r (Optional a) (λ(x : a) → [ x ] : Optional a) l-            )-            ([] : Optional a)--in  last
− Prelude/Optional/length
@@ -1,18 +0,0 @@-{--Returns `+1` if the `Optional` value is present and `+0` if the value is absent--Examples:--```-./length Integer ([ 2 ] : Optional Integer) = +1--./length Integer ([] : Optional Integer) = +0-```--}-    let length-        : ∀(a : Type) → Optional a → Natural-        =   λ(a : Type)-          → λ(xs : Optional a)-          → Optional/fold a xs Natural (λ(_ : a) → +1) +0--in  length
− Prelude/Optional/map
@@ -1,27 +0,0 @@-{--Transform an `Optional` value with a function--Examples:--```-./map Natural Bool Natural/even ([ +3 ] : Optional Natural)-= [ False ] : Optional Bool--./map Natural Bool Natural/even ([] : Optional Natural)-= [] : Optional Bool-```--}-    let map-        : ∀(a : Type) → ∀(b : Type) → (a → b) → Optional a → Optional b-        =   λ(a : Type)-          → λ(b : Type)-          → λ(f : a → b)-          → λ(o : Optional a)-          → Optional/fold-            a-            o-            (Optional b)-            (λ(x : a) → [ f x ] : Optional b)-            ([] : Optional b)--in  map
− Prelude/Optional/null
@@ -1,18 +0,0 @@-{--Returns `True` if the `Optional` value is absent and `False` if present--Examples:--```-./null Integer ([ 2 ] : Optional Integer) = False--./null Integer ([] : Optional Integer) = True-```--}-    let null-        : ∀(a : Type) → Optional a → Bool-        =   λ(a : Type)-          → λ(xs : Optional a)-          → Optional/fold a xs Bool (λ(_ : a) → False) True--in  null
− Prelude/Optional/toList
@@ -1,23 +0,0 @@-{--Convert an `Optional` value into the equivalent `List`--Examples:--```-./toList Integer ([ 1 ] : Optional Integer) = [ 1 ]--./toList Integer ([] : Optional Integer) = [] : List Integer-```--}-    let toList-        : ∀(a : Type) → Optional a → List a-        =   λ(a : Type)-          → λ(o : Optional a)-          → Optional/fold-            a-            o-            (List a)-            (λ(x : a) → ([ x ] : List a))-            ([] : List a)--in  toList
− Prelude/Optional/unzip
@@ -1,41 +0,0 @@-{--Unzip an `Optional` value into two separate `Optional` values--Examples:--```-./unzip-Text-Bool-([ { _1 = "ABC", _2 = True  } ] : Optional { _1 : Text, _2 : Bool })-= { _1 = [ "ABC" ] : Optional Text, _2 = [ True ] : Optional Bool }--./unzip Text Bool ([] : Optional { _1 : Text, _2 : Bool })-= { _1 = [] : Optional Text, _2 = [] : Optional Bool }-```--}-    let unzip-        :   ∀(a : Type)-          → ∀(b : Type)-          → Optional { _1 : a, _2 : b }-          → { _1 : Optional a, _2 : Optional b }-        =   λ(a : Type)-          → λ(b : Type)-          → λ(xs : Optional { _1 : a, _2 : b })-          → { _1 =-                Optional/fold-                { _1 : a, _2 : b }-                xs-                (Optional a)-                (λ(x : { _1 : a, _2 : b }) → [ x._1 ] : Optional a)-                ([] : Optional a)-            , _2 =-                Optional/fold-                { _1 : a, _2 : b }-                xs-                (Optional b)-                (λ(x : { _1 : a, _2 : b }) → [ x._2 ] : Optional b)-                ([] : Optional b)-            }--in  unzip
− Prelude/Text/concat
@@ -1,17 +0,0 @@-{--Concatenate all the `Text` values in a `List`--Examples:--```-./concat [ "ABC", "DEF", "GHI" ] = "ABCDEFGHI"--./concat ([] : List Text) = ""-```--}-    let concat-        : List Text → Text-        =   λ(xs : List Text)-          → List/fold Text xs Text (λ(x : Text) → λ(y : Text) → x ++ y) ""--in  concat
− Prelude/Text/concatMap
@@ -1,21 +0,0 @@-{--Transform each value in a `List` into `Text` and concatenate the result--Examples:--```-./concatMap Integer (λ(n : Integer) → "${Integer/show n} ") [ 0, 1, 2 ]-= "0 1 2 "--./concatMap Integer (λ(n : Integer) → "${Integer/show n} ") ([] : List Integer)-= ""-```--}-    let concatMap-        : ∀(a : Type) → (a → Text) → List a → Text-        =   λ(a : Type)-          → λ(f : a → Text)-          → λ(xs : List a)-          → List/fold a xs Text (λ(x : a) → λ(y : Text) → f x ++ y) ""--in  concatMap
− Prelude/Text/concatMapSep
@@ -1,45 +0,0 @@-{--Transform each value in a `List` to `Text` and then concatenate them with a-separator in between each value--Examples:--```-./concatMapSep ", " Integer Integer/show [ 0, 1, 2 ] = "0, 1, 2"--./concatMapSep ", " Integer Integer/show ([] : List Integer) = ""-```--}-    let concatMapSep-        : ∀(separator : Text) → ∀(a : Type) → (a → Text) → List a → Text-        =   λ(separator : Text)-          → λ(a : Type)-          → λ(f : a → Text)-          → λ(elements : List a)-          →     let status =-                      List/fold-                      a-                      elements-                      < Empty : {} | NonEmpty : Text >-                      (   λ(element : a)-                        → λ(status : < Empty : {} | NonEmpty : Text >)-                        → merge-                          { Empty    =-                              λ(_ : {}) → < NonEmpty = f element | Empty : {} >-                          , NonEmpty =-                                λ(result : Text)-                              → < NonEmpty = f element ++ separator ++ result-                                | Empty    : {}-                                >-                          }-                          status-                          : < Empty : {} | NonEmpty : Text >-                      )-                      < Empty = {=} | NonEmpty : Text >-            -            in  merge-                { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result }-                status-                : Text--in  concatMapSep
− Prelude/Text/concatSep
@@ -1,42 +0,0 @@-{--Concatenate a `List` of `Text` values with a separator in between each value--Examples:--```-./concatSep ", " [ "ABC", "DEF", "GHI" ] = "ABC, DEF, GHI"--./concatSep ", " ([] : List Text) = ""-```--}-    let concatSep-        : ∀(separator : Text) → ∀(elements : List Text) → Text-        =   λ(separator : Text)-          → λ(elements : List Text)-          →     let status =-                      List/fold-                      Text-                      elements-                      < Empty : {} | NonEmpty : Text >-                      (   λ(element : Text)-                        → λ(status : < Empty : {} | NonEmpty : Text >)-                        → merge-                          { Empty    =-                              λ(_ : {}) → < NonEmpty = element | Empty : {} >-                          , NonEmpty =-                                λ(result : Text)-                              → < NonEmpty = element ++ separator ++ result-                                | Empty    : {}-                                >-                          }-                          status-                          : < Empty : {} | NonEmpty : Text >-                      )-                      < Empty = {=} | NonEmpty : Text >-            -            in  merge-                { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result }-                status-                : Text--in  concatSep
+ benchmark/deep-nested-large-record/BigEnum.dhall view
@@ -0,0 +1,302 @@+< A0 : {}+| A1 : {}+| A2 : {}+| A3 : {}+| A4 : {}+| A5 : {}+| A6 : {}+| A7 : {}+| A8 : {}+| A9 : {}+| A10 : {}+| A11 : {}+| A12 : {}+| A13 : {}+| A14 : {}+| A15 : {}+| A16 : {}+| A17 : {}+| A18 : {}+| A19 : {}+| A20 : {}+| A21 : {}+| A22 : {}+| A23 : {}+| A24 : {}+| A25 : {}+| A26 : {}+| A27 : {}+| A28 : {}+| A29 : {}+| A30 : {}+| A31 : {}+| A32 : {}+| A33 : {}+| A34 : {}+| A35 : {}+| A36 : {}+| A37 : {}+| A38 : {}+| A39 : {}+| A40 : {}+| A41 : {}+| A42 : {}+| A43 : {}+| A44 : {}+| A45 : {}+| A46 : {}+| A47 : {}+| A48 : {}+| A49 : {}+| A50 : {}+| A51 : {}+| A52 : {}+| A53 : {}+| A54 : {}+| A55 : {}+| A56 : {}+| A57 : {}+| A58 : {}+| A59 : {}+| A60 : {}+| A61 : {}+| A62 : {}+| A63 : {}+| A64 : {}+| A65 : {}+| A66 : {}+| A67 : {}+| A68 : {}+| A69 : {}+| A70 : {}+| A71 : {}+| A72 : {}+| A73 : {}+| A74 : {}+| A75 : {}+| A76 : {}+| A77 : {}+| A78 : {}+| A79 : {}+| A80 : {}+| A81 : {}+| A82 : {}+| A83 : {}+| A84 : {}+| A85 : {}+| A86 : {}+| A87 : {}+| A88 : {}+| A89 : {}+| A90 : {}+| A91 : {}+| A92 : {}+| A93 : {}+| A94 : {}+| A95 : {}+| A96 : {}+| A97 : {}+| A98 : {}+| A99 : {}+| A100 : {}+| A101 : {}+| A102 : {}+| A103 : {}+| A104 : {}+| A105 : {}+| A106 : {}+| A107 : {}+| A108 : {}+| A109 : {}+| A110 : {}+| A111 : {}+| A112 : {}+| A113 : {}+| A114 : {}+| A115 : {}+| A116 : {}+| A117 : {}+| A118 : {}+| A119 : {}+| A120 : {}+| A121 : {}+| A122 : {}+| A123 : {}+| A124 : {}+| A125 : {}+| A126 : {}+| A127 : {}+| A128 : {}+| A129 : {}+| A130 : {}+| A131 : {}+| A132 : {}+| A133 : {}+| A134 : {}+| A135 : {}+| A136 : {}+| A137 : {}+| A138 : {}+| A139 : {}+| A140 : {}+| A141 : {}+| A142 : {}+| A143 : {}+| A144 : {}+| A145 : {}+| A146 : {}+| A147 : {}+| A148 : {}+| A149 : {}+| A150 : {}+| A151 : {}+| A152 : {}+| A153 : {}+| A154 : {}+| A155 : {}+| A156 : {}+| A157 : {}+| A158 : {}+| A159 : {}+| A160 : {}+| A161 : {}+| A162 : {}+| A163 : {}+| A164 : {}+| A165 : {}+| A166 : {}+| A167 : {}+| A168 : {}+| A169 : {}+| A170 : {}+| A171 : {}+| A172 : {}+| A173 : {}+| A174 : {}+| A175 : {}+| A176 : {}+| A177 : {}+| A178 : {}+| A179 : {}+| A180 : {}+| A181 : {}+| A182 : {}+| A183 : {}+| A184 : {}+| A185 : {}+| A186 : {}+| A187 : {}+| A188 : {}+| A189 : {}+| A190 : {}+| A191 : {}+| A192 : {}+| A193 : {}+| A194 : {}+| A195 : {}+| A196 : {}+| A197 : {}+| A198 : {}+| A199 : {}+| A200 : {}+| A201 : {}+| A202 : {}+| A203 : {}+| A204 : {}+| A205 : {}+| A206 : {}+| A207 : {}+| A208 : {}+| A209 : {}+| A210 : {}+| A211 : {}+| A212 : {}+| A213 : {}+| A214 : {}+| A215 : {}+| A216 : {}+| A217 : {}+| A218 : {}+| A219 : {}+| A220 : {}+| A221 : {}+| A222 : {}+| A223 : {}+| A224 : {}+| A225 : {}+| A226 : {}+| A227 : {}+| A228 : {}+| A229 : {}+| A230 : {}+| A231 : {}+| A232 : {}+| A233 : {}+| A234 : {}+| A235 : {}+| A236 : {}+| A237 : {}+| A238 : {}+| A239 : {}+| A240 : {}+| A241 : {}+| A242 : {}+| A243 : {}+| A244 : {}+| A245 : {}+| A246 : {}+| A247 : {}+| A248 : {}+| A249 : {}+| A250 : {}+| A251 : {}+| A252 : {}+| A253 : {}+| A254 : {}+| A255 : {}+| A256 : {}+| A257 : {}+| A258 : {}+| A259 : {}+| A260 : {}+| A261 : {}+| A262 : {}+| A263 : {}+| A264 : {}+| A265 : {}+| A266 : {}+| A267 : {}+| A268 : {}+| A269 : {}+| A270 : {}+| A271 : {}+| A272 : {}+| A273 : {}+| A274 : {}+| A275 : {}+| A276 : {}+| A277 : {}+| A278 : {}+| A279 : {}+| A280 : {}+| A281 : {}+| A282 : {}+| A283 : {}+| A284 : {}+| A285 : {}+| A286 : {}+| A287 : {}+| A288 : {}+| A289 : {}+| A290 : {}+| A291 : {}+| A292 : {}+| A293 : {}+| A294 : {}+| A295 : {}+| A296 : {}+| A297 : {}+| A298 : {}+| A299 : {}+| A300 : {}+>
+ benchmark/deep-nested-large-record/LittleEnum.dhall view
@@ -0,0 +1,4 @@+< Foo : {}+| Bar : {}+| Baz : {}+>
+ benchmark/deep-nested-large-record/Main.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE OverloadedStrings #-}+module Main (main) where++import Data.Void        (Void)+import Test.Tasty.Bench++import qualified Data.Sequence   as Seq+import qualified Dhall.Core      as Core+import qualified Dhall.Import    as Import+import qualified Dhall.TypeCheck as TypeCheck++dhallPreludeImport :: Core.Import+dhallPreludeImport = Core.Import+  { Core.importMode = Core.Code+  , Core.importHashed = Core.ImportHashed+    { Core.hash = Nothing+    , Core.importType = Core.Local Core.Here $ Core.File+      { Core.directory = Core.Directory ["deep-nested-large-record", "benchmark"]+      , Core.file = "prelude.dhall"+      }+    }+  }++issue412 :: Core.Expr s Void -> Benchmarkable+issue412 prelude = whnf TypeCheck.typeOf expr+  where+    expr+      = Core.Let (Core.Binding Nothing "prelude" Nothing Nothing Nothing prelude)+      $ Core.ListLit Nothing+      $ Seq.replicate 5+      $ Core.Var (Core.V "prelude" 0) `Core.Field` types `Core.Field` little `Core.Field` foo+    types = Core.makeFieldSelection "types"+    little = Core.makeFieldSelection "little"+    foo = Core.makeFieldSelection "Foo"++unionPerformance :: Core.Expr s Void -> Benchmarkable+unionPerformance prelude = whnf TypeCheck.typeOf expr+  where+    expr =+        Core.Let+            (Core.Binding+                Nothing+                "x"+                Nothing+                Nothing+                Nothing+                (Core.Let+                    (Core.Binding+                        Nothing+                        "big"+                        Nothing+                        Nothing+                        Nothing+                        (prelude `Core.Field` types `Core.Field` big)+                    )+                    (Core.Prefer mempty Core.PreferFromSource "big" "big")+                )+            )+            "x"+    types = Core.makeFieldSelection "types"+    big = Core.makeFieldSelection "Big"++main :: IO ()+main =+  defaultMain+    [ env prelude $ \p ->+      bgroup "Prelude"+        [ bench "issue 412" (issue412 p)+        , bench "union performance" (unionPerformance p)+        ]+    ]+  where prelude = Import.load (Core.Embed dhallPreludeImport)
+ benchmark/deep-nested-large-record/prelude.dhall view
@@ -0,0 +1,5 @@+{ types =+  { Big = ./BigEnum.dhall+  , Little = ./LittleEnum.dhall+  }+}
+ benchmark/parser/Main.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Exception (throw)+import Control.Monad     (forM)+import Data.Map          (Map)+import Data.Text         (Text)+import Data.Void         (Void)+import Test.Tasty.Bench++import qualified Data.ByteString.Lazy+import qualified Data.Map             as Map+import qualified Data.Text            as Text+import qualified Data.Text.IO+import qualified Dhall.Binary+import qualified Dhall.Core           as Dhall+import qualified Dhall.Parser         as Dhall+import qualified System.Directory     as Directory++type PreludeFiles = Map FilePath Text++loadPreludeFiles :: IO PreludeFiles+loadPreludeFiles = loadDirectory "./dhall-lang/Prelude"+    where+        loadDirectory :: FilePath -> IO PreludeFiles+        loadDirectory dir =+            Directory.withCurrentDirectory dir $ do+                files <- Directory.getCurrentDirectory >>= Directory.listDirectory+                results <- forM files $ \file -> do+                    file' <- Directory.makeAbsolute file+                    doesExist <- Directory.doesFileExist file'+                    if doesExist+                       then loadFile file'+                       else loadDirectory file'+                pure $ Map.unions results++        loadFile :: FilePath -> IO PreludeFiles+        loadFile path = Map.singleton path <$> Data.Text.IO.readFile path++benchParser :: PreludeFiles -> Benchmark+benchParser =+      bgroup "exprFromText"+    . Map.foldrWithKey (\name expr -> (benchExprFromText name expr :)) []++benchExprFromText :: String -> Text -> Benchmark+benchExprFromText name !expr =+    bench name $ whnf (Dhall.exprFromText "(input)") expr++benchExprFromBytes :: String -> Data.ByteString.Lazy.ByteString -> Benchmark+benchExprFromBytes name bs = bench name (nf f bs)+  where+    f bytes =+        case Dhall.Binary.decodeExpression bytes of+            Left  exception  -> error (show exception)+            Right expression -> expression :: Dhall.Expr Void Dhall.Import++benchNfExprFromText :: String -> Text -> Benchmark+benchNfExprFromText name !expr =+    bench name $ nf (either throw id . Dhall.exprFromText "(input)") expr++main :: IO ()+main = do+    prelude <- loadPreludeFiles+    defaultMain+        [ env issues $ \ ~(it, ib) ->+            bgroup "Issue #108"+                [ benchExprFromText  "Text"   it+                , benchExprFromBytes "Binary" ib+                ]+        , env kubernetesExample $+            benchExprFromBytes "Kubernetes/Binary"+        , benchExprFromText "Long variable names" (Text.replicate 1000000 "x")+        , benchExprFromText "Large number of function arguments" (Text.replicate 10000 "x ")+        , benchExprFromText "Long double-quoted strings" ("\"" <> Text.replicate 1000000 "x" <> "\"")+        , benchExprFromText "Long single-quoted strings" ("''" <> Text.replicate 1000000 "x" <> "''")+        , benchExprFromText "Whitespace" (Text.replicate 1000000 " " <> "x")+        , benchExprFromText "Line comment" ("x -- " <> Text.replicate 1000000 " ")+        , benchExprFromText "Block comment" ("x {- " <> Text.replicate 1000000 " " <> "-}")+        , benchExprFromText "Deeply nested parentheses" "((((((((((((((((x))))))))))))))))"+        , benchParser prelude+        , env cpkgExample $+            benchNfExprFromText "CPkg/Text"+        ]+    where+        cpkgExample = Data.Text.IO.readFile "benchmark/parser/examples/cpkg.dhall"+        issue108Text = Data.Text.IO.readFile "benchmark/parser/examples/issue108.dhall"+        issue108Bytes = Data.ByteString.Lazy.readFile "benchmark/parser/examples/issue108.dhallb"+        issues = (,) <$> issue108Text <*> issue108Bytes+        kubernetesExample = Data.ByteString.Lazy.readFile "benchmark/parser/examples/kubernetes.dhallb"
+ benchmark/parser/examples/cpkg.dhall view

file too large to diff

+ benchmark/parser/examples/issue108.dhall view
@@ -0,0 +1,63 @@+λ ( xs : List { cores : Natural , host : Text , key : Text , mandatoryFeatures :+List Text , platforms : List < AArch64_Linux : {} | ARMv5tel_Linux : {} |+ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} |+PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD :+{} | X86_64_Linux : {} | X86_64_Solaris : {} > , speedFactor : Natural ,+supportedFeatures : List Text , user : Optional Text } )→ List/fold { cores :+Natural , host : Text , key : Text , mandatoryFeatures : List Text , platforms :+List < AArch64_Linux : {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} |+I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} | PowerPC_Linux : {} |+X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux :+{} | X86_64_Solaris : {} > , speedFactor : Natural , supportedFeatures : List+Text , user : Optional Text } xs Text ( λ ( x : { cores : Natural , host : Text+, key : Text , mandatoryFeatures : List Text , platforms : List < AArch64_Linux+: {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux :+{} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} |+X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris :+{} > , speedFactor : Natural , supportedFeatures : List Text , user : Optional+Text } ) → λ(y : Text) →+merge { None = x.host, Some = λ(user : Text) → "${user}@${x.host}" } x.user+++ " " ++ ( merge { Empty = λ(_ : {}) → "",+NonEmpty = λ(result : Text) → result } ( List/fold < AArch64_Linux : {} |+ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |+MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :+{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > x.platforms+< Empty : {} | NonEmpty : Text > ( λ ( element : < AArch64_Linux : {} |+ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |+MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :+{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > ) →+λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <+NonEmpty : Text | Empty : {} >.NonEmpty ( merge { AArch64_Linux = λ(_ : {}) →+"aarch64-linux" , ARMv5tel_Linux = λ(_ : {}) → "armv5tel-linux" , ARMv7l_Linux =+λ(_ : {}) → "armv7l-linux" , I686_Cygwin = λ(_ : {}) → "i686-cygwin" ,+I686_Linux = λ(_ : {}) → "i686-linux" , MIPS64el_Linux = λ(_ : {}) →+"mips64el-linux" , PowerPC_Linux = λ(_ : {}) → "powerpc-linux" , X86_64_Cygwin =+λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin = λ(_ : {}) → "x86_64-darwin" ,+X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" , X86_64_Linux = λ(_ : {}) →+"x86_64-linux" , X86_64_Solaris = λ(_ : {}) → "x86_64-solaris" } element ) ,+NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty ( (+merge { AArch64_Linux = λ(_ : {}) → "aarch64-linux" , ARMv5tel_Linux = λ(_ : {})+→ "armv5tel-linux" , ARMv7l_Linux = λ(_ : {}) → "armv7l-linux" , I686_Cygwin =+λ(_ : {}) → "i686-cygwin" , I686_Linux = λ(_ : {}) → "i686-linux" ,+MIPS64el_Linux = λ(_ : {}) → "mips64el-linux" , PowerPC_Linux = λ(_ : {}) →+"powerpc-linux" , X86_64_Cygwin = λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin =+λ(_ : {}) → "x86_64-darwin" , X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" ,+X86_64_Linux = λ(_ : {}) → "x86_64-linux" , X86_64_Solaris = λ(_ : {}) →+"x86_64-solaris" } element ) ++ "," ++ result ) } status : < Empty : {} |+NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=}) ) : Text ) +++" " ++ x.key ++ " " ++ Integer/show (Natural/toInteger x.cores) ++ " " +++Integer/show (Natural/toInteger x.speedFactor) ++ " " ++ ( merge { Empty = λ(_ :+{}) → "", NonEmpty = λ(result : Text) → result } ( List/fold Text+x.supportedFeatures < Empty : {} | NonEmpty : Text > ( λ(element : Text) →+λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <+NonEmpty : Text | Empty : {} >.NonEmpty element , NonEmpty = λ(result : Text) →+< NonEmpty : Text | Empty : {} >.NonEmpty (element ++ "," ++ result) } status :+< Empty : {} | NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=})+) : Text ) ++ " " ++ ( merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result :+Text) → result } ( List/fold Text x.mandatoryFeatures < Empty : {} | NonEmpty :+Text > ( λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) →+merge { Empty = λ(_ : {}) → < NonEmpty : Text | Empty : {} >.NonEmpty element ,+NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty+(element ++ "," ++ result) } status : < Empty : {} | NonEmpty : Text > ) (<+Empty : {} | NonEmpty : Text+>.Empty {=}) ) : Text ) ++ "\n" ++ y ) ""
+ benchmark/parser/examples/issue108.dhallb view

binary file changed (absent → 3818 bytes)

+ benchmark/parser/examples/kubernetes.dhallb view

file too large to diff

+ benchmark/parser/examples/normalize/ChurchEval.dhall view
@@ -0,0 +1,22 @@++let Nat = ∀(N : Type) → (N → N) → N → N+let n2  = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s z)+let n5  = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s (s (s (s z))))++let mul =+  λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N (b N s) z++let add =+  λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N s (b N s z)++let n10   = mul n2 n5+let n100  = mul n10 n10+let n1k   = mul n10 n100+let n10k  = mul n100 n100+let n100k = mul n10 n10k+let n1M   = mul n10k n100+let n5M   = mul n1M n5+let n10M  = mul n1M n10+let n20M  = mul n10M n2++in n1M Natural (λ (x:Natural) → x + 1) 0
+ benchmark/parser/examples/normalize/FunCompose.dhall view
@@ -0,0 +1,18 @@++let compose+    : ∀(a : Type) → ∀(b : Type) → ∀(c : Type) → (a → b) → (b → c) → a → c+    =   λ(A : Type)+      → λ(B : Type)+      → λ(C : Type)+      → λ(f : A → B)+      → λ(g : B → C)+      → λ(x : A)+      → g (f x)++let composeN : ∀ (a : Type) → Natural → (a → a) → a → a+    = λ (a : Type)+	→ λ (n : Natural)+	→ λ (f : a → a)+	→ Natural/fold n (a → a) (compose a a a f) (λ (x : a) → x)++in composeN Natural 100000 (λ (x : Natural) → x + 1) 0
+ benchmark/parser/examples/normalize/ListBench.dhall view
@@ -0,0 +1,75 @@++let iterate+    =   λ(n : Natural)+      → λ(a : Type)+      → λ(f : a → a)+      → λ(x : a)+      → List/build+        a+        (   λ(list : Type)+          → λ(cons : a → list → list)+          → List/fold+            { index : Natural, value : {} }+            ( List/indexed+              {}+              ( List/build+                {}+                (   λ(list : Type)+                  → λ(cons : {} → list → list)+                  → Natural/fold n list (cons {=})+                )+              )+            )+            list+            (   λ(y : { index : Natural, value : {} })+              → cons (Natural/fold y.index a f x)+            )+        )++let countTo =+  λ (x : Natural)+  → iterate x Natural (λ (x : Natural) → x + 1) 0++let sum =+  λ (xs : List Natural)+  → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0+++let map+        : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b+        =   λ(a : Type)+          → λ(b : Type)+          → λ(f : a → b)+          → λ(xs : List a)+          → List/build+            b+            (   λ(list : Type)+              → λ(cons : b → list → list)+              → List/fold a xs list (λ(x : a) → cons (f x))+            )++let any+        : ∀(a : Type) → (a → Bool) → List a → Bool+        =   λ(a : Type)+          → λ(f : a → Bool)+          → λ(xs : List a)+          → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False++let filter+        : ∀(a : Type) → (a → Bool) → List a → List a+        =   λ(a : Type)+          → λ(f : a → Bool)+          → λ(xs : List a)+          → List/build+            a+            (   λ(list : Type)+              → λ(cons : a → list → list)+              → List/fold+                a+                xs+                list+                (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)+            )++in sum (filter Natural Natural/even+     (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
+ benchmark/parser/examples/normalize/ListBenchAlt.dhall view
@@ -0,0 +1,45 @@++let iterate =+    λ(n : Natural)+  → λ(a : Type)+  → λ(f : a → a)+  → λ(x : a)+  → (Natural/fold n+      (a → List a → {fst:a, snd:List a})+	  (λ (hyp : a → List a → {fst:a, snd:List a}) →+	   λ (x : a) → λ (xs : List a)+	   → let tup = hyp x xs+	     in {fst = f (tup.fst), snd = tup.snd # [tup.fst]})+	  (λ (x : a) → λ (xs : List a) → {fst=x, snd=xs})+	  x ([] : List a)).snd++let countTo =+  λ (x : Natural)+  → iterate x Natural (λ (x : Natural) → x + 1) 0++let sum =+  λ (xs : List Natural)+  → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0++let map+  =   λ(a : Type)+    → λ(b : Type)+    → λ(f : a → b)+    → λ(xs : List a)+	→ List/fold a xs (List b) (λ (x : a) → λ (xs : List b) → [f x] # xs) ([] : List b)++let any+  =   λ(a : Type)+        → λ(f : a → Bool)+        → λ(xs : List a)+        → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False++let filter+  =   λ(a : Type)+    → λ(f : a → Bool)+    → λ(xs : List a)+	→ List/fold a xs (List a)+	    (λ (x : a) → λ (xs : List a) → if f x then [x] # xs else xs) ([] : List a)++in sum (filter Natural Natural/even+     (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
− dhall-format/Main.hs
@@ -1,112 +0,0 @@-{-# LANGUAGE DataKinds          #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE ExplicitNamespaces #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE TypeOperators      #-}--{-| Utility executable for pretty-printing Dhall code--    You typically want to use this to either:--    * improve the readability of Dhall code (either written or generated)-    * automatically format your Dhall code to avoid stylistic debates--    Note that this does not yet support:--    * Preserving all comments-        * Currently, this only preserves all leading comments and whitespace-          up until the last newline preceding the code-        * This lets you preserve a comment header but if you want to document-          subexpressions then you will need to split them into a separate-          file for now-    * Preserving multi-line strings (this reduces them to ordinary strings)--    See the @Dhall.Tutorial@ module for example usage--}-module Main where--import Control.Exception (SomeException)-import Control.Monad (when)-import Data.Monoid ((<>))-import Data.Version (showVersion)-import Dhall.Parser (exprAndHeaderFromText)-import Dhall.Pretty (annToAnsiStyle, prettyExpr)-import Options.Generic (Generic, ParseRecord, Wrapped, type (<?>)(..), (:::))-import System.IO (stderr)-import System.Exit (exitFailure, exitSuccess)-import Text.Trifecta.Delta (Delta(..))--import qualified Paths_dhall as Meta--import qualified Control.Exception-import qualified Data.Text.IO-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.IO-import qualified Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Options.Generic-import qualified System.Console.ANSI-import qualified System.IO--data Options w = Options-    { version :: w ::: Bool           <?> "Display version and exit"-    , inplace :: w ::: Maybe FilePath <?> "Modify the specified file in-place"-    } deriving (Generic)--instance ParseRecord (Options Wrapped)--opts :: Pretty.LayoutOptions-opts =-    Pretty.defaultLayoutOptions-        { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }--main :: IO ()-main = do-    Options {..} <- Options.Generic.unwrapRecord "Formatter for the Dhall language"-    when version $ do-      putStrLn (showVersion Meta.version)-      exitSuccess--    let handler e = do-            let _ = e :: SomeException-            System.IO.hSetEncoding System.IO.stderr System.IO.utf8-            System.IO.hPrint stderr e-            System.Exit.exitFailure--    Control.Exception.handle handler (do-        case inplace of-            Just file -> do-                strictText <- Data.Text.IO.readFile file-                let lazyText = Data.Text.Lazy.fromStrict strictText-                (header, expr) <- case exprAndHeaderFromText (Directed "(stdin)" 0 0 0 0) lazyText of-                    Left  err -> Control.Exception.throwIO err-                    Right x   -> return x--                let doc = Pretty.pretty header <> Pretty.pretty expr-                System.IO.withFile file System.IO.WriteMode (\handle -> do-                    Pretty.renderIO handle (Pretty.layoutSmart opts doc)-                    Data.Text.IO.hPutStrLn handle "" )-            Nothing -> do-                System.IO.hSetEncoding System.IO.stdin System.IO.utf8-                inText <- Data.Text.Lazy.IO.getContents--                (header, expr) <- case exprAndHeaderFromText (Directed "(stdin)" 0 0 0 0) inText of-                    Left  err -> Control.Exception.throwIO err-                    Right x   -> return x--                let doc = Pretty.pretty header <> prettyExpr expr--                supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout--                if supportsANSI-                  then-                    Pretty.renderIO-                      System.IO.stdout-                      (fmap annToAnsiStyle (Pretty.layoutSmart opts doc))-                  else-                    Pretty.renderIO-                      System.IO.stdout-                      (Pretty.layoutSmart opts (Pretty.unAnnotate doc))-                Data.Text.IO.putStrLn "")
− dhall-hash/Main.hs
@@ -1,87 +0,0 @@-{-# LANGUAGE DataKinds          #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE ExplicitNamespaces #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE TypeOperators      #-}--module Main where--import Control.Exception (SomeException)-import Control.Monad (when)-import Data.Version (showVersion)-import Dhall.Core (normalize)-import Dhall.Import (Imported(..), hashExpressionToCode, load)-import Dhall.Parser (Src, exprFromText)-import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X)-import Options.Generic (Generic, ParseRecord, Wrapped, type (<?>)(..), (:::))-import System.IO (stderr)-import System.Exit (exitFailure, exitSuccess)-import Text.Trifecta.Delta (Delta(..))--import qualified Paths_dhall as Meta--import qualified Control.Exception-import qualified Data.Text.Lazy.IO-import qualified Dhall.TypeCheck-import qualified Options.Generic-import qualified System.IO--data Options w = Options-    { explain :: w ::: Bool <?> "Explain error messages in more detail"-    , version :: w ::: Bool <?> "Display version and exit"-    } deriving (Generic)--instance ParseRecord (Options Wrapped)--main :: IO ()-main = do-    Options {..} <- Options.Generic.unwrapRecord "Compiler for the Dhall language"-    when version $ do-      putStrLn (showVersion Meta.version)-      exitSuccess-    let handle =-                Control.Exception.handle handler2-            .   Control.Exception.handle handler1-            .   Control.Exception.handle handler0-          where-            handler0 e = do-                let _ = e :: TypeError Src X-                System.IO.hPutStrLn stderr ""-                if explain-                    then Control.Exception.throwIO (DetailedTypeError e)-                    else do-                        Data.Text.Lazy.IO.hPutStrLn stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"-                        Control.Exception.throwIO e--            handler1 (Imported ps e) = do-                let _ = e :: TypeError Src X-                System.IO.hPutStrLn stderr ""-                if explain-                    then Control.Exception.throwIO (Imported ps (DetailedTypeError e))-                    else do-                        Data.Text.Lazy.IO.hPutStrLn stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"-                        Control.Exception.throwIO (Imported ps e)--            handler2 e = do-                let _ = e :: SomeException-                System.IO.hSetEncoding System.IO.stderr System.IO.utf8-                System.IO.hPrint stderr e-                System.Exit.exitFailure--    handle (do-        System.IO.hSetEncoding System.IO.stdin System.IO.utf8-        inText <- Data.Text.Lazy.IO.getContents--        expr <- case exprFromText (Directed "(stdin)" 0 0 0 0) inText of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr--        expr' <- load expr--        _ <- case Dhall.TypeCheck.typeOf expr' of-            Left  err -> Control.Exception.throwIO err-            Right _   -> return ()--        Data.Text.Lazy.IO.putStrLn (hashExpressionToCode (normalize expr')) )
+ dhall-lang/Prelude/Bool/and view
@@ -0,0 +1,3 @@+  missing+    sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d+? ./and.dhall
+ dhall-lang/Prelude/Bool/and.dhall view
@@ -0,0 +1,14 @@+{-|+The `and` function returns `False` if there are any `False` elements in the+`List` and returns `True` otherwise+-}+let and+    : List Bool → Bool+    = λ(xs : List Bool) →+        List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l && r) True++let example0 = assert : and [ True, False, True ] ≡ False++let example1 = assert : and ([] : List Bool) ≡ True++in  and
+ dhall-lang/Prelude/Bool/build view
@@ -0,0 +1,3 @@+  missing+    sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b+? ./build.dhall
+ dhall-lang/Prelude/Bool/build.dhall view
@@ -0,0 +1,16 @@+--| `build` is the inverse of `fold`+let build+    : (∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool+    = λ(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) →+        f Bool True False++let example0 =+        assert+      : build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true) ≡ True++let example1 =+        assert+      :   build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)+        ≡ False++in  build
+ dhall-lang/Prelude/Bool/equal.dhall view
@@ -0,0 +1,6 @@+--| Returns `True` if both arguments are equal and returns `False` otherwise+let equal+    : Bool -> Bool -> Bool+    = \(x : Bool) -> \(y : Bool) -> x == y++in  equal
+ dhall-lang/Prelude/Bool/even view
@@ -0,0 +1,3 @@+  missing+    sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5+? ./even.dhall
+ dhall-lang/Prelude/Bool/even.dhall view
@@ -0,0 +1,20 @@+{-|+Returns `True` if there are an even number of `False` elements in the list and+returns `False` otherwise.++This function is the `Monoid` for the `==` operation.+-}+let even+    : List Bool → Bool+    = λ(xs : List Bool) →+        List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x == y) True++let example0 = assert : even [ False, True, False ] ≡ True++let example1 = assert : even [ False, True ] ≡ False++let example2 = assert : even [ False ] ≡ False++let example3 = assert : even ([] : List Bool) ≡ True++in  even
+ dhall-lang/Prelude/Bool/fold view
@@ -0,0 +1,3 @@+  missing+    sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae+? ./fold.dhall
+ dhall-lang/Prelude/Bool/fold.dhall view
@@ -0,0 +1,14 @@+--| `fold` is essentially the same as `if`/`then`/`else` except as a function+let fold+    : ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool+    = λ(b : Bool) →+      λ(bool : Type) →+      λ(true : bool) →+      λ(false : bool) →+        if b then true else false++let example0 = assert : fold True Natural 0 1 ≡ 0++let example1 = assert : fold False Natural 0 1 ≡ 1++in  fold
+ dhall-lang/Prelude/Bool/not view
@@ -0,0 +1,3 @@+  missing+    sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+? ./not.dhall
+ dhall-lang/Prelude/Bool/not.dhall view
@@ -0,0 +1,10 @@+--| Flip the value of a `Bool`+let not+    : Bool → Bool+    = λ(b : Bool) → b == False++let example0 = assert : not True ≡ False++let example1 = assert : not False ≡ True++in  not
+ dhall-lang/Prelude/Bool/odd view
@@ -0,0 +1,3 @@+  missing+    sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999+? ./odd.dhall
+ dhall-lang/Prelude/Bool/odd.dhall view
@@ -0,0 +1,20 @@+{-|+Returns `True` if there are an odd number of `True` elements in the list and+returns `False` otherwise.++This function is the `Monoid` for the `!=` operation.+-}+let odd+    : List Bool → Bool+    = λ(xs : List Bool) →+        List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x != y) False++let example0 = assert : odd [ True, False, True ] ≡ False++let example1 = assert : odd [ True, False ] ≡ True++let example2 = assert : odd [ True ] ≡ True++let example3 = assert : odd ([] : List Bool) ≡ False++in  odd
+ dhall-lang/Prelude/Bool/or view
@@ -0,0 +1,3 @@+  missing+    sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4+? ./or.dhall
+ dhall-lang/Prelude/Bool/or.dhall view
@@ -0,0 +1,14 @@+{-|+The `or` function returns `True` if there are any `True` elements in the `List`+and returns `False` otherwise+-}+let or+    : List Bool → Bool+    = λ(xs : List Bool) →+        List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l || r) False++let example0 = assert : or [ True, False, True ] ≡ True++let example1 = assert : or ([] : List Bool) ≡ False++in  or
+ dhall-lang/Prelude/Bool/package.dhall view
@@ -0,0 +1,37 @@+{ and =+      missing+        sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d+    ? ./and.dhall+, build =+      missing+        sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b+    ? ./build.dhall+, equal =+      missing+        sha256:f0dc047ca14644c2a979bb126f2a3c6659ec770c66bd7beb70ae4a9d05815709+    ? ./equal.dhall+, even =+      missing+        sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5+    ? ./even.dhall+, fold =+      missing+        sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae+    ? ./fold.dhall+, not =+      missing+        sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+    ? ./not.dhall+, odd =+      missing+        sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999+    ? ./odd.dhall+, or =+      missing+        sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4+    ? ./or.dhall+, show =+      missing+        sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61+    ? ./show.dhall+}
+ dhall-lang/Prelude/Bool/show view
@@ -0,0 +1,3 @@+  missing+    sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61+? ./show.dhall
+ dhall-lang/Prelude/Bool/show.dhall view
@@ -0,0 +1,13 @@+{-|+Render a `Bool` as `Text` using the same representation as Dhall source code+(i.e. beginning with a capital letter)+-}+let show+    : Bool → Text+    = λ(b : Bool) → if b then "True" else "False"++let example0 = assert : show True ≡ "True"++let example1 = assert : show False ≡ "False"++in  show
+ dhall-lang/Prelude/Date/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:8a0eb9732cbc3c8f161b7cb05b183493befacc4728d2d9b7ee1384f19106a5ff+    ? ./show.dhall+}
+ dhall-lang/Prelude/Date/show.dhall view
@@ -0,0 +1,15 @@+{-+Render a `Date` as `Text` using the same representation as Dhall source code+(i.e. `YYYY-MM-DD`)+-}+let show+    : Date → Text+    = Date/show++let example0 = assert : show 2000-09-02 ≡ "2000-09-02"++let example1 = assert : show 9999-12-31 ≡ "9999-12-31"++let example2 = assert : show 0000-01-01 ≡ "0000-01-01"++in  show
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/Type.dhall view
@@ -0,0 +1,5 @@+{-|+A (total) set of access rights; See chmod(5) for an explanation of the flags.+For a partial set of of access rights see `Access`.+-}+{ execute : Bool, read : Bool, write : Bool }
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/intersect.dhall view
@@ -0,0 +1,69 @@+{-|+@intersect a b@ intesects the flags of the two `Mask`s @a@ and @b@. This+resembles the bitwise "and", i.e. the value of a flag is 'True' if and only if+it is set to 'True' in both @a@ and @b@. As a consequence @intersect a rwx == a@+and @intersect a none == none@ for all @a@.+-}+let Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ./Type.dhall++let intersect+    : Mask -> Mask -> Mask+    = \(m1 : Mask) ->+      \(m2 : Mask) ->+        { read = m1.read && m2.read+        , write = m1.write && m2.write+        , execute = m1.execute && m2.execute+        }++let example0 =+      let r =+              missing+                sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+            ? ./r.dhall++      let w =+              missing+                sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+            ? ./w.dhall++      let x =+              missing+                sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+            ? ./x.dhall++      let rwx =+              missing+                sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+            ? ./rwx.dhall++      let none =+              missing+                sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+            ? ./none.dhall++      in  assert : intersect r (intersect w (intersect x rwx)) === none++let example1 =+      \(a : Mask) ->+        let rwx =+                missing+                  sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+              ? ./rwx.dhall++        in    assert+            :     intersect a rwx+              ===  { execute = a.execute, read = a.read, write = a.write }++let example2 =+      \(a : Mask) ->+        let none =+                missing+                  sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+              ? ./none.dhall++        in  assert : intersect a none === none++in  intersect
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/invert.dhall view
@@ -0,0 +1,48 @@+{-|+Inverts the flags set in a `Mask`.+-}+let Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ./Type.dhall++let Bool/not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../../../Bool/not.dhall++let invert+    : Mask -> Mask+    = \(m : Mask) ->+        { read = Bool/not m.read+        , write = Bool/not m.write+        , execute = Bool/not m.execute+        }++let example0 =+      let none =+              missing+                sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+            ? ./none.dhall++      let rwx =+              missing+                sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+            ? ./rwx.dhall++      in  assert : invert rwx === none++let example1 =+      let none =+              missing+                sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+            ? ./none.dhall++      let rwx =+              missing+                sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+            ? ./rwx.dhall++      in  assert : invert none === rwx++in  invert
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/none.dhall view
@@ -0,0 +1,4 @@+  { read = False, write = False, execute = False }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/package.dhall view
@@ -0,0 +1,53 @@+{ Type =+      missing+        sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+    ? ./Type.dhall+, intersect =+      missing+        sha256:7c7dab3e305f43cba556e0778b5a797cf8e9b1d1a6c6f6fe0ea311c329919663+    ? ./intersect.dhall+, invert =+      missing+        sha256:8807fb02f694fe2117f8a7f794e5afbb967ec36eac3405184bf9232c33cdd830+    ? ./invert.dhall+, none =+      missing+        sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+    ? ./none.dhall+, r =+      missing+        sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+    ? ./r.dhall+, rw =+      missing+        sha256:c3cce19f462b841e64adafbdf2963699a0031f5fc08b041c8ad364483c544d8b+    ? ./rw.dhall+, rwx =+      missing+        sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+    ? ./rwx.dhall+, rx =+      missing+        sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+    ? ./rx.dhall+, toAccess =+      missing+        sha256:78fe016f0273b2551c8590da71bf204cc26d6879c6b84622d4d8ad5624328438+    ? ./toAccess.dhall+, toAccessWith =+      missing+        sha256:814ab74ad292c121620a1f468837d4a5473323423bf68c1bceca69e7b3c59077+    ? ./toAccessWith.dhall+, union =+      missing+        sha256:b40c4cbb266991e3f764af075e9db544b59c16b3d9aa680c0cf6cb7552da191f+    ? ./union.dhall+, w =+      missing+        sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+    ? ./w.dhall+, x =+      missing+        sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+    ? ./x.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/r.dhall view
@@ -0,0 +1,4 @@+  { read = True, write = False, execute = False }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/rw.dhall view
@@ -0,0 +1,4 @@+  { read = True, write = True, execute = False }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/rwx.dhall view
@@ -0,0 +1,4 @@+  { read = True, write = True, execute = True }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/rx.dhall view
@@ -0,0 +1,4 @@+  { read = True, write = False, execute = True }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/toAccess.dhall view
@@ -0,0 +1,20 @@+{-|+Convert a `Mask` value to an `Access` value. For a partial conversion see+`toAccessWith`.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../Type.dhall++let Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ./Type.dhall++let toAccess+    : Mask -> Access+    = \(m : Mask) ->+        { execute = Some m.execute, read = Some m.read, write = Some m.write }++in  toAccess
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/toAccessWith.dhall view
@@ -0,0 +1,42 @@+{-|+@toAccessWith x m@ converts some fields of a `Mask` @m@ to an `Access` setting:+If the respective field is set in the first `Mask` @x@, then the flag will be+set to the flags value given in @m@. Otherwise, the value set in @m@ is ignored+and the value of the flag in the result is `None`.++For a motivation of this function see the documenation on `toModeWith`.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../Type.dhall++let Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ./Type.dhall++let toAccessWith+    : Mask -> Mask -> Access+    = \(set : Mask) ->+      \(m : Mask) ->+        { execute = if set.execute then Some m.execute else None Bool+        , read = if set.read then Some m.read else None Bool+        , write = if set.write then Some m.write else None Bool+        }++let example0 =+      \(a : Mask) ->+        let Access/none =+                missing+                  sha256:955a2eed689139c811d4b9ef3dd8d0c484392b18c3bb8752c59fd69dbdaf4881+              ? ../none.dhall++        let none =+                missing+                  sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+              ? ./none.dhall++        in  assert : toAccessWith none a === Access/none++in  toAccessWith
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/union.dhall view
@@ -0,0 +1,64 @@+{-|+@union a b@ combines the flags of the two `Mask`s @a@ and @b@. This resembles+the bitwise "or", i.e. the value of a flag is 'True' if it is set to 'True' in+either @a@ and @b@. As a consequence @union a rwx == rwx@ and+@union a none == a@ for all @a@.+-}+let Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ./Type.dhall++let union+    : Mask -> Mask -> Mask+    = \(m1 : Mask) ->+      \(m2 : Mask) ->+        { read = m1.read || m2.read+        , write = m1.write || m2.write+        , execute = m1.execute || m2.execute+        }++let example0 =+      let r =+              missing+                sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+            ? ./r.dhall++      let w =+              missing+                sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+            ? ./w.dhall++      let x =+              missing+                sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+            ? ./x.dhall++      let rwx =+              missing+                sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+            ? ./rwx.dhall++      in  assert : union r (union w x) === rwx++let example1 =+      \(a : Mask) ->+        let rwx =+                missing+                  sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+              ? ./rwx.dhall++        in  assert : union a rwx === rwx++let example1 =+      \(a : Mask) ->+        let none =+                missing+                  sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+              ? ./none.dhall++        in    assert+            :     union a none+              ===  { execute = a.execute, read = a.read, write = a.write }++in  union
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/w.dhall view
@@ -0,0 +1,4 @@+  { read = False, write = True, execute = False }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Mask/x.dhall view
@@ -0,0 +1,4 @@+  { read = False, write = False, execute = True }+:   missing+      sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/Type.dhall view
@@ -0,0 +1,5 @@+{-|+A (partial) set of access rights; See chmod(5) for an explanation of the flags.+For a total set of access rights see `Mask`.+-}+{ execute : Optional Bool, read : Optional Bool, write : Optional Bool }
+ dhall-lang/Prelude/DirectoryTree/Access/equal.dhall view
@@ -0,0 +1,29 @@+{-|+`equal` checks if two `Access` settings are equal.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ./Type.dhall++let Bool/equal =+        missing+          sha256:f0dc047ca14644c2a979bb126f2a3c6659ec770c66bd7beb70ae4a9d05815709+      ? ../../Bool/equal.dhall++let Optional/equal =+        missing+          sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+      ? ../../Optional/equal.dhall++let f+    : Optional Bool -> Optional Bool -> Bool+    = Optional/equal Bool Bool/equal++let equal+    : Access -> Access -> Bool+    = \(a1 : Access) ->+      \(a2 : Access) ->+        f a1.execute a2.execute && f a1.read a2.read && f a1.write a2.write++in  equal
+ dhall-lang/Prelude/DirectoryTree/Access/none.dhall view
@@ -0,0 +1,4 @@+  { read = None Bool, write = None Bool, execute = None Bool }+:   missing+      sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+  ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Access/package.dhall view
@@ -0,0 +1,17 @@+{ Mask =+      missing+        sha256:ed736de51ea15a2ef671eaa7219dfbf3138bb52acfd0ae17894acf2ec4b06369+    ? ./Mask/package.dhall+, Type =+      missing+        sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+    ? ./Type.dhall+, equal =+      missing+        sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+    ? ./equal.dhall+, schema =+      missing+        sha256:7d33a584a42a5d92411d5ca623e27ccb397762905be86ecfd01b106719fae690+    ? ./schema.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Access/schema.dhall view
@@ -0,0 +1,12 @@+{-|+A schema for blank access rights.+-}+{ Type =+      missing+        sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+    ? ./Type.dhall+, default =+      missing+        sha256:955a2eed689139c811d4b9ef3dd8d0c484392b18c3bb8752c59fd69dbdaf4881+    ? ./none.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Entry/BinaryFileEntry.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+      ? ./Type.dhall++in  Entry Bytes
+ dhall-lang/Prelude/DirectoryTree/Entry/DirectoryEntry.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+      ? ./Type.dhall++in  \(tree : Type) -> Entry (List tree)
+ dhall-lang/Prelude/DirectoryTree/Entry/Metadata.dhall view
@@ -0,0 +1,24 @@+{-|+An `Entry` without content. That in turn implies that the type of the entry+(i.e. whether it is a file or a directory) is not (yet) fixed as well.+-}+let User =+        missing+          sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+      ? ../User/Type.dhall++let Group =+        missing+          sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+      ? ../Group/Type.dhall++let Mode =+        missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ../Mode/Type.dhall++in  { name : Text+    , user : Optional User+    , group : Optional Group+    , mode : Optional Mode+    }
+ dhall-lang/Prelude/DirectoryTree/Entry/TextFileEntry.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+      ? ./Type.dhall++in  Entry Text
+ dhall-lang/Prelude/DirectoryTree/Entry/Type.dhall view
@@ -0,0 +1,6 @@+let Metadata =+        missing+          sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+      ? ./Metadata.dhall++in  \(content : Type) -> Metadata //\\ { content : content }
+ dhall-lang/Prelude/DirectoryTree/Entry/binary-file.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+      ? ./entry.dhall++in  Entry Bytes
+ dhall-lang/Prelude/DirectoryTree/Entry/directory.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+      ? ./entry.dhall++in  \(tree : Type) -> Entry (List tree)
+ dhall-lang/Prelude/DirectoryTree/Entry/entry.dhall view
@@ -0,0 +1,24 @@+let Entry =+        missing+          sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+      ? ./Type.dhall++let User =+        missing+          sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+      ? ../User/Type.dhall++let Group =+        missing+          sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+      ? ../Group/Type.dhall++let Mode =+        missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ../Mode/Type.dhall++in  \(content : Type) ->+      { Type = Entry content+      , default = { user = None User, group = None Group, mode = None Mode }+      }
+ dhall-lang/Prelude/DirectoryTree/Entry/package.dhall view
@@ -0,0 +1,37 @@+{ BinaryFileEntry =+      missing+        sha256:f027db2893f6f38bbe6d868a91f22de530e85407237f00b147427c87d32bf55c+    ? ./BinaryFileEntry.dhall+, DirectoryEntry =+      missing+        sha256:163a4536fdd05ce122d793ceda01d03fcffb29463817ae8b7b5601bf4a06ce6e+    ? ./DirectoryEntry.dhall+, Metadata =+      missing+        sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+    ? ./Metadata.dhall+, TextFileEntry =+      missing+        sha256:23a8cb29d96aeb623501519d9a62c5c49659e8d1c30b4ae4f2399809e3fd3a01+    ? ./TextFileEntry.dhall+, Type =+      missing+        sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+    ? ./Type.dhall+, binary-file =+      missing+        sha256:bd49df43268c259e3d0bef995917c3ab517ae7b98bf1faac8f4a7e8a602e3465+    ? ./binary-file.dhall+, directory =+      missing+        sha256:0bee17310a21efa5b06f139b6731fdcee4f9e0245ef711c2b0127b8938dfed2e+    ? ./directory.dhall+, entry =+      missing+        sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+    ? ./entry.dhall+, text-file =+      missing+        sha256:c5d76fd43216668d03df9945183fe7b3c55486aedcc77324c3372bd63e283b78+    ? ./text-file.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Entry/text-file.dhall view
@@ -0,0 +1,6 @@+let Entry =+        missing+          sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+      ? ./entry.dhall++in  Entry Text
+ dhall-lang/Prelude/DirectoryTree/Group/Type.dhall view
@@ -0,0 +1,1 @@+< GroupId : Natural | GroupName : Text >
+ dhall-lang/Prelude/DirectoryTree/Group/id.dhall view
@@ -0,0 +1,6 @@+let Group =+        missing+          sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+      ? ./Type.dhall++in  Group.GroupId
+ dhall-lang/Prelude/DirectoryTree/Group/name.dhall view
@@ -0,0 +1,6 @@+let Group =+        missing+          sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+      ? ./Type.dhall++in  Group.GroupName
+ dhall-lang/Prelude/DirectoryTree/Group/package.dhall view
@@ -0,0 +1,13 @@+{ Type =+      missing+        sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+    ? ./Type.dhall+, id =+      missing+        sha256:2bf9e546f56a583243d419a652caba16ca4053df9ccb3c5b242506d86806944b+    ? ./id.dhall+, name =+      missing+        sha256:51ac5c407f2939ab0c80bf2896d292ee6049bd8ba10acda0af327a3777f2205d+    ? ./name.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/Type.dhall view
@@ -0,0 +1,10 @@+{-|+A complete mode with all access rights specified explicitely. For an incomplete+mode where some access rights might not be set see `Mode`.+-}+let Access/Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ../../Access/Mask/Type.dhall++in  { user : Access/Mask, group : Access/Mask, other : Access/Mask }
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/all.dhall view
@@ -0,0 +1,9 @@+{-|+Permissions with all flags set: rwxrwxrwx+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++in  { user = rwx, group = rwx, other = rwx }
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/directory.dhall view
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for directories: rwxr-xr-x+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++let rx =+        missing+          sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+      ? ../../Access/Mask/rx.dhall++in    { user = rwx, group = rx, other = rx }+    :   missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/executable.dhall view
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for executable files: rwxr-xr-x+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++let rx =+        missing+          sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+      ? ../../Access/Mask/rx.dhall++in    { user = rwx, group = rx, other = rx }+    :   missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/file.dhall view
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for regular files: rw-r--r--+-}+let r =+        missing+          sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+      ? ../../Access/Mask/r.dhall++let rw =+        missing+          sha256:c3cce19f462b841e64adafbdf2963699a0031f5fc08b041c8ad364483c544d8b+      ? ../../Access/Mask/rw.dhall++in    { user = rw, group = r, other = r }+    :   missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/group.dhall view
@@ -0,0 +1,14 @@+{-|+Permissions with group flags set: ---rwx---+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++let none =+        missing+          sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+      ? ../../Access/Mask/none.dhall++in  { user = none, group = rwx, other = none }
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/intersect.dhall view
@@ -0,0 +1,24 @@+{-|+Calculates the intersection of the access rights of two `Mask`s using+`Access/intersect`.+-}+let Mask =+        missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall++let Access/intersect =+        missing+          sha256:7c7dab3e305f43cba556e0778b5a797cf8e9b1d1a6c6f6fe0ea311c329919663+      ? ../../Access/Mask/intersect.dhall++let intersect+    : Mask -> Mask -> Mask+    = \(m1 : Mask) ->+      \(m2 : Mask) ->+        { user = Access/intersect m1.user m2.user+        , group = Access/intersect m1.group m2.group+        , other = Access/intersect m1.other m2.other+        }++in  intersect
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/invert.dhall view
@@ -0,0 +1,22 @@+{-|+Inverts each access right set in a `Mask` using `Access/invert`.+-}+let Mask =+        missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall++let Access/invert =+        missing+          sha256:8807fb02f694fe2117f8a7f794e5afbb967ec36eac3405184bf9232c33cdd830+      ? ../../Access/Mask/invert.dhall++let invert+    : Mask -> Mask+    = \(m : Mask) ->+        { user = Access/invert m.user+        , group = Access/invert m.group+        , other = Access/invert m.other+        }++in  invert
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/none.dhall view
@@ -0,0 +1,12 @@+{-|+Permissions with no flags set: ---------+-}+let none =+        missing+          sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+      ? ../../Access/Mask/none.dhall++in    { user = none, group = none, other = none }+    :   missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/other.dhall view
@@ -0,0 +1,14 @@+{-|+Permissions with other flags set: ------rwx+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++let none =+        missing+          sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+      ? ../../Access/Mask/none.dhall++in  { user = none, group = none, other = rwx }
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/package.dhall view
@@ -0,0 +1,41 @@+{ Type =+      missing+        sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+    ? ./Type.dhall+, directory =+      missing+        sha256:a43f235f0caa25c7cabd89ac5d77e466e0c0ebf3339046993c18e481930243fd+    ? ./directory.dhall+, executable =+      missing+        sha256:a43f235f0caa25c7cabd89ac5d77e466e0c0ebf3339046993c18e481930243fd+    ? ./executable.dhall+, file =+      missing+        sha256:32d34228d48a707996272d1c9681171ddcd6651f72eeb3de9727d1c26ba99df3+    ? ./file.dhall+, intersect =+      missing+        sha256:146be962523ef619d3a250699f977b69c3e5f6c24b975453f351c0e807266fc8+    ? ./intersect.dhall+, invert =+      missing+        sha256:07a13d8c233d0a9fd6b3a11475987c10619072fec882c96bc5499bfb3c01e9b2+    ? ./invert.dhall+, none =+      missing+        sha256:7cac21e2b72cadf3ee0bf10680df4902ca73b6ee070219df5eac1a24cd66ccdf+    ? ./none.dhall+, toMode =+      missing+        sha256:af2b0dab799374afa0a2f28551446760ff29f4697c200da0a8b0a8def7feee2a+    ? ./toMode.dhall+, toModeWith =+      missing+        sha256:b92327bec9141cc1a55bc3f11ae2584af0883b94fe2513376fc40f1da5ade9b2+    ? ./toModeWith.dhall+, union =+      missing+        sha256:3bb32fc6ea21f661571e46d90e450e0340b2f2b65482ba7bd1a30514e1b39fc2+    ? ./union.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/toMode.dhall view
@@ -0,0 +1,28 @@+{-|+Convert a `Mask` value to a `Mode` value. For a partial conversion see+`toModeWith`.+-}+let Mode =+        missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ../Type.dhall++let Mask =+        missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall++let Access/toAccess =+        missing+          sha256:78fe016f0273b2551c8590da71bf204cc26d6879c6b84622d4d8ad5624328438+      ? ../../Access/Mask/toAccess.dhall++let toMode+    : Mask -> Mode+    = \(m : Mask) ->+        { user = Some (Access/toAccess m.user)+        , group = Some (Access/toAccess m.group)+        , other = Some (Access/toAccess m.other)+        }++in  toMode
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/toModeWith.dhall view
@@ -0,0 +1,149 @@+{-|+@toModeWith x m@ converts some fields of a `Mask` @m@ to a `Mode`: If the+respective field is set in the first `Mask` @x@, then the flag will be set to+the flags value given in @m@. Otherwise, the value set in @m@ is ignored and the+value of the flag in the result is `None`.++The function is motivated by the following use case:+Alice has her umask set to 022 and new files will have permissions set to+rw-r--r--. Bob has the umask set to 077, hence newly created files will have+rw------- permissions. Now Eve distributes Dhall code writing a file with the+following mode to the filesystem:+```dhall+let mask = ./other.dhall++let permissions = ./all.dhall++in+toModeWith mask permissions+```+The written file will have rw-r--rwx permissions for Alice and rw----rwx+permissions for Bob as the `toModeWith mask` produces a `Mode` that will only+apply the permissions for the 'other' part.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../../Access/Type.dhall++let Access/Mask =+        missing+          sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+      ? ../../Access/Mask/Type.dhall++let Mode =+        missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ../Type.dhall++let Mask =+        missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall++let Access/equal =+        missing+          sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+      ? ../../Access/equal.dhall++let Access/toAccessWith =+        missing+          sha256:814ab74ad292c121620a1f468837d4a5473323423bf68c1bceca69e7b3c59077+      ? ../../Access/Mask/toAccessWith.dhall++let f+    : Access/Mask -> Access/Mask -> Optional Access+    = \(set : Access/Mask) ->+      \(m : Access/Mask) ->+        let x = Access/toAccessWith set m++        in  if    Access/equal+                    { execute = None Bool, read = None Bool, write = None Bool }+                    x+            then  None Access+            else  Some x++let toModeWith+    : Mask -> Mask -> Mode+    = \(set : Mask) ->+      \(m : Mask) ->+        { user = f set.user m.user+        , group = f set.group m.group+        , other = f set.other m.other+        }++let example0 =+      \(a : Mask) ->+        let none =+                missing+                  sha256:7cac21e2b72cadf3ee0bf10680df4902ca73b6ee070219df5eac1a24cd66ccdf+              ? ./none.dhall++        let Mode/none =+                missing+                  sha256:0ed46da7e6acbdff9e4c9e27a9f2770075a7cd6cb6bb565765c62093df1b5563+              ? ../none.dhall++        in  assert : toModeWith none a === Mode/none++let example1 =+      \(a : Mask) ->+        let toMode =+                missing+                  sha256:af2b0dab799374afa0a2f28551446760ff29f4697c200da0a8b0a8def7feee2a+              ? ./toMode.dhall++        let all =+                missing+                  sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+              ? ./all.dhall++        in  assert : toModeWith all a === toMode a++let example2 =+      let mask =+              missing+                sha256:94bf82678d8d1c4f370a96f3831d3ad4464fbee508ffb37e93a479a1d9ee25cf+            ? ./other.dhall++      let permissions =+              missing+                sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+            ? ./all.dhall++      let rwx = { read = Some True, write = Some True, execute = Some True }++      in    assert+          :     toModeWith mask permissions+            ===  { user = None Access, group = None Access, other = Some rwx }++let example3 =+      let union =+              missing+                sha256:3bb32fc6ea21f661571e46d90e450e0340b2f2b65482ba7bd1a30514e1b39fc2+            ? ./union.dhall++      let group =+              missing+                sha256:faa567630372f77bb5cd2fa4fe7cb4760d2f9f79e35df80917e6e0064decf7cf+            ? ./group.dhall++      let other =+              missing+                sha256:94bf82678d8d1c4f370a96f3831d3ad4464fbee508ffb37e93a479a1d9ee25cf+            ? ./other.dhall++      let permissions =+              missing+                sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+            ? ./all.dhall++      let mask = union group other++      let rwx = { read = Some True, write = Some True, execute = Some True }++      in    assert+          :     toModeWith mask permissions+            ===  { user = None Access, group = Some rwx, other = Some rwx }++in  toModeWith
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/union.dhall view
@@ -0,0 +1,24 @@+{-|+Calculates the union of the access rights set by both `Mask`s using+`Access/union`.+-}+let Mask =+        missing+          sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+      ? ./Type.dhall++let Access/union =+        missing+          sha256:b40c4cbb266991e3f764af075e9db544b59c16b3d9aa680c0cf6cb7552da191f+      ? ../../Access/Mask/union.dhall++let union+    : Mask -> Mask -> Mask+    = \(m1 : Mask) ->+      \(m2 : Mask) ->+        { user = Access/union m1.user m2.user+        , group = Access/union m1.group m2.group+        , other = Access/union m1.other m2.other+        }++in  union
+ dhall-lang/Prelude/DirectoryTree/Mode/Mask/user.dhall view
@@ -0,0 +1,14 @@+{-|+Permissions with all user flags set: rwx------+-}+let rwx =+        missing+          sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+      ? ../../Access/Mask/rwx.dhall++let none =+        missing+          sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+      ? ../../Access/Mask/none.dhall++in  { user = rwx, group = none, other = none }
+ dhall-lang/Prelude/DirectoryTree/Mode/Type.dhall view
@@ -0,0 +1,10 @@+{-|+An incomplete mode where some access rights might not be set explicitely. For a+complete mode with all access rights specified explicitely see `Mask`.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../Access/Type.dhall++in  { user : Optional Access, group : Optional Access, other : Optional Access }
+ dhall-lang/Prelude/DirectoryTree/Mode/equal.dhall view
@@ -0,0 +1,34 @@+{-|+`equal` checks if two `Mode`s are equal.+-}+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../Access/Type.dhall++let Mode =+        missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ./Type.dhall++let Access/equal =+        missing+          sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+      ? ../Access/equal.dhall++let Optional/equal =+        missing+          sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+      ? ../../Optional/equal.dhall++let f+    : Optional Access -> Optional Access -> Bool+    = Optional/equal Access Access/equal++let equal+    : Mode -> Mode -> Bool+    = \(m1 : Mode) ->+      \(m2 : Mode) ->+        f m1.user m2.user && f m1.group m2.group && f m1.other m2.other++in  equal
+ dhall-lang/Prelude/DirectoryTree/Mode/none.dhall view
@@ -0,0 +1,9 @@+let Access =+        missing+          sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+      ? ../Access/Type.dhall++in    { user = None Access, group = None Access, other = None Access }+    :   missing+          sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+      ? ./Type.dhall
+ dhall-lang/Prelude/DirectoryTree/Mode/package.dhall view
@@ -0,0 +1,17 @@+{ Mask =+      missing+        sha256:ce2c7ac1b81c2184b906cdd07c79936ba0eaf0445f1e383f53fd18d688ee7044+    ? ./Mask/package.dhall+, Type =+      missing+        sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+    ? ./Type.dhall+, equal =+      missing+        sha256:32fee2d3a56a2162d6c98fb63d47d31f98b352f22cc60c8b506011c9b5230e56+    ? ./equal.dhall+, schema =+      missing+        sha256:49f8eff9612d761c1bd424299b68317ad0f3ba325e4d22ec8acb550c2f1c0a40+    ? ./schema.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Mode/schema.dhall view
@@ -0,0 +1,12 @@+{-|+A schema for a blank file mode.+-}+{ Type =+      missing+        sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+    ? ./Type.dhall+, default =+      missing+        sha256:0ed46da7e6acbdff9e4c9e27a9f2770075a7cd6cb6bb565765c62093df1b5563+    ? ./none.dhall+}
+ dhall-lang/Prelude/DirectoryTree/Tree/Make.dhall view
@@ -0,0 +1,20 @@+let Directory =+        missing+          sha256:163a4536fdd05ce122d793ceda01d03fcffb29463817ae8b7b5601bf4a06ce6e+      ? ../Entry/DirectoryEntry.dhall++let BinaryFile =+        missing+          sha256:f027db2893f6f38bbe6d868a91f22de530e85407237f00b147427c87d32bf55c+      ? ../Entry/BinaryFileEntry.dhall++let TextFile =+        missing+          sha256:23a8cb29d96aeb623501519d9a62c5c49659e8d1c30b4ae4f2399809e3fd3a01+      ? ../Entry/TextFileEntry.dhall++in  \(tree : Type) ->+      { directory : Directory tree -> tree+      , binary-file : BinaryFile -> tree+      , file : TextFile -> tree+      }
+ dhall-lang/Prelude/DirectoryTree/Tree/Type.dhall view
@@ -0,0 +1,6 @@+let Make =+        missing+          sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+      ? ./Make.dhall++in  forall (tree : Type) -> forall (make : Make tree) -> List tree
+ dhall-lang/Prelude/DirectoryTree/Tree/makeTree.dhall view
@@ -0,0 +1,32 @@+{-|+@makeTree tree make parents x@ places the tree @x@ below the directory @parent@.+@parent@ is given as a list of 'Metadata' values where each of those will be+used to create the respective level of the directory tree.+-}+let Make =+        missing+          sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+      ? ./Make.dhall++let Metadata =+        missing+          sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+      ? ../Entry/Metadata.dhall++let makeTree+    : forall (tree : Type) -> Make tree -> List Metadata -> tree -> tree+    = \(tree : Type) ->+      \(make : Make tree) ->+      \(parents : List Metadata) ->+      \(leaf : tree) ->+        List/fold+          Metadata+          parents+          tree+          ( \(directory : Metadata) ->+            \(result : tree) ->+              make.directory (directory /\ { content = [ result ] })+          )+          leaf++in  makeTree
+ dhall-lang/Prelude/DirectoryTree/Tree/makeTreeFromList.dhall view
@@ -0,0 +1,42 @@+{-|+@makeTreeFromList tree make parents xs@ places the trees @xs@ below the+directory @parent@. @parent@ is given as a non-empty list of 'Metadata' values+where each of those will be used to create the respective level of the directory+tree.+-}+let Make =+        missing+          sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+      ? ./Make.dhall++let Metadata =+        missing+          sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+      ? ../Entry/Metadata.dhall++let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ../../NonEmpty/Type.dhall++let makeTreesFromList =+        missing+          sha256:02fce5b194da66c2f98bd05af0a3bfdccf0b57d7971f17bcafee436652d9a88e+      ? ./makeTreesFromList.dhall++let makeTreeFromList+    : forall (tree : Type) ->+      Make tree ->+      NonEmpty Metadata ->+      List tree ->+        tree+    = \(tree : Type) ->+      \(make : Make tree) ->+      \(parents : NonEmpty Metadata) ->+      \(leaves : List tree) ->+        make.directory+          (     parents.head+            /\  { content = makeTreesFromList tree make parents.tail leaves }+          )++in  makeTreeFromList
+ dhall-lang/Prelude/DirectoryTree/Tree/makeTreesFromList.dhall view
@@ -0,0 +1,36 @@+{-|+@makeTreesFromList tree make parents xs@ places the trees @xs@ below the+directory @parent@. @parent@ is given as a list of 'Metadata' values where each+of those will be used to create the respective level of the directory tree.+-}+let Make =+        missing+          sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+      ? ./Make.dhall++let Metadata =+        missing+          sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+      ? ../Entry/Metadata.dhall++let makeTreesFromList+    : forall (tree : Type) ->+      Make tree ->+      List Metadata ->+      List tree ->+        List tree+    = \(tree : Type) ->+      \(make : Make tree) ->+      \(parents : List Metadata) ->+      \(leaves : List tree) ->+        List/fold+          Metadata+          parents+          (List tree)+          ( \(directory : Metadata) ->+            \(content : List tree) ->+              [ make.directory (directory /\ { content }) ]+          )+          leaves++in  makeTreesFromList
+ dhall-lang/Prelude/DirectoryTree/Tree/package.dhall view
@@ -0,0 +1,21 @@+{ Make =+      missing+        sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+    ? ./Make.dhall+, Type =+      missing+        sha256:60b4d351213c6d851d7b2163ada40290b3c492a27326a2066fdec1a3915fb33b+    ? ./Type.dhall+, makeTree =+      missing+        sha256:2c1339fa63b4947864e1a6eede3c296288b53cf91a09d0d6881ae56790342e44+    ? ./makeTree.dhall+, makeTreeFromList =+      missing+        sha256:b894c9398e123d7262320684ac6301c2efe44d9d4f5a303b99d14e9be6b3150f+    ? ./makeTreeFromList.dhall+, makeTreesFromList =+      missing+        sha256:02fce5b194da66c2f98bd05af0a3bfdccf0b57d7971f17bcafee436652d9a88e+    ? ./makeTreesFromList.dhall+}
+ dhall-lang/Prelude/DirectoryTree/User/Type.dhall view
@@ -0,0 +1,1 @@+< UserId : Natural | UserName : Text >
+ dhall-lang/Prelude/DirectoryTree/User/id.dhall view
@@ -0,0 +1,6 @@+let User =+        missing+          sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+      ? ./Type.dhall++in  User.UserId
+ dhall-lang/Prelude/DirectoryTree/User/name.dhall view
@@ -0,0 +1,6 @@+let User =+        missing+          sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+      ? ./Type.dhall++in  User.UserName
+ dhall-lang/Prelude/DirectoryTree/User/package.dhall view
@@ -0,0 +1,13 @@+{ Type =+      missing+        sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+    ? ./Type.dhall+, id =+      missing+        sha256:b572ca9f08a04e8e472f1b6141fd71ff27cc7f22d1e72be50eba5f54798b5a6d+    ? ./id.dhall+, name =+      missing+        sha256:9cfd68599bbd626d3f32c9caa3f09b358ecc08659ef2540b24a4b17b49027015+    ? ./name.dhall+}
+ dhall-lang/Prelude/DirectoryTree/package.dhall view
@@ -0,0 +1,25 @@+{ Access =+      missing+        sha256:12f2ac90297a81c6e5a548bbf568fc7c93c906a6528432aa74faab6ec859de30+    ? ./Access/package.dhall+, Entry =+      missing+        sha256:795db8b6c2bc28fdff6fbcc832c5b4cb6931c1f62ffa84674280c24d4f2eacd8+    ? ./Entry/package.dhall+, Group =+      missing+        sha256:76a0d7e4606bdb91ab001b245cbd411939333b3fc3934ecbb5d41982d1ea001f+    ? ./Group/package.dhall+, Mode =+      missing+        sha256:6687ff7703fe9abdc4af9b3404af3d1c7d21a523d10a0c0b57d102a0bd87843f+    ? ./Mode/package.dhall+, Tree =+      missing+        sha256:6a64c27fa8a0c95830a4cc836651257235da0d985b7f93d11813cdb7a72e646b+    ? ./Tree/package.dhall+, User =+      missing+        sha256:eee7762ea4769371278907a4e33b3808d88430dda32dfc0536dc9bb2bb49d46a+    ? ./User/package.dhall+}
+ dhall-lang/Prelude/Double/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f+    ? ./show.dhall+}
+ dhall-lang/Prelude/Double/show view
@@ -0,0 +1,3 @@+  missing+    sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f+? ./show.dhall
+ dhall-lang/Prelude/Double/show.dhall view
@@ -0,0 +1,13 @@+{-|+Render a `Double` as `Text` using the same representation as Dhall source+code (i.e. a decimal floating point number with a leading `-` sign if negative)+-}+let show+    : Double → Text+    = Double/show++let example0 = assert : show -3.1 ≡ "-3.1"++let example1 = assert : show 0.4 ≡ "0.4"++in  show
+ dhall-lang/Prelude/Function/compose view
@@ -0,0 +1,3 @@+  missing+    sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+? ./compose.dhall
+ dhall-lang/Prelude/Function/compose.dhall view
@@ -0,0 +1,17 @@+--| Compose two functions into one.+let compose+    : ∀(a : Type) → ∀(b : Type) → ∀(c : Type) → (a → b) → (b → c) → a → c+    = λ(a : Type) →+      λ(b : Type) →+      λ(c : Type) →+      λ(f : a → b) →+      λ(g : b → c) →+      λ(x : a) →+        g (f x)++let example0 =+        assert+      :   compose Natural Natural Bool (λ(n : Natural) → n + n) Natural/even 3+        ≡ True++in  compose
+ dhall-lang/Prelude/Function/composeList.dhall view
@@ -0,0 +1,35 @@+{-|+Composes a list of functions starting from the left.+-}+let compose =+        missing+          sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+      ? ./compose.dhall++let identity =+        missing+          sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+      ? ./identity.dhall++let composeList+    : ∀(a : Type) → List (a → a) → a → a+    = λ(a : Type) →+      λ(functions : List (a → a)) →+        List/fold (a → a) functions (a → a) (compose a a a) (identity a)++let example0 =+        assert+      :   composeList+            Natural+            [ λ(x : Natural) → x * 2, λ(x : Natural) → x + 1 ]+            1+        ≡ 3++let property0 =+      λ(a : Type) →+      λ(f : a → a) →+      λ(g : a → a) →+      λ(h : a → a) →+        assert : composeList a [ f, g, h ] ≡ (λ(x : a) → h (g (f x)))++in  composeList
+ dhall-lang/Prelude/Function/identity view
@@ -0,0 +1,3 @@+  missing+    sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+? ./identity.dhall
+ dhall-lang/Prelude/Function/identity.dhall view
@@ -0,0 +1,10 @@+--| The identity function simply returns its input+let identity+    : ∀(a : Type) → ∀(x : a) → a+    = λ(a : Type) → λ(x : a) → x++let example0 = assert : identity Natural 1 ≡ 1++let example1 = assert : identity Bool ≡ (λ(x : Bool) → x)++in  identity
+ dhall-lang/Prelude/Function/package.dhall view
@@ -0,0 +1,13 @@+{ compose =+      missing+        sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+    ? ./compose.dhall+, composeList =+      missing+        sha256:2c6931544d8b5a5b14514098c07bd1813f67b16834588d056df3c0bc2e489937+    ? ./composeList.dhall+, identity =+      missing+        sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+    ? ./identity.dhall+}
+ dhall-lang/Prelude/Integer/abs view
@@ -0,0 +1,3 @@+  missing+    sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+? ./abs.dhall
+ dhall-lang/Prelude/Integer/abs.dhall view
@@ -0,0 +1,15 @@+--| Returns the absolute value of an `Integer`, i.e. its non-negative value.+let abs+    : Integer → Natural+    = λ(n : Integer) →+        if    Natural/isZero (Integer/clamp n)+        then  Integer/clamp (Integer/negate n)+        else  Integer/clamp n++let example0 = assert : abs +7 ≡ 7++let example2 = assert : abs +0 ≡ 0++let example3 = assert : abs -3 ≡ 3++in  abs
+ dhall-lang/Prelude/Integer/add view
@@ -0,0 +1,3 @@+  missing+    sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+? ./add.dhall
+ dhall-lang/Prelude/Integer/add.dhall view
@@ -0,0 +1,25 @@+--| `add m n` computes `m + n`.+let Integer/subtract =+        missing+          sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+      ? ./subtract.dhall++let add+    : Integer → Integer → Integer+    = λ(m : Integer) → λ(n : Integer) → Integer/subtract (Integer/negate m) n++let example0 = assert : add +3 +5 ≡ +8++let example1 = assert : add -3 -5 ≡ -8++let example2 = assert : add -4 +4 ≡ +0++let example3 = assert : add -3 +5 ≡ +2++let example4 = assert : add +3 -5 ≡ -2++let example5 = assert : add +0 -3 ≡ -3++let example6 = assert : add +0 +3 ≡ +3++in  add
+ dhall-lang/Prelude/Integer/clamp view
@@ -0,0 +1,3 @@+  missing+    sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+? ./clamp.dhall
+ dhall-lang/Prelude/Integer/clamp.dhall view
@@ -0,0 +1,14 @@+{-|+Convert an `Integer` to a `Natural` number, with negative numbers becoming zero.+-}+let clamp+    : Integer → Natural+    = Integer/clamp++let example0 = assert : clamp +7 ≡ 7++let example2 = assert : clamp +0 ≡ 0++let example3 = assert : clamp -3 ≡ 0++in  clamp
+ dhall-lang/Prelude/Integer/equal view
@@ -0,0 +1,3 @@+  missing+    sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+? ./equal.dhall
+ dhall-lang/Prelude/Integer/equal.dhall view
@@ -0,0 +1,24 @@+--| `equal` checks if two Integers are equal.+let Natural/equal =+        missing+          sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+      ? ../Natural/equal.dhall++let equal+    : Integer → Integer → Bool+    = λ(a : Integer) →+      λ(b : Integer) →+            Natural/equal (Integer/clamp a) (Integer/clamp b)+        &&  Natural/equal+              (Integer/clamp (Integer/negate a))+              (Integer/clamp (Integer/negate b))++let example0 = assert : equal +5 +5 ≡ True++let example1 = assert : equal +5 +6 ≡ False++let example2 = assert : equal +5 -5 ≡ False++let example3 = assert : equal -5 -5 ≡ True++in  equal
+ dhall-lang/Prelude/Integer/greaterThan view
@@ -0,0 +1,3 @@+  missing+    sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+? ./greaterThan.dhall
+ dhall-lang/Prelude/Integer/greaterThan.dhall view
@@ -0,0 +1,30 @@+--| `greaterThan` checks if one Integer is greater than another.+let Bool/not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let lessThanEqual =+        missing+          sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+      ? ./lessThanEqual.dhall++let greaterThan+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → Bool/not (lessThanEqual x y)++let example0 = assert : greaterThan +5 +6 ≡ False++let example1 = assert : greaterThan +5 +5 ≡ False++let example2 = assert : greaterThan +5 +4 ≡ True++let example3 = assert : greaterThan -5 +8 ≡ False++let example4 = assert : greaterThan -5 -3 ≡ False++let example5 = assert : greaterThan -3 -5 ≡ True++let example6 = assert : greaterThan -3 -3 ≡ False++in  greaterThan
+ dhall-lang/Prelude/Integer/greaterThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+? ./greaterThanEqual.dhall
+ dhall-lang/Prelude/Integer/greaterThanEqual.dhall view
@@ -0,0 +1,27 @@+{-|+`greaterThanEqual` checks if one Integer is greater than or equal to another.+-}+let lessThanEqual =+        missing+          sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+      ? ./lessThanEqual.dhall++let greaterThanEqual+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → lessThanEqual y x++let example0 = assert : greaterThanEqual +5 +6 ≡ False++let example1 = assert : greaterThanEqual +5 +5 ≡ True++let example2 = assert : greaterThanEqual +5 +4 ≡ True++let example3 = assert : greaterThanEqual -5 +8 ≡ False++let example4 = assert : greaterThanEqual -5 -3 ≡ False++let example5 = assert : greaterThanEqual -3 -5 ≡ True++let example6 = assert : greaterThanEqual -3 -3 ≡ True++in  greaterThanEqual
+ dhall-lang/Prelude/Integer/lessThan view
@@ -0,0 +1,3 @@+  missing+    sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+? ./lessThan.dhall
+ dhall-lang/Prelude/Integer/lessThan.dhall view
@@ -0,0 +1,25 @@+--| `lessThan` checks if one Integer is less than another.+let greaterThan =+        missing+          sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+      ? ./greaterThan.dhall++let lessThan+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → greaterThan y x++let example0 = assert : lessThan +5 +6 ≡ True++let example1 = assert : lessThan +5 +5 ≡ False++let example2 = assert : lessThan +5 +4 ≡ False++let example3 = assert : lessThan -5 +8 ≡ True++let example4 = assert : lessThan -5 -3 ≡ True++let example5 = assert : lessThan -3 -5 ≡ False++let example6 = assert : lessThan -3 -3 ≡ False++in  lessThan
+ dhall-lang/Prelude/Integer/lessThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+? ./lessThanEqual.dhall
+ dhall-lang/Prelude/Integer/lessThanEqual.dhall view
@@ -0,0 +1,47 @@+--| `lessThanEqual` checks if one Integer is less than or equal to another.+let Natural/greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ../Natural/greaterThanEqual.dhall++let Natural/lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ../Natural/lessThanEqual.dhall++let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ./nonNegative.dhall++let lessThanEqual+    : Integer → Integer → Bool+    = λ(x : Integer) →+      λ(y : Integer) →+        if    nonPositive x+        then      nonNegative y+              ||  Natural/greaterThanEqual+                    (Integer/clamp (Integer/negate x))+                    (Integer/clamp (Integer/negate y))+        else  Natural/lessThanEqual (Integer/clamp x) (Integer/clamp y)++let example0 = assert : lessThanEqual +5 +6 ≡ True++let example1 = assert : lessThanEqual +5 +5 ≡ True++let example2 = assert : lessThanEqual +5 +4 ≡ False++let example3 = assert : lessThanEqual -5 +8 ≡ True++let example4 = assert : lessThanEqual -5 -3 ≡ True++let example5 = assert : lessThanEqual -3 -5 ≡ False++let example6 = assert : lessThanEqual -3 -3 ≡ True++in  lessThanEqual
+ dhall-lang/Prelude/Integer/multiply view
@@ -0,0 +1,3 @@+  missing+    sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+? ./multiply.dhall
+ dhall-lang/Prelude/Integer/multiply.dhall view
@@ -0,0 +1,40 @@+--| `multiply m n` computes `m * n`.+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let multiplyNonNegative =+      λ(x : Integer) →+      λ(y : Integer) →+        Natural/toInteger (Integer/clamp x * Integer/clamp y)++let multiply+    : Integer → Integer → Integer+    = λ(m : Integer) →+      λ(n : Integer) →+        if    nonPositive m+        then  if    nonPositive n+              then  multiplyNonNegative (Integer/negate m) (Integer/negate n)+              else  Integer/negate (multiplyNonNegative (Integer/negate m) n)+        else  if nonPositive n+        then  Integer/negate (multiplyNonNegative m (Integer/negate n))+        else  multiplyNonNegative m n++let example0 = assert : multiply +3 +5 ≡ +15++let example1 = assert : multiply -3 +5 ≡ -15++let example2 = assert : multiply -3 -5 ≡ +15++let example3 = assert : multiply +0 +5 ≡ +0++let example4 = assert : multiply +5 +0 ≡ +0++let example5 = assert : multiply +0 +0 ≡ +0++let example6 = assert : multiply +1 +5 ≡ +5++let example7 = assert : multiply +3 -1 ≡ -3++in  multiply
+ dhall-lang/Prelude/Integer/negate view
@@ -0,0 +1,3 @@+  missing+    sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+? ./negate.dhall
+ dhall-lang/Prelude/Integer/negate.dhall view
@@ -0,0 +1,12 @@+--| Invert the sign of an `Integer`, with zero remaining unchanged.+let negate+    : Integer → Integer+    = Integer/negate++let example0 = assert : negate -3 ≡ +3++let example2 = assert : negate +7 ≡ -7++let example3 = assert : negate +0 ≡ +0++in  negate
+ dhall-lang/Prelude/Integer/negative view
@@ -0,0 +1,3 @@+  missing+    sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+? ./negative.dhall
+ dhall-lang/Prelude/Integer/negative.dhall view
@@ -0,0 +1,21 @@+{-|+Returns `True` for any `Integer` less than `+0`.++`negative` is more efficient than `./lessThan +0` or `./lessThanEqual -1`.+-}+let positive =+        missing+          sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+      ? ./positive.dhall++let negative+    : Integer → Bool+    = λ(n : Integer) → positive (Integer/negate n)++let example0 = assert : negative +1 ≡ False++let example1 = assert : negative +0 ≡ False++let example2 = assert : negative -1 ≡ True++in  negative
+ dhall-lang/Prelude/Integer/nonNegative view
@@ -0,0 +1,3 @@+  missing+    sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+? ./nonNegative.dhall
+ dhall-lang/Prelude/Integer/nonNegative.dhall view
@@ -0,0 +1,21 @@+{-|+Returns `True` for `+0` and any positive `Integer`.++`nonNegative` is more efficient than `./greaterThanEqual +0` or `./greaterThan -1`.+-}+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let nonNegative+    : Integer → Bool+    = λ(n : Integer) → nonPositive (Integer/negate n)++let example0 = assert : nonNegative +1 ≡ True++let example1 = assert : nonNegative +0 ≡ True++let example2 = assert : nonNegative -1 ≡ False++in  nonNegative
+ dhall-lang/Prelude/Integer/nonPositive view
@@ -0,0 +1,3 @@+  missing+    sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+? ./nonPositive.dhall
+ dhall-lang/Prelude/Integer/nonPositive.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `True` for `+0` and any negative `Integer`.++`nonPositive` is more efficient than `./lessThanEqual +0` or `./lessThan +1`.+-}+let nonPositive+    : Integer → Bool+    = λ(n : Integer) → Natural/isZero (Integer/clamp n)++let example0 = assert : nonPositive +1 ≡ False++let example1 = assert : nonPositive +0 ≡ True++let example2 = assert : nonPositive -1 ≡ True++in  nonPositive
+ dhall-lang/Prelude/Integer/package.dhall view
@@ -0,0 +1,73 @@+{ abs =+      missing+        sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+    ? ./abs.dhall+, add =+      missing+        sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+    ? ./add.dhall+, clamp =+      missing+        sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+    ? ./clamp.dhall+, equal =+      missing+        sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+    ? ./equal.dhall+, greaterThan =+      missing+        sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+    ? ./greaterThan.dhall+, greaterThanEqual =+      missing+        sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+    ? ./greaterThanEqual.dhall+, lessThan =+      missing+        sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+    ? ./lessThan.dhall+, lessThanEqual =+      missing+        sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+    ? ./lessThanEqual.dhall+, multiply =+      missing+        sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+    ? ./multiply.dhall+, negate =+      missing+        sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+    ? ./negate.dhall+, negative =+      missing+        sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+    ? ./negative.dhall+, nonNegative =+      missing+        sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+    ? ./nonNegative.dhall+, nonPositive =+      missing+        sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+    ? ./nonPositive.dhall+, positive =+      missing+        sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+    ? ./positive.dhall+, show =+      missing+        sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+    ? ./show.dhall+, subtract =+      missing+        sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+    ? ./subtract.dhall+, toDouble =+      missing+        sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+    ? ./toDouble.dhall+, toNatural =+      missing+        sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+    ? ./toNatural.dhall+}
+ dhall-lang/Prelude/Integer/positive view
@@ -0,0 +1,3 @@+  missing+    sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+? ./positive.dhall
+ dhall-lang/Prelude/Integer/positive.dhall view
@@ -0,0 +1,26 @@+{-|+Returns `True` for any `Integer` greater than `+0`.++`positive` is more efficient than `./greaterThan +0` or `./greaterThanEqual +1`.+-}+let not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let positive+    : Integer → Bool+    = λ(n : Integer) → not (nonPositive n)++let example0 = assert : positive +1 ≡ True++let example1 = assert : positive +0 ≡ False++let example2 = assert : positive -1 ≡ False++in  positive
+ dhall-lang/Prelude/Integer/show view
@@ -0,0 +1,3 @@+  missing+    sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+? ./show.dhall
+ dhall-lang/Prelude/Integer/show.dhall view
@@ -0,0 +1,14 @@+{-|+Render an `Integer` as `Text` using the same representation as Dhall source+code (i.e. a decimal number with a leading `-` sign if negative and a leading+`+` sign if non-negative)+-}+let show+    : Integer → Text+    = Integer/show++let example0 = assert : show -3 ≡ "-3"++let example1 = assert : show +0 ≡ "+0"++in  show
+ dhall-lang/Prelude/Integer/subtract view
@@ -0,0 +1,3 @@+  missing+    sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+? ./subtract.dhall
+ dhall-lang/Prelude/Integer/subtract.dhall view
@@ -0,0 +1,54 @@+--| `subtract m n` computes `n - m`.+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let subtractNonNegative =+      λ(xi : Integer) →+      λ(yi : Integer) →+        let xn = Integer/clamp xi++        let yn = Integer/clamp yi++        let dn = Natural/subtract xn yn++        in  if    Natural/isZero dn+            then  Integer/negate (Natural/toInteger (Natural/subtract yn xn))+            else  Natural/toInteger dn++let subtract+    : Integer → Integer → Integer+    = λ(m : Integer) →+      λ(n : Integer) →+        if    nonPositive m+        then  if    nonPositive n+              then  subtractNonNegative (Integer/negate n) (Integer/negate m)+              else  Natural/toInteger+                      (Integer/clamp (Integer/negate m) + Integer/clamp n)+        else  if nonPositive n+        then  Integer/negate+                ( Natural/toInteger+                    (Integer/clamp m + Integer/clamp (Integer/negate n))+                )+        else  subtractNonNegative m n++let example0 = assert : subtract +3 +5 ≡ +2++let example1 = assert : subtract +4 +4 ≡ +0++let example2 = assert : subtract +5 +3 ≡ -2++let example3 = assert : subtract -3 -5 ≡ -2++let example4 = assert : subtract -4 -4 ≡ +0++let example5 = assert : subtract -5 -3 ≡ +2++let example6 = assert : subtract -3 +5 ≡ +8++let example7 = assert : subtract +3 -5 ≡ -8++let example8 = assert : subtract +0 -3 ≡ -3++in  subtract
+ dhall-lang/Prelude/Integer/toDouble view
@@ -0,0 +1,3 @@+  missing+    sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+? ./toDouble.dhall
+ dhall-lang/Prelude/Integer/toDouble.dhall view
@@ -0,0 +1,10 @@+--| Convert an `Integer` to the corresponding `Double`+let toDouble+    : Integer → Double+    = Integer/toDouble++let example0 = assert : toDouble -3 ≡ -3.0++let example1 = assert : toDouble +2 ≡ 2.0++in  toDouble
+ dhall-lang/Prelude/Integer/toNatural view
@@ -0,0 +1,3 @@+  missing+    sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+? ./toNatural.dhall
+ dhall-lang/Prelude/Integer/toNatural.dhall view
@@ -0,0 +1,20 @@+{-|+Convert an `Integer` to an `Optional Natural`, with negative numbers becoming `None Natural`.+-}+let nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ./nonNegative.dhall++let toNatural+    : Integer → Optional Natural+    = λ(n : Integer) →+        if nonNegative n then Some (Integer/clamp n) else None Natural++let example0 = assert : toNatural +7 ≡ Some 7++let example2 = assert : toNatural +0 ≡ Some 0++let example3 = assert : toNatural -3 ≡ None Natural++in  toNatural
+ dhall-lang/Prelude/JSON/Format view
@@ -0,0 +1,3 @@+  missing+    sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+? ./Format.dhall
+ dhall-lang/Prelude/JSON/Format.dhall view
@@ -0,0 +1,7 @@+{-|+An internal type used by `./renderAs` to select the output format.++You should not need to use this type directly, simply use `./render`+or `./renderYAML` as appropriate.+-}+< YAML | JSON >
+ dhall-lang/Prelude/JSON/Nesting view
@@ -0,0 +1,3 @@+  missing+    sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+? ./Nesting.dhall
+ dhall-lang/Prelude/JSON/Nesting.dhall view
@@ -0,0 +1,35 @@+{-|+This type is used as part of `dhall-json`'s support for preserving alternative+names++For example, this Dhall code:++```+let Example = < Left : { foo : Natural } | Right : { bar : Bool } >++let Nesting = < Inline | Nested : Text >++in  { field =+        "name"+    , nesting =+        Nesting.Inline+    , contents =+        Example.Left { foo = 2 }+    }+```++... generates this JSON:++```+{+  "foo": 2,+  "name": "Left"+}+```++-}+let Nesting+    : Type+    = < Inline | Nested : Text >++in  Nesting
+ dhall-lang/Prelude/JSON/Tagged view
@@ -0,0 +1,3 @@+  missing+    sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+? ./Tagged.dhall
+ dhall-lang/Prelude/JSON/Tagged.dhall view
@@ -0,0 +1,74 @@+{-|+This is a convenient type-level function when using `dhall-to-json`'s support+for preserving alternative names++For example, this code:++```+let map = ../List/map++let Provisioner =+      < shell :+          { inline : List Text }+      | file :+          { source : Text, destination : Text }+      >++let Tagged = ./Tagged++let Nesting = ./Nesting++let wrap+    : Provisioner → Tagged Provisioner+    = λ(x : Provisioner) →+        { field = "type", nesting = Nesting.Nested "params", contents = x }++in  { provisioners =+        map+        Provisioner+        (Tagged Provisioner)+        wrap+        [ Provisioner.shell { inline = [ "echo foo" ] }+        , Provisioner.file+          { source = "app.tar.gz", destination = "/tmp/app.tar.gz" }+        ]+    }+```++... produces this JSON:++```+{+  "provisioners": [+    {+      "params": {+        "inline": [+          "echo foo"+        ]+      },+      "type": "shell"+    },+    {+      "params": {+        "destination": "/tmp/app.tar.gz",+        "source": "app.tar.gz"+      },+      "type": "file"+    }+  ]+}+```++-}+let Tagged+    : Type → Type+    = λ(a : Type) →+        { field : Text+        , nesting :+              missing+                sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+            ? ./Nesting.dhall+        , contents : a+        }++in  Tagged
+ dhall-lang/Prelude/JSON/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+? ./Type.dhall
+ dhall-lang/Prelude/JSON/Type.dhall view
@@ -0,0 +1,63 @@+{-|+Dhall encoding of an arbitrary JSON value++For example, the following JSON value:++```+[ { "foo": null, "bar": [ 1.0, true ] } ]+```++... corresponds to the following Dhall expression:++```+λ(JSON : Type) →+λ ( json+  : { array : List JSON → JSON+    , bool : Bool → JSON+    , null : JSON+    , double : Double → JSON+    , integer : Integer → JSON+    , object : List { mapKey : Text, mapValue : JSON } → JSON+    , string : Text → JSON+    }+  ) →+  json.object+    [ { mapKey = "foo", mapValue = json.null }+    , { mapKey = "bar"+      , mapValue = json.array [ json.double 1.0, json.bool True ]+      }+    ]+```++  You do not need to create these values directly, though.  You can use+  the utilities exported by `./package.dhall` to create values of this type,+  such as:++```+let JSON = ./package.dhall++in  JSON.object+      [ { mapKey = "foo", mapValue = JSON.null }+      , { mapKey = "bar"+        , mapValue = JSON.array [ JSON.double 1.0, JSON.bool True ]+        }+      ]+```++-}+let JSON/Type+    : Type+    = ∀(JSON : Type) →+      ∀ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        JSON++in  JSON/Type
+ dhall-lang/Prelude/JSON/array view
@@ -0,0 +1,3 @@+  missing+    sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+? ./array.dhall
+ dhall-lang/Prelude/JSON/array.dhall view
@@ -0,0 +1,41 @@+{-|+Create a JSON array from a `List` of JSON values++```+let JSON = ./package.dhall+in  JSON.render (JSON.array [ JSON.double 1.0, JSON.bool True ])+= "[ 1.0, true ]"++let JSON/Type = ./Type+let JSON = ./package.dhall+in  JSON.render (JSON.array ([] : List JSON/Type))+= "[ ]"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let array+    : List JSON → JSON+    = λ(x : List JSON) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.array (List/map JSON@1 JSON (λ(j : JSON@1) → j JSON json) x)++in  array
+ dhall-lang/Prelude/JSON/bool view
@@ -0,0 +1,3 @@+  missing+    sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+? ./bool.dhall
+ dhall-lang/Prelude/JSON/bool.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON bool from a Dhall `Bool`++```+let JSON = ./package.dhall+in  JSON.render (JSON.bool True)+= "true"++let JSON = ./package.dhall+in  JSON.render (JSON.bool False)+= "false"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let bool+    : Bool → JSON+    = λ(x : Bool) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.bool x++in  bool
+ dhall-lang/Prelude/JSON/core.dhall view
@@ -0,0 +1,70 @@+{-|+A record of functions useful for constructing `JSON` values.++This is only a subset of what `package.dhall` exports. If you are not writing a+JSON prelude function, you should use the `package.dhall` file instead.++It is used internally by `render`, `renderYAML` and `omitNullFields` instead of+`package.dhall` to avoid import cycles.+-}+{ Type =+      missing+        sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+    ? ./Type.dhall+, Tagged =+      missing+        sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+    ? ./Tagged.dhall+, Nesting =+      missing+        sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+    ? ./Nesting.dhall+, keyText =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./keyText.dhall+, keyValue =+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+    ? ./keyValue.dhall+, string =+      missing+        sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+    ? ./string.dhall+, number =+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./number.dhall+, double =+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./double.dhall+, integer =+      missing+        sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+    ? ./integer.dhall+, natural =+      missing+        sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+    ? ./natural.dhall+, object =+      missing+        sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+    ? ./object.dhall+, array =+      missing+        sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+    ? ./array.dhall+, bool =+      missing+        sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+    ? ./bool.dhall+, null =+      missing+        sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+    ? ./null.dhall+, renderInteger =+      missing+        sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+    ? ./renderInteger.dhall+}
+ dhall-lang/Prelude/JSON/double view
@@ -0,0 +1,3 @@+  missing+    sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+? ./double.dhall
+ dhall-lang/Prelude/JSON/double.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON number from a Dhall `Double`++```+let JSON = ./package.dhall+in  JSON.render (JSON.double 42.0)+= "42.0"++let JSON = ./package.dhall+in  JSON.render (JSON.double -1.5e-10)+= "-1.5e-10"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let double+    : Double → JSON+    = λ(x : Double) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.double x++in  double
+ dhall-lang/Prelude/JSON/integer view
@@ -0,0 +1,3 @@+  missing+    sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+? ./integer.dhall
+ dhall-lang/Prelude/JSON/integer.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON number from a Dhall `Integer`++```+let JSON = ./package.dhall+in  JSON.render (JSON.integer -1)+= "-1"++let JSON = ./package.dhall+in  JSON.render (JSON.integer +2)+= "+2"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let integer+    : Integer → JSON+    = λ(x : Integer) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.integer x++in  integer
+ dhall-lang/Prelude/JSON/keyText view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ./keyText.dhall
+ dhall-lang/Prelude/JSON/keyText.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ../Map/keyText.dhall
+ dhall-lang/Prelude/JSON/keyValue view
@@ -0,0 +1,3 @@+  missing+    sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+? ./keyValue.dhall
+ dhall-lang/Prelude/JSON/keyValue.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+? ../Map/keyValue.dhall
+ dhall-lang/Prelude/JSON/natural view
@@ -0,0 +1,3 @@+  missing+    sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+? ./natural.dhall
+ dhall-lang/Prelude/JSON/natural.dhall view
@@ -0,0 +1,31 @@+{-|+Create a JSON number from a Dhall `Natural`++```+let JSON = ./package.dhall+in  JSON.render (JSON.natural 42)+= "42"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let natural+    : Natural → JSON+    = λ(x : Natural) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.integer (Natural/toInteger x)++in  natural
+ dhall-lang/Prelude/JSON/null view
@@ -0,0 +1,3 @@+  missing+    sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+? ./null.dhall
+ dhall-lang/Prelude/JSON/null.dhall view
@@ -0,0 +1,30 @@+{-|+Create a JSON null++```+let JSON = ./package.dhall+in  JSON.render JSON.null+= "null"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let null+    : JSON+    = λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.null++in  null
+ dhall-lang/Prelude/JSON/number view
@@ -0,0 +1,3 @@+  missing+    sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+? ./number.dhall
+ dhall-lang/Prelude/JSON/number.dhall view
@@ -0,0 +1,28 @@+{-|+Create a JSON number from a Dhall `Double`++```+let JSON = ./package.dhall+in  JSON.render (JSON.number 42.0)+= "42.0"++let JSON = ./package.dhall+in  JSON.render (JSON.number -1.5e-10)+= "-1.5e-10"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let double =+        missing+          sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+      ? ./double.dhall++let number+    : Double → JSON+    = double++in  number
+ dhall-lang/Prelude/JSON/object view
@@ -0,0 +1,3 @@+  missing+    sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+? ./object.dhall
+ dhall-lang/Prelude/JSON/object.dhall view
@@ -0,0 +1,55 @@+{-|+Create a JSON object from a Dhall `Map`++```+let JSON = ./package.dhall+in  JSON.render+    ( JSON.object+      [ { mapKey = "foo", mapValue = JSON.double 1.0 }+      , { mapKey = "bar", mapValue = JSON.bool True  }+      ]+    )+= "{ \"foo\": 1.0, \"bar\": true }"++let JSON/Type = ./Type+let JSON = ./package.dhall+in  JSON.render+    (JSON.object ([] : List { mapKey : Text, mapValue : JSON/Type }))+= "{ }"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let object+    : List { mapKey : Text, mapValue : JSON } → JSON+    = λ(x : List { mapKey : Text, mapValue : JSON }) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.object+          ( List/map+              { mapKey : Text, mapValue : JSON@1 }+              { mapKey : Text, mapValue : JSON }+              ( λ(kv : { mapKey : Text, mapValue : JSON@1 }) →+                  { mapKey = kv.mapKey, mapValue = kv.mapValue JSON json }+              )+              x+          )++in  object
+ dhall-lang/Prelude/JSON/omitNullFields view
@@ -0,0 +1,3 @@+  missing+    sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+? ./omitNullFields.dhall
+ dhall-lang/Prelude/JSON/omitNullFields.dhall view
@@ -0,0 +1,145 @@+{-|+This utility omits all `null` record fields, which is often the idiomatic way+for a configuration to encode absent fields+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let omitNullFields+    : JSON.Type → JSON.Type+    = λ(old : JSON.Type) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        let result =+              old+                { value : JSON, isNull : Bool }+                { string =+                    λ(x : Text) → { value = json.string x, isNull = False }+                , double =+                    λ(x : Double) → { value = json.double x, isNull = False }+                , integer =+                    λ(x : Integer) → { value = json.integer x, isNull = False }+                , object =+                    λ ( keyValues+                      : List+                          { mapKey : Text+                          , mapValue : { value : JSON, isNull : Bool }+                          }+                      ) →+                      let value =+                            json.object+                              ( List/concatMap+                                  { mapKey : Text+                                  , mapValue : { value : JSON, isNull : Bool }+                                  }+                                  { mapKey : Text, mapValue : JSON }+                                  ( λ ( keyValue+                                      : { mapKey : Text+                                        , mapValue :+                                            { value : JSON, isNull : Bool }+                                        }+                                      ) →+                                      if    keyValue.mapValue.isNull+                                      then  [] : List+                                                   { mapKey : Text+                                                   , mapValue : JSON+                                                   }+                                      else  [   keyValue.{ mapKey }+                                              ∧ { mapValue =+                                                    keyValue.mapValue.value+                                                }+                                            ]+                                  )+                                  keyValues+                              )++                      in  { value, isNull = False }+                , array =+                    λ(xs : List { value : JSON, isNull : Bool }) →+                      let value =+                            json.array+                              ( List/map+                                  { value : JSON, isNull : Bool }+                                  JSON+                                  ( λ(x : { value : JSON, isNull : Bool }) →+                                      x.value+                                  )+                                  xs+                              )++                      in  { value, isNull = False }+                , bool = λ(x : Bool) → { value = json.bool x, isNull = False }+                , null = { value = json.null, isNull = True }+                }++        in  result.value++let property =+      λ(a : Text) →+      λ(b : Double) →+      λ(c : Bool) →+          assert+        :   omitNullFields+              ( JSON.object+                  ( toMap+                      { string = JSON.string a+                      , double = JSON.double b+                      , bool = JSON.bool c+                      , null = JSON.null+                      }+                  )+              )+          ≡ JSON.object+              ( toMap+                  { string = JSON.string a+                  , double = JSON.double b+                  , bool = JSON.bool c+                  }+              )++let example =+        assert+      :   omitNullFields+            ( JSON.object+                ( toMap+                    { array =+                        JSON.array [ JSON.object (toMap { null = JSON.null }) ]+                    }+                )+            )+        ≡ JSON.object+            ( toMap+                { array =+                    JSON.array+                      [ JSON.object+                          ([] : List { mapKey : Text, mapValue : JSON.Type })+                      ]+                }+            )++let example =+        assert+      : omitNullFields (JSON.array [ JSON.null ]) ≡ JSON.array [ JSON.null ]++in  omitNullFields
+ dhall-lang/Prelude/JSON/package.dhall view
@@ -0,0 +1,29 @@+  { render =+        missing+          sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836+      ? ./render.dhall+  , renderCompact =+        missing+          sha256:e6c8809fbe193fddd430f94350d69cefd45e7aaf8bd379e51b750fde75008562+      ? ./renderCompact.dhall+  , renderYAML =+        missing+          sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478+      ? ./renderYAML.dhall+  , omitNullFields =+        missing+          sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+      ? ./omitNullFields.dhall+  , tagInline =+        missing+          sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+      ? ./tagInline.dhall+  , tagNested =+        missing+          sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+      ? ./tagNested.dhall+  }+∧ (   missing+        sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+    ? ./core.dhall+  )
+ dhall-lang/Prelude/JSON/render view
@@ -0,0 +1,3 @@+  missing+    sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836+? ./render.dhall
+ dhall-lang/Prelude/JSON/render.dhall view
@@ -0,0 +1,52 @@+{-|+Render a `JSON` value as `Text`++This is useful for debugging `JSON` values or for tests.  For anything+more sophisticated you should use `dhall-to-json` or `dhall-to-yaml`+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let renderAs =+        missing+          sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+      ? ./renderAs.dhall++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let render+    : JSON.Type → Text+    = renderAs Format.JSON++let example0 =+      let data =+              assert+            :   render+                  ( JSON.array+                      [ JSON.bool True+                      , JSON.string "Hello"+                      , JSON.object+                          [ { mapKey = "foo", mapValue = JSON.null }+                          , { mapKey = "bar", mapValue = JSON.double 1.0 }+                          ]+                      ]+                  )+              ≡ ''+                [+                  true,+                  "Hello",+                  {+                    "foo": null,+                    "bar": 1.0+                  }+                ]+                ''++      in  True++in  render
+ dhall-lang/Prelude/JSON/renderAs view
@@ -0,0 +1,3 @@+  missing+    sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+? ./renderAs.dhall
+ dhall-lang/Prelude/JSON/renderAs.dhall view
@@ -0,0 +1,458 @@+--| Render a `JSON` value as `Text` in either JSON or YAML format.+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let Function/identity =+        missing+          sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+      ? ../Function/identity.dhall++let Text/concatMap =+        missing+          sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+      ? ../Text/concatMap.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ../NonEmpty/Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ../NonEmpty/toList.dhall++let NonEmpty/concat =+        missing+          sha256:6d55181938c06c6b806877028f6a241912e9c0935d9a10dd958775bf21e0f64d+      ? ../NonEmpty/concat.dhall++let NonEmpty/map =+        missing+          sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+      ? ../NonEmpty/map.dhall++let NonEmpty/singleton =+        missing+          sha256:c9197aabe97695f7ca66f7419bf172d806b2c915594a8fc0d2ff6495db496ff2+      ? ../NonEmpty/singleton.dhall++let List/uncons+    : ∀(a : Type) → List a → Optional (NonEmpty a)+    = {- This version uses the `ls` argument only once to prevent cache blowups at the price+         of performing two passes over the list:+         A first one to reverse it, a second one with `List/fold` to determine+         the head element.+         See https://github.com/dhall-lang/dhall-lang/pull/1015#issuecomment-633381024+         for some context regarding the caching issue.+      -}+      λ(a : Type) →+      λ(ls : List a) →+        List/fold+          a+          (List/reverse a ls)+          (Optional (NonEmpty a))+          ( λ(x : a) →+            λ(acc : Optional (NonEmpty a)) →+              merge+                { None = Some (NonEmpty/singleton a x)+                , Some =+                    λ(ne : NonEmpty a) → Some (ne ⫽ { tail = ne.tail # [ x ] })+                }+                acc+          )+          (None (NonEmpty a))++let NonEmpty/mapHead+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        ls ⫽ { head = fn ls.head }++let NonEmpty/mapTail+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        ls ⫽ { tail = List/map a a fn ls.tail }++let NonEmpty/prepend+    : ∀(a : Type) → a → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(prefix : a) →+      λ(ls : NonEmpty a) →+        { head = prefix, tail = NonEmpty/toList a ls }++let NonYtpme+    : Type → Type+    = λ(a : Type) → { init : List a, last : a }++let List/unsnoc+    : ∀(a : Type) → List a → Optional (NonYtpme a)+    = λ(a : Type) →+      λ(ls : List a) →+        List/fold+          a+          ls+          (Optional (NonYtpme a))+          ( λ(x : a) →+            λ(acc : Optional (NonYtpme a)) →+              merge+                { None = Some { init = [] : List a, last = x }+                , Some =+                    λ(ny : NonYtpme a) → Some (ny ⫽ { init = [ x ] # ny.init })+                }+                acc+          )+          (None (NonYtpme a))++let NonEmpty/mapLast+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        merge+          { Some = λ(x : NonYtpme a) → ls ⫽ { tail = x.init # [ fn x.last ] }+          , None = NonEmpty/singleton a (fn ls.head)+          }+          (List/unsnoc a ls.tail)++let NonEmpty/mapLeading+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        merge+          { Some =+              λ(x : NonYtpme a) →+                { head = fn ls.head+                , tail = List/map a a fn x.init # [ x.last ]+                }+          , None = ls+          }+          (List/unsnoc a ls.tail)++let Lines+    : Type+    = NonEmpty Text++let Block+    : Type+    = < Simple : Text | Complex : Lines >++let Block/toLines+    : Block → Lines+    = λ(block : Block) →+        merge+          { Simple = NonEmpty/singleton Text+          , Complex = Function/identity Lines+          }+          block++let manyBlocks+    : ∀(a : Type) → Text → (NonEmpty a → Lines) → List a → Block+    = λ(a : Type) →+      λ(ifEmpty : Text) →+      λ(render : NonEmpty a → Lines) →+      λ(inputs : List a) →+        merge+          { Some = λ(inputs : NonEmpty a) → Block.Complex (render inputs)+          , None = Block.Simple ifEmpty+          }+          (List/uncons a inputs)++let blockToText+    : Block → Text+    = λ(block : Block) →+        Text/concatMap+          Text+          (λ(line : Text) → line ++ "\n")+          (NonEmpty/toList Text (Block/toLines block))++let addPrefix = λ(prefix : Text) → λ(line : Text) → prefix ++ line++let addIndent = addPrefix "  "++let indentTail = NonEmpty/mapTail Text addIndent++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let ObjectField = { mapKey : Text, mapValue : Block }++let -- Essentially the same thing as `Text/show`, except that this does not+    -- escape `$`+    escape =+      List/fold+        (Text → Text)+        [ Text/replace "\"" "\\\""+        , Text/replace "\b" "\\b"+        , Text/replace "\f" "\\f"+        , Text/replace "\n" "\\n"+        , Text/replace "\r" "\\r"+        , Text/replace "\t" "\\t"+        , Text/replace "\\" "\\\\"+        ]+        Text+        (λ(replace : Text → Text) → λ(text : Text) → replace text)++let renderJSONStruct =+      λ(prefix : Text) →+      λ(suffix : Text) →+      λ(blocks : NonEmpty Lines) →+        let indent = List/map Text Text addIndent++        let appendComma+            : Lines → Lines+            = NonEmpty/mapLast Text (λ(line : Text) → line ++ ",")++        let blocks = NonEmpty/mapLeading Lines appendComma blocks++        let block = NonEmpty/concat Text blocks++        in  merge+              { None =+                  NonEmpty/singleton Text "${prefix} ${block.head} ${suffix}"+              , Some =+                  λ(ny : NonYtpme Text) →+                    { head = prefix+                    , tail =+                          indent ([ block.head ] # ny.init # [ ny.last ])+                        # [ suffix ]+                    }+              }+              (List/unsnoc Text block.tail)++let renderObject =+      λ(format : Format) →+      λ(fields : NonEmpty ObjectField) →+        let keystr = λ(field : ObjectField) → "\"${escape field.mapKey}\":"++        let prefixKeyOnFirst =+              λ(field : ObjectField) →+                NonEmpty/mapHead+                  Text+                  (addPrefix "${keystr field} ")+                  (Block/toLines field.mapValue)++        let prependKeyLine =+              λ(field : ObjectField) →+                NonEmpty/prepend+                  Text+                  (keystr field)+                  (Block/toLines field.mapValue)++        let renderYAMLField =+              λ(field : ObjectField) →+                merge+                  { Simple =+                      λ(line : Text) →+                        NonEmpty/singleton Text "${keystr field} ${line}"+                  , Complex = λ(_ : Lines) → indentTail (prependKeyLine field)+                  }+                  field.mapValue++        in  merge+              { JSON =+                  renderJSONStruct+                    "{"+                    "}"+                    (NonEmpty/map ObjectField Lines prefixKeyOnFirst fields)+              , YAML =+                  NonEmpty/concat+                    Text+                    (NonEmpty/map ObjectField Lines renderYAMLField fields)+              }+              format++let renderYAMLArrayField =+      λ(block : Block) →+        NonEmpty/mapHead+          Text+          (addPrefix "- ")+          (indentTail (Block/toLines block))++let renderArray =+      λ(format : Format) →+      λ(fields : NonEmpty Block) →+        merge+          { JSON =+              renderJSONStruct+                "["+                "]"+                (NonEmpty/map Block Lines Block/toLines fields)+          , YAML =+              NonEmpty/concat+                Text+                (NonEmpty/map Block Lines renderYAMLArrayField fields)+          }+          format++let renderAs+    : Format → JSON.Type → Text+    = λ(format : Format) →+      λ(json : JSON.Type) →+        blockToText+          ( json+              Block+              { string = λ(x : Text) → Block.Simple "\"${escape x}\""+              , double = λ(x : Double) → Block.Simple (Double/show x)+              , integer = λ(x : Integer) → Block.Simple (JSON.renderInteger x)+              , object = manyBlocks ObjectField "{}" (renderObject format)+              , array = manyBlocks Block "[]" (renderArray format)+              , bool =+                  λ(x : Bool) → Block.Simple (if x then "true" else "false")+              , null = Block.Simple "null"+              }+          )++let example0 =+      let data =+            JSON.array+              [ JSON.bool True+              , JSON.string "Hello"+              , JSON.object+                  [ { mapKey = "foo", mapValue = JSON.null }+                  , { mapKey = "bar", mapValue = JSON.double 1.0 }+                  ]+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                - true+                - "Hello"+                - "foo": null+                  "bar": 1.0+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                [+                  true,+                  "Hello",+                  {+                    "foo": null,+                    "bar": 1.0+                  }+                ]+                ''++      in  True++let example1 =+      let data =+            JSON.object+              [ { mapKey = "zero", mapValue = JSON.array ([] : List JSON.Type) }+              , { mapKey = "one", mapValue = JSON.array [ JSON.string "a" ] }+              , { mapKey = "two"+                , mapValue = JSON.array [ JSON.string "a", JSON.string "b" ]+                }+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                "zero": []+                "one":+                  - "a"+                "two":+                  - "a"+                  - "b"+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                {+                  "zero": [],+                  "one": [ "a" ],+                  "two": [+                    "a",+                    "b"+                  ]+                }+                ''++      in  True++let example2 =+      let data =+            JSON.object+              [ { mapKey = "zero"+                , mapValue =+                    JSON.object+                      (toMap {=} : List { mapKey : Text, mapValue : JSON.Type })+                }+              , { mapKey = "one"+                , mapValue = JSON.object (toMap { a = JSON.null })+                }+              , { mapKey = "two"+                , mapValue =+                    JSON.object (toMap { a = JSON.null, b = JSON.null })+                }+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                "zero": {}+                "one":+                  "a": null+                "two":+                  "a": null+                  "b": null+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                {+                  "zero": {},+                  "one": { "a": null },+                  "two": {+                    "a": null,+                    "b": null+                  }+                }+                ''++      in  True++let example3 =+      let specialCharacters =+            ''+            "\${"\b\f"}+            ${"\r"}	$''++      let data =+            JSON.object+              [ { mapKey = specialCharacters+                , mapValue = JSON.string specialCharacters+                }+              ]++      in    assert+          :   renderAs Format.JSON data+            ≡ ''+              { "\"\\\b\f\n\r\t$": "\"\\\b\f\n\r\t$" }+              ''++in  renderAs
+ dhall-lang/Prelude/JSON/renderCompact.dhall view
@@ -0,0 +1,61 @@+--| This renders JSON on a single line+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let Text/concatMapSep =+        missing+          sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+      ? ../Text/concatMapSep++let renderInteger =+        missing+          sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+      ? ./renderInteger.dhall++let renderCompact+    : JSON.Type → Text+    = λ(j : JSON.Type) →+        j+          Text+          { string = Text/show+          , double = Double/show+          , integer = renderInteger+          , object =+              λ(x : List { mapKey : Text, mapValue : Text }) →+                let body =+                      Text/concatMapSep+                        ","+                        { mapKey : Text, mapValue : Text }+                        ( λ(e : { mapKey : Text, mapValue : Text }) →+                            " ${Text/show e.mapKey}: ${e.mapValue}"+                        )+                        x++                in  "{${body} }"+          , array =+              λ(x : List Text) →+                let body = Text/concatMapSep "," Text (λ(y : Text) → " ${y}") x++                in  "[${body} ]"+          , bool = λ(x : Bool) → if x then "true" else "false"+          , null = "null"+          }++let example =+        assert+      :   renderCompact+            ( JSON.array+                [ JSON.bool True+                , JSON.string "Hello"+                , JSON.object+                    [ { mapKey = "foo", mapValue = JSON.null }+                    , { mapKey = "bar", mapValue = JSON.double 1.1 }+                    , { mapKey = "baz", mapValue = JSON.integer +2 }+                    ]+                ]+            )+        ≡ "[ true, \"Hello\", { \"foo\": null, \"bar\": 1.1, \"baz\": 2 } ]"++in  renderCompact
+ dhall-lang/Prelude/JSON/renderInteger.dhall view
@@ -0,0 +1,23 @@+{-|+Render an `Integer` value as a `JSON number`, according to the JSON standard, in+which a number may not start with a plus sign (`+`).+-}+let Integer/nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ../Integer/nonNegative.dhall++let renderInteger+    : Integer → Text+    = λ(integer : Integer) →+        if    Integer/nonNegative integer+        then  Natural/show (Integer/clamp integer)+        else  Integer/show integer++let positive = assert : renderInteger +1 ≡ "1"++let zero = assert : renderInteger +0 ≡ "0"++let negative = assert : renderInteger -1 ≡ "-1"++in  renderInteger
+ dhall-lang/Prelude/JSON/renderYAML view
@@ -0,0 +1,3 @@+  missing+    sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478+? ./renderYAML.dhall
+ dhall-lang/Prelude/JSON/renderYAML.dhall view
@@ -0,0 +1,49 @@+{-|+Render a `JSON` value as `Text` in YAML format.++The generated YAML text will only contain escaped object keys and+string values and might therefore not be very human readable.++However, it is useful for debugging `JSON` values or for tests.+For anything more sophisticated you should use `dhall-to-json` or+`dhall-to-yaml`.+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let renderAs =+        missing+          sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+      ? ./renderAs.dhall++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let renderYAML+    : JSON.Type → Text+    = renderAs Format.YAML++let example0 =+        assert+      :   renderYAML+            ( JSON.array+                [ JSON.bool True+                , JSON.string "Hello"+                , JSON.object+                    [ { mapKey = "foo", mapValue = JSON.null }+                    , { mapKey = "bar", mapValue = JSON.double 1.0 }+                    ]+                ]+            )+        ≡ ''+          - true+          - "Hello"+          - "foo": null+            "bar": 1.0+          ''++in  renderYAML
+ dhall-lang/Prelude/JSON/string view
@@ -0,0 +1,3 @@+  missing+    sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+? ./string.dhall
+ dhall-lang/Prelude/JSON/string.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON string from Dhall `Text`++```+let JSON = ./package.dhall+in  JSON.render (JSON.string "ABC $ \" 🙂")+= "\"ABC \\u0024 \\\" 🙂\""++let JSON = ./package.dhall+in  JSON.render (JSON.string "")+= "\"\""+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let string+    : Text → JSON+    = λ(x : Text) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.string x++in  string
+ dhall-lang/Prelude/JSON/tagInline view
@@ -0,0 +1,3 @@+  missing+    sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+? ./tagInline.dhall
+ dhall-lang/Prelude/JSON/tagInline.dhall view
@@ -0,0 +1,29 @@+--| Prepare a union value for JSON- or YAML-encoding with the inline layout+let Nesting =+        missing+          sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+      ? ./Nesting.dhall++let Tagged =+        missing+          sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+      ? ./Tagged.dhall++let tagInline+    : Text → ∀(a : Type) → a → Tagged a+    = λ(tagFieldName : Text) →+      λ(a : Type) →+      λ(contents : a) →+        { nesting = Nesting.Inline, field = tagFieldName, contents }++let example0 =+      let Example = < Left : { foo : Natural } | Right : { bar : Bool } >++      in    assert+          :   tagInline "name" Example (Example.Left { foo = 2 })+            ≡ { field = "name"+              , nesting = Nesting.Inline+              , contents = Example.Left { foo = 2 }+              }++in  tagInline
+ dhall-lang/Prelude/JSON/tagNested view
@@ -0,0 +1,3 @@+  missing+    sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+? ./tagNested.dhall
+ dhall-lang/Prelude/JSON/tagNested.dhall view
@@ -0,0 +1,33 @@+--| Prepare a union value for JSON- or YAML-encoding with the nested layout+let Nesting =+        missing+          sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+      ? ./Nesting.dhall++let Tagged =+        missing+          sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+      ? ./Tagged.dhall++let tagNested+    : Text → Text → ∀(a : Type) → a → Tagged a+    = λ(contentsFieldName : Text) →+      λ(tagFieldName : Text) →+      λ(a : Type) →+      λ(contents : a) →+        { nesting = Nesting.Nested contentsFieldName+        , field = tagFieldName+        , contents+        }++let example0 =+      let Example = < Left : { foo : Natural } | Right : { bar : Bool } >++      in    assert+          :   tagNested "value" "name" Example (Example.Left { foo = 2 })+            ≡ { field = "name"+              , nesting = Nesting.Nested "value"+              , contents = Example.Left { foo = 2 }+              }++in  tagNested
+ dhall-lang/Prelude/List/all view
@@ -0,0 +1,3 @@+  missing+    sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15+? ./all.dhall
+ dhall-lang/Prelude/List/all.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `True` if the supplied function returns `True` for all elements in the+`List`+-}+let all+    : ∀(a : Type) → (a → Bool) → List a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : List a) →+        List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x && r) True++let example0 = assert : all Natural Natural/even [ 2, 3, 5 ] ≡ False++let example1 = assert : all Natural Natural/even ([] : List Natural) ≡ True++in  all
+ dhall-lang/Prelude/List/any view
@@ -0,0 +1,3 @@+  missing+    sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8+? ./any.dhall
+ dhall-lang/Prelude/List/any.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `True` if the supplied function returns `True` for any element in the+`List`+-}+let any+    : ∀(a : Type) → (a → Bool) → List a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : List a) →+        List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False++let example0 = assert : any Natural Natural/even [ 2, 3, 5 ] ≡ True++let example1 = assert : any Natural Natural/even ([] : List Natural) ≡ False++in  any
+ dhall-lang/Prelude/List/build view
@@ -0,0 +1,3 @@+  missing+    sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42+? ./build.dhall
+ dhall-lang/Prelude/List/build.dhall view
@@ -0,0 +1,30 @@+--| `build` is the inverse of `fold`+let build+    : ∀(a : Type) →+      (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list) →+        List a+    = List/build++let example0 =+        assert+      :   build+            Text+            ( λ(list : Type) →+              λ(cons : Text → list → list) →+              λ(nil : list) →+                cons "ABC" (cons "DEF" nil)+            )+        ≡ [ "ABC", "DEF" ]++let example1 =+        assert+      :   build+            Text+            ( λ(list : Type) →+              λ(cons : Text → list → list) →+              λ(nil : list) →+                nil+            )+        ≡ ([] : List Text)++in  build
+ dhall-lang/Prelude/List/concat view
@@ -0,0 +1,3 @@+  missing+    sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b+? ./concat.dhall
+ dhall-lang/Prelude/List/concat.dhall view
@@ -0,0 +1,34 @@+--| Concatenate a `List` of `List`s into a single `List`+let concat+    : ∀(a : Type) → List (List a) → List a+    = λ(a : Type) →+      λ(xss : List (List a)) →+        List/build+          a+          ( λ(list : Type) →+            λ(cons : a → list → list) →+            λ(nil : list) →+              List/fold+                (List a)+                xss+                list+                (λ(xs : List a) → λ(ys : list) → List/fold a xs list cons ys)+                nil+          )++let example0 =+        assert+      :   concat Natural [ [ 0, 1, 2 ], [ 3, 4 ], [ 5, 6, 7, 8 ] ]+        ≡ [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]++let example1 =+        assert+      :   concat+            Natural+            [ [] : List Natural, [] : List Natural, [] : List Natural ]+        ≡ ([] : List Natural)++let example2 =+      assert : concat Natural ([] : List (List Natural)) ≡ ([] : List Natural)++in  concat
+ dhall-lang/Prelude/List/concatMap view
@@ -0,0 +1,3 @@+  missing+    sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+? ./concatMap.dhall
+ dhall-lang/Prelude/List/concatMap.dhall view
@@ -0,0 +1,32 @@+{-|+Transform a list by applying a function to each element and flattening the+results+-}+let concatMap+    : ∀(a : Type) → ∀(b : Type) → (a → List b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → List b) →+      λ(xs : List a) →+        List/build+          b+          ( λ(list : Type) →+            λ(cons : b → list → list) →+              List/fold a xs list (λ(x : a) → List/fold b (f x) list cons)+          )++let example0 =+        assert+      :   concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+        ≡ [ 2, 2, 3, 3, 5, 5 ]++let example1 =+        assert+      :   concatMap+            Natural+            Natural+            (λ(n : Natural) → [ n, n ])+            ([] : List Natural)+        ≡ ([] : List Natural)++in  concatMap
+ dhall-lang/Prelude/List/default view
@@ -0,0 +1,3 @@+  missing+    sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+? ./default.dhall
+ dhall-lang/Prelude/List/default.dhall view
@@ -0,0 +1,15 @@+{-|+Unpack an `Optional` containing a `List`, defaulting to an empty list when the+`Optional` is `None`+-}+let default+    : ∀(a : Type) → Optional (List a) → List a+    = λ(a : Type) →+      λ(o : Optional (List a)) →+        merge { Some = λ(l : List a) → l, None = [] : List a } o++let example0 = assert : default Bool (None (List Bool)) ≡ ([] : List Bool)++let example1 = assert : default Bool (Some [ True ]) ≡ [ True ]++in  default
+ dhall-lang/Prelude/List/drop view
@@ -0,0 +1,3 @@+  missing+    sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+? ./drop.dhall
+ dhall-lang/Prelude/List/drop.dhall view
@@ -0,0 +1,28 @@+--| Remove first `n` elements of a list+let Natural/greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ../Natural/greaterThanEqual.dhall++let drop+    : ∀(n : Natural) → ∀(a : Type) → List a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(xs : List a) →+        List/fold+          { index : Natural, value : a }+          (List/indexed a xs)+          (List a)+          ( λ(x : { index : Natural, value : a }) →+            λ(xs : List a) →+              if    Natural/greaterThanEqual x.index n+              then  [ x.value ] # xs+              else  xs+          )+          ([] : List a)++let example = assert : drop 2 Natural [ 2, 3, 5 ] ≡ [ 5 ]++let example = assert : drop 5 Natural [ 2, 3, 5 ] ≡ ([] : List Natural)++in  drop
+ dhall-lang/Prelude/List/empty view
@@ -0,0 +1,3 @@+  missing+    sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+? ./empty.dhall
+ dhall-lang/Prelude/List/empty.dhall view
@@ -0,0 +1,8 @@+--| An empty list of the given type+let empty+    : ∀(a : Type) → List a+    = λ(a : Type) → [] : List a++let example0 = assert : empty Bool ≡ ([] : List Bool)++in  empty
+ dhall-lang/Prelude/List/filter view
@@ -0,0 +1,3 @@+  missing+    sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6+? ./filter.dhall
+ dhall-lang/Prelude/List/filter.dhall view
@@ -0,0 +1,22 @@+--| Only keep elements of the list where the supplied function returns `True`+let filter+    : ∀(a : Type) → (a → Bool) → List a → List a+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : List a) →+        List/build+          a+          ( λ(list : Type) →+            λ(cons : a → list → list) →+              List/fold+                a+                xs+                list+                (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)+          )++let example0 = assert : filter Natural Natural/even [ 2, 3, 5 ] ≡ [ 2 ]++let example1 = assert : filter Natural Natural/odd [ 2, 3, 5 ] ≡ [ 3, 5 ]++in  filter
+ dhall-lang/Prelude/List/filterMap.dhall view
@@ -0,0 +1,45 @@+--| Transform a list by applying a function to each element and omitting None results.+let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ./concatMap.dhall++let Optional/toList =+        missing+          sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+      ? ../Optional/toList.dhall++let filterMap+    : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+        List/concatMap a b (λ(x : a) → Optional/toList b (f x))++let example0 =+        assert+      :   filterMap+            (List Natural)+            Natural+            (List/head Natural)+            [ [ 1 ], [] : List Natural, [ 3, 4 ] ]+        ≡ [ 1, 3 ]++let example1 =+      let Example = < Left : Bool | Right : Natural >++      in    assert+          :   filterMap+                Example+                Natural+                ( λ(x : Example) →+                    merge+                      { Left = λ(_ : Bool) → None Natural+                      , Right = λ(n : Natural) → Some n+                      }+                      x+                )+                [ Example.Left False, Example.Right 2, Example.Left True ]+            ≡ [ 2 ]++in  filterMap
+ dhall-lang/Prelude/List/fold view
@@ -0,0 +1,3 @@+  missing+    sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814+? ./fold.dhall
+ dhall-lang/Prelude/List/fold.dhall view
@@ -0,0 +1,43 @@+{-|+`fold` is the primitive function for consuming `List`s++If you treat the list `[ x, y, z ]` as `cons x (cons y (cons z nil))`, then a+`fold` just replaces each `cons` and `nil` with something else+-}+let fold+    : ∀(a : Type) →+      List a →+      ∀(list : Type) →+      ∀(cons : a → list → list) →+      ∀(nil : list) →+        list+    = List/fold++let example0 =+        assert+      :   fold+            Natural+            [ 2, 3, 5 ]+            Text+            (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+            "0"+        ≡ "2350"++let example1 =+      λ(nil : Text) →+          assert+        :   fold+              Natural+              [ 2, 3, 5 ]+              Text+              (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+              nil+          ≡ "2" ++ ("3" ++ ("5" ++ nil))++let example2 =+      λ(cons : Natural → Text → Text) →+      λ(nil : Text) →+          assert+        : fold Natural [ 2, 3, 5 ] Text cons nil ≡ cons 2 (cons 3 (cons 5 nil))++in  fold
+ dhall-lang/Prelude/List/foldLeft.dhall view
@@ -0,0 +1,60 @@+{-|+`foldLeft` is like `List/fold` except that the accumulation starts from the left++If you treat the list `[ x, y, z ]` as `cons (cons (cons nil x) y) z`, then+`foldLeft` just replaces each `cons` and `nil` with something else+-}+let foldLeft+    : ∀(a : Type) →+      List a →+      ∀(list : Type) →+      ∀(cons : list → a → list) →+      ∀(nil : list) →+        list+    = λ(a : Type) →+      λ(xs : List a) →+      λ(list : Type) →+      λ(cons : list → a → list) →+      λ(nil : list) →+        List/fold+          a+          xs+          (list → list)+          (λ(x : a) → λ(f : list → list) → λ(l : list) → f (cons l x))+          (λ(l : list) → l)+          nil++let example0 =+        assert+      :   foldLeft+            Natural+            [ 2, 3, 5 ]+            Text+            (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+            "0"+        ≡ "0235"++let example1 =+        assert+      :   ( λ(nil : Text) →+              foldLeft+                Natural+                [ 2, 3, 5 ]+                Text+                (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+                nil+          )+        ≡ (λ(nil : Text) → nil ++ "2" ++ "3" ++ "5")++let example2 =+        assert+      :   ( λ(cons : Text → Natural → Text) →+            λ(nil : Text) →+              foldLeft Natural [ 2, 3, 5 ] Text cons nil+          )+        ≡ ( λ(cons : Text → Natural → Text) →+            λ(nil : Text) →+              cons (cons (cons nil 2) 3) 5+          )++in  foldLeft
+ dhall-lang/Prelude/List/generate view
@@ -0,0 +1,3 @@+  missing+    sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4+? ./generate.dhall
+ dhall-lang/Prelude/List/generate.dhall view
@@ -0,0 +1,35 @@+{-|+Build a list by calling the supplied function on all `Natural` numbers from `0`+up to but not including the supplied `Natural` number+-}+let generate+    : Natural → ∀(a : Type) → (Natural → a) → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(f : Natural → a) →+        List/build+          a+          ( λ(list : Type) →+            λ(cons : a → list → list) →+              List/fold+                { index : Natural, value : {} }+                ( List/indexed+                    {}+                    ( List/build+                        {}+                        ( λ(list : Type) →+                          λ(cons : {} → list → list) →+                            Natural/fold n list (cons {=})+                        )+                    )+                )+                list+                (λ(x : { index : Natural, value : {} }) → cons (f x.index))+          )++let example0 =+      assert : generate 5 Bool Natural/even ≡ [ True, False, True, False, True ]++let example1 = assert : generate 0 Bool Natural/even ≡ ([] : List Bool)++in  generate
+ dhall-lang/Prelude/List/head view
@@ -0,0 +1,3 @@+  missing+    sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026+? ./head.dhall
+ dhall-lang/Prelude/List/head.dhall view
@@ -0,0 +1,10 @@+--| Retrieve the first element of the list+let head+    : ∀(a : Type) → List a → Optional a+    = List/head++let example0 = assert : head Natural [ 0, 1, 2 ] ≡ Some 0++let example1 = assert : head Natural ([] : List Natural) ≡ None Natural++in  head
+ dhall-lang/Prelude/List/index view
@@ -0,0 +1,3 @@+  missing+    sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+? ./index.dhall
+ dhall-lang/Prelude/List/index.dhall view
@@ -0,0 +1,18 @@+--| Retrieve an element from a `List` using its 0-based index+let drop =+        missing+          sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+      ? ./drop.dhall++let index+    : Natural → ∀(a : Type) → List a → Optional a+    = λ(n : Natural) → λ(a : Type) → λ(xs : List a) → List/head a (drop n a xs)++let property =+      λ(n : Natural) → λ(a : Type) → assert : index n a ([] : List a) ≡ None a++let example0 = assert : index 1 Natural [ 2, 3, 5 ] ≡ Some 3++let example1 = assert : index 1 Natural ([] : List Natural) ≡ None Natural++in  index
+ dhall-lang/Prelude/List/indexed view
@@ -0,0 +1,3 @@+  missing+    sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f+? ./indexed.dhall
+ dhall-lang/Prelude/List/indexed.dhall view
@@ -0,0 +1,19 @@+--| Tag each element of the list with its index+let indexed+    : ∀(a : Type) → List a → List { index : Natural, value : a }+    = List/indexed++let example0 =+        assert+      :   indexed Bool [ True, False, True ]+        ≡ [ { index = 0, value = True }+          , { index = 1, value = False }+          , { index = 2, value = True }+          ]++let example1 =+        assert+      :   indexed Bool ([] : List Bool)+        ≡ ([] : List { index : Natural, value : Bool })++in  indexed
+ dhall-lang/Prelude/List/iterate view
@@ -0,0 +1,3 @@+  missing+    sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26+? ./iterate.dhall
+ dhall-lang/Prelude/List/iterate.dhall view
@@ -0,0 +1,42 @@+{-|+Generate a list of the specified length given a seed value and transition+function+-}+let iterate+    : Natural → ∀(a : Type) → (a → a) → a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(f : a → a) →+      λ(x : a) →+        List/build+          a+          ( λ(list : Type) →+            λ(cons : a → list → list) →+              List/fold+                { index : Natural, value : {} }+                ( List/indexed+                    {}+                    ( List/build+                        {}+                        ( λ(list : Type) →+                          λ(cons : {} → list → list) →+                            Natural/fold n list (cons {=})+                        )+                    )+                )+                list+                ( λ(y : { index : Natural, value : {} }) →+                    cons (Natural/fold y.index a f x)+                )+          )++let example0 =+        assert+      :   iterate 10 Natural (λ(x : Natural) → x * 2) 1+        ≡ [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ]++let example1 =+        assert+      : iterate 0 Natural (λ(x : Natural) → x * 2) 1 ≡ ([] : List Natural)++in  iterate
+ dhall-lang/Prelude/List/last view
@@ -0,0 +1,3 @@+  missing+    sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d+? ./last.dhall
+ dhall-lang/Prelude/List/last.dhall view
@@ -0,0 +1,10 @@+--| Retrieve the last element of the list+let last+    : ∀(a : Type) → List a → Optional a+    = List/last++let example0 = assert : last Natural [ 0, 1, 2 ] ≡ Some 2++let example1 = assert : last Natural ([] : List Natural) ≡ None Natural++in  last
+ dhall-lang/Prelude/List/length view
@@ -0,0 +1,3 @@+  missing+    sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461+? ./length.dhall
+ dhall-lang/Prelude/List/length.dhall view
@@ -0,0 +1,10 @@+--| Returns the number of elements in a list+let length+    : ∀(a : Type) → List a → Natural+    = List/length++let example0 = assert : length Natural [ 0, 1, 2 ] ≡ 3++let example1 = assert : length Natural ([] : List Natural) ≡ 0++in  length
+ dhall-lang/Prelude/List/map view
@@ -0,0 +1,3 @@+  missing+    sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+? ./map.dhall
+ dhall-lang/Prelude/List/map.dhall view
@@ -0,0 +1,23 @@+--| Transform a list by applying a function to each element+let map+    : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → b) →+      λ(xs : List a) →+        List/build+          b+          ( λ(list : Type) →+            λ(cons : b → list → list) →+              List/fold a xs list (λ(x : a) → cons (f x))+          )++let example0 =+        assert+      : map Natural Bool Natural/even [ 2, 3, 5 ] ≡ [ True, False, False ]++let example1 =+        assert+      : map Natural Bool Natural/even ([] : List Natural) ≡ ([] : List Bool)++in  map
+ dhall-lang/Prelude/List/mapMaybe.dhall view
@@ -0,0 +1,37 @@+--| Apply a function across a list, keeping only the `Some` results.+let List/unpackOptionals =+        missing+          sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+      ? ./unpackOptionals.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ./map.dhall++let mapMaybe+    : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+      λ(xs : List a) →+        List/unpackOptionals b (List/map a (Optional b) f xs)++let property =+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+        assert : mapMaybe a b f ([] : List a) ≡ ([] : List b)++let example0 =+        assert+      :   mapMaybe+            Natural+            Text+            ( λ(n : Natural) →+                if Natural/isZero n then None Text else Some (Natural/show n)+            )+            [ 0, 1, 2, 3 ]+        ≡ [ "1", "2", "3" ]++in  mapMaybe
+ dhall-lang/Prelude/List/mapWithIndex.dhall view
@@ -0,0 +1,41 @@+--| Transform a list by applying a function to each element with its index+let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ./map.dhall++let List/mapWithIndex+    : ∀(a : Type) → ∀(b : Type) → (Natural → a → b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : Natural → a → b) →+      λ(xs : List a) →+        List/map+          { index : Natural, value : a }+          b+          (λ(i : { index : Natural, value : a }) → f i.index i.value)+          (List/indexed a xs)++let List/empty =+        missing+          sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+      ? ./empty.dhall++let List/replicate =+        missing+          sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+      ? ./replicate.dhall++let example0 =+        assert+      :   List/mapWithIndex+            Text+            (List Text)+            ( λ(index : Natural) →+              λ(value : Text) →+                List/replicate index Text value+            )+            [ "A", "B", "C" ]+        ≡ [ List/empty Text, [ "B" ], [ "C", "C" ] ]++in  List/mapWithIndex
+ dhall-lang/Prelude/List/null view
@@ -0,0 +1,3 @@+  missing+    sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80+? ./null.dhall
+ dhall-lang/Prelude/List/null.dhall view
@@ -0,0 +1,10 @@+--| Returns `True` if the `List` is empty and `False` otherwise+let null+    : ∀(a : Type) → List a → Bool+    = λ(a : Type) → λ(xs : List a) → Natural/isZero (List/length a xs)++let example0 = assert : null Natural [ 0, 1, 2 ] ≡ False++let example1 = assert : null Natural ([] : List Natural) ≡ True++in  null
+ dhall-lang/Prelude/List/package.dhall view
@@ -0,0 +1,125 @@+{ all =+      missing+        sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15+    ? ./all.dhall+, any =+      missing+        sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8+    ? ./any.dhall+, build =+      missing+        sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42+    ? ./build.dhall+, concat =+      missing+        sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b+    ? ./concat.dhall+, concatMap =+      missing+        sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+    ? ./concatMap.dhall+, default =+      missing+        sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+    ? ./default.dhall+, drop =+      missing+        sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+    ? ./drop.dhall+, empty =+      missing+        sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+    ? ./empty.dhall+, filter =+      missing+        sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6+    ? ./filter.dhall+, filterMap =+      missing+        sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+    ? ./filterMap.dhall+, fold =+      missing+        sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814+    ? ./fold.dhall+, foldLeft =+      missing+        sha256:3c6ab57950fe644906b7bbdef0b9523440b6ee17773ebb8cbd41ffacb8bfab61+    ? ./foldLeft.dhall+, generate =+      missing+        sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4+    ? ./generate.dhall+, head =+      missing+        sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026+    ? ./head.dhall+, index =+      missing+        sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+    ? ./index.dhall+, indexed =+      missing+        sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f+    ? ./indexed.dhall+, iterate =+      missing+        sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26+    ? ./iterate.dhall+, last =+      missing+        sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d+    ? ./last.dhall+, length =+      missing+        sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461+    ? ./length.dhall+, map =+      missing+        sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+    ? ./map.dhall+, mapMaybe =+      missing+        sha256:6f3c4f8c94577b46e7d30f8df7e82a269b0ad0a7e18c0f0370f243fd1127e77f+    ? ./mapMaybe.dhall+, mapWithIndex =+      missing+        sha256:98599e0b55c5d3ae75264ba90657c6f68c7ce32834bd12b215acaea711eed6eb+    ? ./mapWithIndex.dhall+, null =+      missing+        sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80+    ? ./null.dhall+, partition =+      missing+        sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+    ? ./partition.dhall+, replicate =+      missing+        sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+    ? ./replicate.dhall+, reverse =+      missing+        sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d+    ? ./reverse.dhall+, shifted =+      missing+        sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+    ? ./shifted.dhall+, take =+      missing+        sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+    ? ./take.dhall+, unpackOptionals =+      missing+        sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+    ? ./unpackOptionals.dhall+, unzip =+      missing+        sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+    ? ./unzip.dhall+, zip =+      missing+        sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+    ? ./zip.dhall+}
+ dhall-lang/Prelude/List/partition view
@@ -0,0 +1,3 @@+  missing+    sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+? ./partition.dhall
+ dhall-lang/Prelude/List/partition.dhall view
@@ -0,0 +1,31 @@+{-|+`partition` divides a `List` of elements into those that satisfy a predicate+and those that do not+-}+let Partition+    : Type → Type+    = λ(a : Type) → { true : List a, false : List a }++let partition+    : ∀(a : Type) → (a → Bool) → List a → Partition a+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : List a) →+        List/fold+          a+          xs+          (Partition a)+          ( λ(x : a) →+            λ(p : Partition a) →+              if    f x+              then  { true = [ x ] # p.true, false = p.false }+              else  { true = p.true, false = [ x ] # p.false }+          )+          { true = [] : List a, false = [] : List a }++let example0 =+        assert+      :   partition Natural Natural/even [ 0, 1, 2, 3 ]+        ≡ { true = [ 0, 2 ], false = [ 1, 3 ] }++in  partition
+ dhall-lang/Prelude/List/replicate view
@@ -0,0 +1,3 @@+  missing+    sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+? ./replicate.dhall
+ dhall-lang/Prelude/List/replicate.dhall view
@@ -0,0 +1,18 @@+--| Build a list by copying the given element the specified number of times+let replicate+    : Natural → ∀(a : Type) → a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(x : a) →+        List/build+          a+          ( λ(list : Type) →+            λ(cons : a → list → list) →+              Natural/fold n list (cons x)+          )++let example0 = assert : replicate 9 Natural 1 ≡ [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]++let example1 = assert : replicate 0 Natural 1 ≡ ([] : List Natural)++in  replicate
+ dhall-lang/Prelude/List/reverse view
@@ -0,0 +1,3 @@+  missing+    sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d+? ./reverse.dhall
+ dhall-lang/Prelude/List/reverse.dhall view
@@ -0,0 +1,11 @@+--| Reverse a list+let reverse+    : ∀(a : Type) → List a → List a+    = List/reverse++let example0 = assert : reverse Natural [ 0, 1, 2 ] ≡ [ 2, 1, 0 ]++let example1 =+      assert : reverse Natural ([] : List Natural) ≡ ([] : List Natural)++in  reverse
+ dhall-lang/Prelude/List/shifted view
@@ -0,0 +1,3 @@+  missing+    sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+? ./shifted.dhall
+ dhall-lang/Prelude/List/shifted.dhall view
@@ -0,0 +1,83 @@+{-|+Combine a `List` of `List`s, offsetting the `index` of each element by the+number of elements in preceding lists+-}+let shifted+    : ∀(a : Type) →+      List (List { index : Natural, value : a }) →+        List { index : Natural, value : a }+    = λ(a : Type) →+      λ(kvss : List (List { index : Natural, value : a })) →+        List/build+          { index : Natural, value : a }+          ( λ(list : Type) →+            λ(cons : { index : Natural, value : a } → list → list) →+            λ(nil : list) →+              let result =+                    List/fold+                      (List { index : Natural, value : a })+                      kvss+                      { count : Natural, diff : Natural → list }+                      ( λ(kvs : List { index : Natural, value : a }) →+                        λ(y : { count : Natural, diff : Natural → list }) →+                          let length =+                                List/length { index : Natural, value : a } kvs++                          in  { count = y.count + length+                              , diff =+                                  λ(n : Natural) →+                                    List/fold+                                      { index : Natural, value : a }+                                      kvs+                                      list+                                      ( λ ( kvOld+                                          : { index : Natural, value : a }+                                          ) →+                                        λ(z : list) →+                                          let kvNew =+                                                { index = kvOld.index + n+                                                , value = kvOld.value+                                                }++                                          in  cons kvNew z+                                      )+                                      (y.diff (n + length))+                              }+                      )+                      { count = 0, diff = λ(_ : Natural) → nil }++              in  result.diff 0+          )++let example0 =+        assert+      :   shifted+            Bool+            [ [ { index = 0, value = True }+              , { index = 1, value = True }+              , { index = 2, value = True }+              ]+            , [ { index = 0, value = False }, { index = 1, value = False } ]+            , [ { index = 0, value = True }+              , { index = 1, value = True }+              , { index = 2, value = True }+              , { index = 3, value = True }+              ]+            ]+        ≡ [ { index = 0, value = True }+          , { index = 1, value = True }+          , { index = 2, value = True }+          , { index = 3, value = False }+          , { index = 4, value = False }+          , { index = 5, value = True }+          , { index = 6, value = True }+          , { index = 7, value = True }+          , { index = 8, value = True }+          ]++let example1 =+        assert+      :   shifted Bool ([] : List (List { index : Natural, value : Bool }))+        ≡ ([] : List { index : Natural, value : Bool })++in  shifted
+ dhall-lang/Prelude/List/take view
@@ -0,0 +1,3 @@+  missing+    sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+? ./take.dhall
+ dhall-lang/Prelude/List/take.dhall view
@@ -0,0 +1,26 @@+--| Truncate a list to the first `n` elements+let Natural/lessThan =+        missing+          sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+      ? ../Natural/lessThan.dhall++let take+    : ∀(n : Natural) → ∀(a : Type) → List a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(xs : List a) →+        List/fold+          { index : Natural, value : a }+          (List/indexed a xs)+          (List a)+          ( λ(x : { index : Natural, value : a }) →+            λ(xs : List a) →+              if Natural/lessThan x.index n then [ x.value ] # xs else xs+          )+          ([] : List a)++let example = assert : take 2 Natural [ 2, 3, 5 ] ≡ [ 2, 3 ]++let example = assert : take 5 Natural [ 2, 3, 5 ] ≡ [ 2, 3, 5 ]++in  take
+ dhall-lang/Prelude/List/unpackOptionals view
@@ -0,0 +1,3 @@+  missing+    sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+? ./unpackOptionals.dhall
+ dhall-lang/Prelude/List/unpackOptionals.dhall view
@@ -0,0 +1,31 @@+--| Unpack Optionals in a List, omitting None items.+let List/filterMap =+        missing+          sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+      ? ./filterMap.dhall++let unpackOptionals+    : ∀(a : Type) → ∀(l : List (Optional a)) → List a+    = λ(a : Type) → List/filterMap (Optional a) a (λ(x : Optional a) → x)++let property1 =+      λ(a : Type) → λ(x : a) → assert : unpackOptionals a [ Some x ] ≡ [ x ]++let property2 =+      λ(a : Type) → assert : unpackOptionals a [ None a ] ≡ ([] : List a)++let example0 =+        assert+      : unpackOptionals Natural [ Some 1, None Natural, Some 3 ] ≡ [ 1, 3 ]++let example1 =+        assert+      :   unpackOptionals Natural ([] : List (Optional Natural))+        ≡ ([] : List Natural)++let example2 =+        assert+      :   unpackOptionals Natural [ None Natural, None Natural ]+        ≡ ([] : List Natural)++in  unpackOptionals
+ dhall-lang/Prelude/List/unzip view
@@ -0,0 +1,3 @@+  missing+    sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+? ./unzip.dhall
+ dhall-lang/Prelude/List/unzip.dhall view
@@ -0,0 +1,50 @@+--| Unzip a `List` into two separate `List`s+let unzip+    : ∀(a : Type) →+      ∀(b : Type) →+      List { _1 : a, _2 : b } →+        { _1 : List a, _2 : List b }+    = λ(a : Type) →+      λ(b : Type) →+      λ(xs : List { _1 : a, _2 : b }) →+        { _1 =+            List/build+              a+              ( λ(list : Type) →+                λ(cons : a → list → list) →+                  List/fold+                    { _1 : a, _2 : b }+                    xs+                    list+                    (λ(x : { _1 : a, _2 : b }) → cons x._1)+              )+        , _2 =+            List/build+              b+              ( λ(list : Type) →+                λ(cons : b → list → list) →+                  List/fold+                    { _1 : a, _2 : b }+                    xs+                    list+                    (λ(x : { _1 : a, _2 : b }) → cons x._2)+              )+        }++let example0 =+        assert+      :   unzip+            Text+            Bool+            [ { _1 = "ABC", _2 = True }+            , { _1 = "DEF", _2 = False }+            , { _1 = "GHI", _2 = True }+            ]+        ≡ { _1 = [ "ABC", "DEF", "GHI" ], _2 = [ True, False, True ] }++let example1 =+        assert+      :   unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+        ≡ { _1 = [] : List Text, _2 = [] : List Bool }++in  unzip
+ dhall-lang/Prelude/List/zip view
@@ -0,0 +1,3 @@+  missing+    sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+? ./zip.dhall
+ dhall-lang/Prelude/List/zip.dhall view
@@ -0,0 +1,58 @@+{-|+Zip two `List` into a single `List`++The resulting `List` will have the length of the shortest of its arguments.+-}+let List/index =+        missing+          sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+      ? ./index.dhall++let zip+    : ∀(a : Type) → List a → ∀(b : Type) → List b → List { _1 : a, _2 : b }+    = λ(a : Type) →+      λ(xs : List a) →+      λ(b : Type) →+      λ(ys : List b) →+        let ixs = List/indexed a xs++        in  List/build+              { _1 : a, _2 : b }+              ( λ(list : Type) →+                λ(cons : { _1 : a, _2 : b } → list → list) →+                λ(nil : list) →+                  List/fold+                    { index : Natural, value : a }+                    ixs+                    list+                    ( λ(ix : { index : Natural, value : a }) →+                      λ(rest : list) →+                        merge+                          { None = rest+                          , Some =+                              λ(y : b) → cons { _1 = ix.value, _2 = y } rest+                          }+                          (List/index ix.index b ys)+                    )+                    nil+              )++let example0 =+        assert+      :   zip Text [ "ABC", "DEF", "GHI" ] Natural [ 1, 2, 3 ]+        ≡ [ { _1 = "ABC", _2 = 1 }+          , { _1 = "DEF", _2 = 2 }+          , { _1 = "GHI", _2 = 3 }+          ]++let example1 =+        assert+      :   zip Text [ "ABC" ] Bool ([] : List Bool)+        ≡ ([] : List { _1 : Text, _2 : Bool })++let example2 =+        assert+      :   zip Text [ "ABC", "DEF", "GHI" ] Natural [ 1 ]+        ≡ [ { _1 = "ABC", _2 = 1 } ]++in  zip
+ dhall-lang/Prelude/Location/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+? ./Type.dhall
+ dhall-lang/Prelude/Location/Type.dhall view
@@ -0,0 +1,15 @@+--| This is the union type returned when you import something `as Location`+let Location+    : Type+    = < Environment : Text | Local : Text | Missing | Remote : Text >++let example0 =+        assert+      :   missing as Location+        ≡ < Environment : Text+          | Local : Text+          | Missing+          | Remote : Text+          >.Missing++in  Location
+ dhall-lang/Prelude/Location/package.dhall view
@@ -0,0 +1,5 @@+{ Type =+      missing+        sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+    ? ./Type.dhall+}
+ dhall-lang/Prelude/Map/Entry view
@@ -0,0 +1,3 @@+  missing+    sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+? ./Entry.dhall
+ dhall-lang/Prelude/Map/Entry.dhall view
@@ -0,0 +1,6 @@+--| The type of each key-value pair in a `Map`+let Entry+    : Type → Type → Type+    = λ(k : Type) → λ(v : Type) → { mapKey : k, mapValue : v }++in  Entry
+ dhall-lang/Prelude/Map/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+? ./Type.dhall
+ dhall-lang/Prelude/Map/Type.dhall view
@@ -0,0 +1,25 @@+{-|+This is the canonical way to encode a dynamic list of key-value pairs.++Tools (such as `dhall-to-json`/`dhall-to-yaml` will recognize values of this+type and convert them to maps/dictionaries/hashes in the target language++For example, `dhall-to-json` converts a Dhall value like this:++```+[ { mapKey = "foo", mapValue = 1 }+, { mapKey = "bar", mapValue = 2 }+] : ./Map Text Natural+```++... to a JSON value like this:++```+{ "foo": 1, "bar", 2 }+```+-}+let Map+    : Type → Type → Type+    = λ(k : Type) → λ(v : Type) → List { mapKey : k, mapValue : v }++in  Map
+ dhall-lang/Prelude/Map/empty view
@@ -0,0 +1,3 @@+  missing+    sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+? ./empty.dhall
+ dhall-lang/Prelude/Map/empty.dhall view
@@ -0,0 +1,14 @@+--| An empty `Map` of the given key and value types+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let empty+    : ∀(k : Type) → ∀(v : Type) → Map k v+    = λ(k : Type) → λ(v : Type) → [] : Map k v++let example0 =+      assert : empty Text Bool ≡ ([] : List { mapKey : Text, mapValue : Bool })++in  empty
+ dhall-lang/Prelude/Map/keyText view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ./keyText.dhall
+ dhall-lang/Prelude/Map/keyText.dhall view
@@ -0,0 +1,15 @@+{-|+Builds a key-value record such that a `List` of them will be converted to a+homogeneous record by dhall-to-json and dhall-to-yaml.++Both key and value are fixed to `Text`.++Take a look at `./keyValue` for a polymorphic version.+-}+let keyText =+      λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++let example0 =+      assert : keyText "foo" "bar" ≡ { mapKey = "foo", mapValue = "bar" }++in  keyText
+ dhall-lang/Prelude/Map/keyValue view
@@ -0,0 +1,3 @@+  missing+    sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+? ./keyValue.dhall
+ dhall-lang/Prelude/Map/keyValue.dhall view
@@ -0,0 +1,17 @@+{-|+Builds a key-value record such that a List of them will be converted to a+homogeneous record by dhall-to-json and dhall-to-yaml.+-}+let keyValue =+      λ(v : Type) →+      λ(key : Text) →+      λ(value : v) →+        { mapKey = key, mapValue = value }++let example0 =+      assert : keyValue Natural "foo" 2 ≡ { mapKey = "foo", mapValue = 2 }++let example1 =+      assert : keyValue Text "bar" "baz" ≡ { mapKey = "bar", mapValue = "baz" }++in  keyValue
+ dhall-lang/Prelude/Map/keys view
@@ -0,0 +1,3 @@+  missing+    sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+? ./keys.dhall
+ dhall-lang/Prelude/Map/keys.dhall view
@@ -0,0 +1,39 @@+--| Get all of the keys of a `Map` as a `List`+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map++let keys+    : ∀(k : Type) → ∀(v : Type) → Map k v → List k+    = λ(k : Type) →+      λ(v : Type) →+        List/map (Entry k v) k (λ(x : Entry k v) → x.mapKey)++let example0 =+        assert+      :   keys+            Text+            Natural+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ "A", "B", "C" ]++let example1 =+        assert+      :   keys Text Natural ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List Text)++in  keys
+ dhall-lang/Prelude/Map/map view
@@ -0,0 +1,3 @@+  missing+    sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+? ./map.dhall
+ dhall-lang/Prelude/Map/map.dhall view
@@ -0,0 +1,58 @@+--| Transform a `Map` by applying a function to each value+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let map+    : ∀(k : Type) → ∀(a : Type) → ∀(b : Type) → (a → b) → Map k a → Map k b+    = λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → b) →+      λ(m : Map k a) →+        List/map+          (Entry k a)+          (Entry k b)+          ( λ(before : Entry k a) →+              { mapKey = before.mapKey, mapValue = f before.mapValue }+          )+          m++let example0 =+        assert+      :   map+            Text+            Natural+            Bool+            Natural/even+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ { mapKey = "A", mapValue = True }+          , { mapKey = "B", mapValue = False }+          , { mapKey = "C", mapValue = False }+          ]++let example1 =+        assert+      :   map+            Text+            Natural+            Bool+            Natural/even+            ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List { mapKey : Text, mapValue : Bool })++in  map
+ dhall-lang/Prelude/Map/mapMaybe.dhall view
@@ -0,0 +1,56 @@+--| Apply a function across the values of a `Map k v`, dropping+--  entries whose values return `None`.+let Map/empty =+        missing+          sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+      ? ./empty.dhall++let Map/unpackOptionals =+        missing+          sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+      ? ./unpackOptionals.dhall++let Map/map =+        missing+          sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+      ? ./map.dhall++let Map/Type =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let mapMaybe+    : ∀(k : Type) →+      ∀(a : Type) →+      ∀(b : Type) →+      (a → Optional b) →+      Map/Type k a →+        Map/Type k b+    = λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+      λ(m : Map/Type k a) →+        Map/unpackOptionals k b (Map/map k a (Optional b) f m)++let property =+      λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+        assert : mapMaybe k a b f (Map/empty k a) ≡ Map/empty k b++let example0 =+        assert+      :   mapMaybe+            Text+            Natural+            Text+            ( λ(n : Natural) →+                if Natural/isZero n then None Text else Some (Natural/show n)+            )+            (toMap { foo = 2, bar = 0 })+        ≡ toMap { foo = "2" }++in  mapMaybe
+ dhall-lang/Prelude/Map/package.dhall view
@@ -0,0 +1,41 @@+{ Type =+      missing+        sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+    ? ./Type+, Entry =+      missing+        sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+    ? ./Entry+, empty =+      missing+        sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+    ? ./empty+, keyText =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./keyText+, keyValue =+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+    ? ./keyValue+, keys =+      missing+        sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+    ? ./keys+, map =+      missing+        sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+    ? ./map+, mapMaybe =+      missing+        sha256:4ea58b720d7af38cef3ef07bef36e476caeed21032cd4a9dc733868a74d9a521+    ? ./mapMaybe.dhall+, unpackOptionals =+      missing+        sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+    ? ./unpackOptionals.dhall+, values =+      missing+        sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+    ? ./values+}
+ dhall-lang/Prelude/Map/unpackOptionals.dhall view
@@ -0,0 +1,41 @@+--| Turn a `Map k (Optional v)` into a `Map k v` by dropping all+--  entries with value `None`.+let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let Map/Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let Map/Type =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let unpackOptionals+    : ∀(k : Type) → ∀(v : Type) → Map/Type k (Optional v) → Map/Type k v+    = λ(k : Type) →+      λ(v : Type) →+        List/concatMap+          (Map/Entry k (Optional v))+          (Map/Entry k v)+          ( λ(e : Map/Entry k (Optional v)) →+              merge+                { None = [] : Map/Type k v+                , Some = λ(v : v) → [ { mapKey = e.mapKey, mapValue = v } ]+                }+                e.mapValue+          )++let example0 =+        assert+      :   unpackOptionals+            Text+            Text+            (toMap { foo = Some "bar", baz = None Text })+        ≡ toMap { foo = "bar" }++in  unpackOptionals
+ dhall-lang/Prelude/Map/values view
@@ -0,0 +1,3 @@+  missing+    sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+? ./values.dhall
+ dhall-lang/Prelude/Map/values.dhall view
@@ -0,0 +1,39 @@+--| Get all of the values of a `Map` as a `List`+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let values+    : ∀(k : Type) → ∀(v : Type) → Map k v → List v+    = λ(k : Type) →+      λ(v : Type) →+        List/map (Entry k v) v (λ(x : Entry k v) → x.mapValue)++let example0 =+        assert+      :   values+            Text+            Natural+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ 2, 3, 5 ]++let example1 =+        assert+      :   values Text Natural ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List Natural)++in  values
+ dhall-lang/Prelude/Monoid view
@@ -0,0 +1,3 @@+  missing+    sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+? ./Monoid.dhall
+ dhall-lang/Prelude/Monoid.dhall view
@@ -0,0 +1,43 @@+{-|+Any function `f` that is a `Monoid` must satisfy the following law:++```+t  : Type+f  : ./Monoid t+xs : List (List t)++f (./List/concat t xs) = f (./map (List t) t f xs)+```++Examples:++```+./Bool/and+    : ./Monoid Bool+./Bool/or+    : ./Monoid Bool+./Bool/even+    : ./Monoid Bool+./Bool/odd+    : ./Monoid Bool+./List/concat+    : ∀(a : Type) → ./Monoid (List a)+./List/shifted+    : ∀(a : Type) → ./Monoid (List { index : Natural, value : a })+./Natural/sum+    : ./Monoid Natural+./Natural/product+    : ./Monoid Natural+./Optional/head+    : ∀(a : Type) → ./Monoid (Optional a)+./Optional/last+    : ∀(a : Type) → ./Monoid (Optional a)+./Text/concat+    : ./Monoid Text+```+-}+let Monoid+    : ∀(m : Type) → Type+    = λ(m : Type) → List m → m++in  Monoid
+ dhall-lang/Prelude/Natural/build view
@@ -0,0 +1,3 @@+  missing+    sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c+? ./build.dhall
+ dhall-lang/Prelude/Natural/build.dhall view
@@ -0,0 +1,31 @@+--| `build` is the inverse of `fold`+let build+    : ( ∀(natural : Type) →+        ∀(succ : natural → natural) →+        ∀(zero : natural) →+          natural+      ) →+        Natural+    = Natural/build++let example0 =+        assert+      :   build+            ( λ(natural : Type) →+              λ(succ : natural → natural) →+              λ(zero : natural) →+                succ (succ (succ zero))+            )+        ≡ 3++let example1 =+        assert+      :   build+            ( λ(natural : Type) →+              λ(succ : natural → natural) →+              λ(zero : natural) →+                zero+            )+        ≡ 0++in  build
+ dhall-lang/Prelude/Natural/enumerate view
@@ -0,0 +1,3 @@+  missing+    sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+? ./enumerate.dhall
+ dhall-lang/Prelude/Natural/enumerate.dhall view
@@ -0,0 +1,32 @@+{-|+Generate a list of numbers from `0` up to but not including the specified+number+-}+let enumerate+    : Natural → List Natural+    = λ(n : Natural) →+        List/build+          Natural+          ( λ(list : Type) →+            λ(cons : Natural → list → list) →+              List/fold+                { index : Natural, value : {} }+                ( List/indexed+                    {}+                    ( List/build+                        {}+                        ( λ(list : Type) →+                          λ(cons : {} → list → list) →+                            Natural/fold n list (cons {=})+                        )+                    )+                )+                list+                (λ(x : { index : Natural, value : {} }) → cons x.index)+          )++let example0 = assert : enumerate 10 ≡ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]++let example1 = assert : enumerate 0 ≡ ([] : List Natural)++in  enumerate
+ dhall-lang/Prelude/Natural/equal view
@@ -0,0 +1,3 @@+  missing+    sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+? ./equal.dhall
+ dhall-lang/Prelude/Natural/equal.dhall view
@@ -0,0 +1,17 @@+--| `equal` checks if two Naturals are equal.+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let equal+    : Natural → Natural → Bool+    = λ(a : Natural) → λ(b : Natural) → lessThanEqual a b && lessThanEqual b a++let example0 = assert : equal 5 5 ≡ True++let example1 = assert : equal 5 6 ≡ False++let property0 = λ(n : Natural) → assert : equal n n ≡ True++in  equal
+ dhall-lang/Prelude/Natural/even view
@@ -0,0 +1,3 @@+  missing+    sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66+? ./even.dhall
+ dhall-lang/Prelude/Natural/even.dhall view
@@ -0,0 +1,10 @@+--| Returns `True` if a number if even and returns `False` otherwise+let even+    : Natural → Bool+    = Natural/even++let example0 = assert : even 3 ≡ False++let example1 = assert : even 0 ≡ True++in  even
+ dhall-lang/Prelude/Natural/fold view
@@ -0,0 +1,3 @@+  missing+    sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+? ./fold.dhall
+ dhall-lang/Prelude/Natural/fold.dhall view
@@ -0,0 +1,28 @@+{-|+`fold` is the primitive function for consuming `Natural` numbers++If you treat the number `3` as `succ (succ (succ zero))` then a `fold` just+replaces each `succ` and `zero` with something else+-}+let fold+    : Natural →+      ∀(natural : Type) →+      ∀(succ : natural → natural) →+      ∀(zero : natural) →+        natural+    = Natural/fold++let example0 = assert : fold 3 Text (λ(x : Text) → "A" ++ x) "B" ≡ "AAAB"++let example1 =+      λ(zero : Text) →+          assert+        :   fold 3 Text (λ(x : Text) → "A" ++ x) zero+          ≡ "A" ++ ("A" ++ ("A" ++ zero))++let example2 =+      λ(succ : Text → Text) →+      λ(zero : Text) →+        assert : fold 3 Text succ zero ≡ succ (succ (succ zero))++in  fold
+ dhall-lang/Prelude/Natural/greaterThan view
@@ -0,0 +1,3 @@+  missing+    sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+? ./greaterThan.dhall
+ dhall-lang/Prelude/Natural/greaterThan.dhall view
@@ -0,0 +1,21 @@+--| `greaterThan` checks if one Natural is strictly greater than another.+let lessThan =+        missing+          sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+      ? ./lessThan.dhall++let greaterThan+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → lessThan y x++let example0 = assert : greaterThan 5 6 ≡ False++let example1 = assert : greaterThan 5 5 ≡ False++let example2 = assert : greaterThan 5 4 ≡ True++let property0 = λ(n : Natural) → assert : greaterThan 0 n ≡ False++let property1 = λ(n : Natural) → assert : greaterThan n n ≡ False++in  greaterThan
+ dhall-lang/Prelude/Natural/greaterThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+? ./greaterThanEqual.dhall
+ dhall-lang/Prelude/Natural/greaterThanEqual.dhall view
@@ -0,0 +1,23 @@+{-|+`greaterThanEqual` checks if one Natural is greater than or equal to another.+-}+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let greaterThanEqual+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → lessThanEqual y x++let example0 = assert : greaterThanEqual 5 6 ≡ False++let example1 = assert : greaterThanEqual 5 5 ≡ True++let example2 = assert : greaterThanEqual 5 4 ≡ True++let property0 = λ(n : Natural) → assert : greaterThanEqual n 0 ≡ True++let property1 = λ(n : Natural) → assert : greaterThanEqual n n ≡ True++in  greaterThanEqual
+ dhall-lang/Prelude/Natural/isZero view
@@ -0,0 +1,3 @@+  missing+    sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+? ./isZero.dhall
+ dhall-lang/Prelude/Natural/isZero.dhall view
@@ -0,0 +1,10 @@+--| Returns `True` if a number is `0` and returns `False` otherwise+let isZero+    : Natural → Bool+    = Natural/isZero++let example0 = assert : isZero 2 ≡ False++let example1 = assert : isZero 0 ≡ True++in  isZero
+ dhall-lang/Prelude/Natural/lessThan view
@@ -0,0 +1,3 @@+  missing+    sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+? ./lessThan.dhall
+ dhall-lang/Prelude/Natural/lessThan.dhall view
@@ -0,0 +1,26 @@+--| `lessThan` checks if one Natural is strictly less than another.+let greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ./greaterThanEqual.dhall++let Bool/not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let lessThan+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → Bool/not (greaterThanEqual x y)++let example0 = assert : lessThan 5 6 ≡ True++let example1 = assert : lessThan 5 5 ≡ False++let example2 = assert : lessThan 5 4 ≡ False++let property0 = λ(n : Natural) → assert : lessThan n 0 ≡ False++let property1 = λ(n : Natural) → assert : lessThan n n ≡ False++in  lessThan
+ dhall-lang/Prelude/Natural/lessThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+? ./lessThanEqual.dhall
+ dhall-lang/Prelude/Natural/lessThanEqual.dhall view
@@ -0,0 +1,16 @@+--| `lessThanEqual` checks if one Natural is less than or equal to another.+let lessThanEqual+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → Natural/isZero (Natural/subtract y x)++let example0 = assert : lessThanEqual 5 6 ≡ True++let example1 = assert : lessThanEqual 5 5 ≡ True++let example2 = assert : lessThanEqual 5 4 ≡ False++let property0 = λ(n : Natural) → assert : lessThanEqual 0 n ≡ True++let property1 = λ(n : Natural) → assert : lessThanEqual n n ≡ True++in  lessThanEqual
+ dhall-lang/Prelude/Natural/listMax view
@@ -0,0 +1,3 @@+  missing+    sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+? ./listMax.dhall
+ dhall-lang/Prelude/Natural/listMax.dhall view
@@ -0,0 +1,30 @@+{-|+`listMax` returns the largest element of a `List` or `None Natural` if the+`List` is empty+-}+let max =+        missing+          sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+      ? ./max.dhall++let Optional/map =+        missing+          sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+      ? ../Optional/map.dhall++let listMax+    : List Natural → Optional Natural+    = λ(xs : List Natural) →+        Optional/map+          Natural+          Natural+          (λ(n : Natural) → List/fold Natural xs Natural max n)+          (List/head Natural xs)++let example0 = assert : listMax [ 1, 2 ] ≡ Some 2++let example1 = assert : listMax ([] : List Natural) ≡ None Natural++let property0 = λ(n : Natural) → assert : listMax [ n ] ≡ Some n++in  listMax
+ dhall-lang/Prelude/Natural/listMin view
@@ -0,0 +1,3 @@+  missing+    sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+? ./listMin.dhall
+ dhall-lang/Prelude/Natural/listMin.dhall view
@@ -0,0 +1,34 @@+{-|+`listMin` returns the smallest element of a `List` or `None Natural` if the+`List` is empty+-}+let min =+        missing+          sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+      ? ./min.dhall++let Optional/map =+        missing+          sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+      ? ../Optional/map.dhall++let listMin+    : List Natural → Optional Natural+    = λ(xs : List Natural) →+        Optional/map+          Natural+          Natural+          ( λ(n : Natural) →+              if Natural/isZero n then n else List/fold Natural xs Natural min n+          )+          (List/head Natural xs)++let example0 = assert : listMin [ 0, 1 ] ≡ Some 0++let example1 = assert : listMin ([] : List Natural) ≡ None Natural++let example2 = assert : listMin [ 3, 2, 1 ] ≡ Some 1++let property0 = λ(n : Natural) → assert : listMin [ n ] ≡ Some n++in  listMin
+ dhall-lang/Prelude/Natural/max view
@@ -0,0 +1,3 @@+  missing+    sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+? ./max.dhall
+ dhall-lang/Prelude/Natural/max.dhall view
@@ -0,0 +1,19 @@+--| `max a b` returns the larger of `a` or `b`+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let max+    : Natural → Natural → Natural+    = λ(a : Natural) → λ(b : Natural) → if lessThanEqual a b then b else a++let example0 = assert : max 1 2 ≡ 2++let example1 = assert : max 2 1 ≡ 2++let property0 = λ(n : Natural) → assert : max n n ≡ n++let property1 = λ(n : Natural) → assert : max 0 n ≡ n++in  max
+ dhall-lang/Prelude/Natural/min view
@@ -0,0 +1,3 @@+  missing+    sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+? ./min.dhall
+ dhall-lang/Prelude/Natural/min.dhall view
@@ -0,0 +1,17 @@+--| `min a b` returns the smaller of `a` or `b`+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let min+    : Natural → Natural → Natural+    = λ(a : Natural) → λ(b : Natural) → if lessThanEqual a b then a else b++let example0 = assert : min 1 2 ≡ 1++let example1 = assert : min 2 1 ≡ 1++let property0 = λ(n : Natural) → assert : min n n ≡ n++in  min
+ dhall-lang/Prelude/Natural/odd view
@@ -0,0 +1,3 @@+  missing+    sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5+? ./odd.dhall
+ dhall-lang/Prelude/Natural/odd.dhall view
@@ -0,0 +1,10 @@+--| Returns `True` if a number is odd and returns `False` otherwise+let odd+    : Natural → Bool+    = Natural/odd++let example0 = assert : odd 3 ≡ True++let example1 = assert : odd 0 ≡ False++in  odd
+ dhall-lang/Prelude/Natural/package.dhall view
@@ -0,0 +1,89 @@+{ build =+      missing+        sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c+    ? ./build.dhall+, enumerate =+      missing+        sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+    ? ./enumerate.dhall+, even =+      missing+        sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66+    ? ./even.dhall+, fold =+      missing+        sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+    ? ./fold.dhall+, isZero =+      missing+        sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+    ? ./isZero.dhall+, odd =+      missing+        sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5+    ? ./odd.dhall+, product =+      missing+        sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6+    ? ./product.dhall+, sum =+      missing+        sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037+    ? ./sum.dhall+, show =+      missing+        sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21+    ? ./show.dhall+, toDouble =+      missing+        sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81+    ? ./toDouble.dhall+, toInteger =+      missing+        sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f+    ? ./toInteger.dhall+, lessThan =+      missing+        sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+    ? ./lessThan.dhall+, lessThanEqual =+      missing+        sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+    ? ./lessThanEqual.dhall+, equal =+      missing+        sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+    ? ./equal.dhall+, greaterThanEqual =+      missing+        sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+    ? ./greaterThanEqual.dhall+, greaterThan =+      missing+        sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+    ? ./greaterThan.dhall+, min =+      missing+        sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+    ? ./min.dhall+, max =+      missing+        sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+    ? ./max.dhall+, listMin =+      missing+        sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+    ? ./listMin.dhall+, listMax =+      missing+        sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+    ? ./listMax.dhall+, sort =+      missing+        sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+    ? ./sort.dhall+, subtract =+      missing+        sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+    ? ./subtract.dhall+}
+ dhall-lang/Prelude/Natural/product view
@@ -0,0 +1,3 @@+  missing+    sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6+? ./product.dhall
+ dhall-lang/Prelude/Natural/product.dhall view
@@ -0,0 +1,11 @@+--| Multiply all the numbers in a `List`+let product+    : List Natural → Natural+    = λ(xs : List Natural) →+        List/fold Natural xs Natural (λ(l : Natural) → λ(r : Natural) → l * r) 1++let example0 = assert : product [ 2, 3, 5 ] ≡ 30++let example1 = assert : product ([] : List Natural) ≡ 1++in  product
+ dhall-lang/Prelude/Natural/show view
@@ -0,0 +1,3 @@+  missing+    sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21+? ./show.dhall
+ dhall-lang/Prelude/Natural/show.dhall view
@@ -0,0 +1,13 @@+{-|+Render a `Natural` number as `Text` using the same representation as Dhall+source code (i.e. a decimal number)+-}+let show+    : Natural → Text+    = Natural/show++let example0 = assert : show 3 ≡ "3"++let example1 = assert : show 0 ≡ "0"++in  show
+ dhall-lang/Prelude/Natural/sort view
@@ -0,0 +1,3 @@+  missing+    sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+? ./sort.dhall
+ dhall-lang/Prelude/Natural/sort.dhall view
@@ -0,0 +1,61 @@+--| `sort` sorts a `List` of `Natural`s in ascending order+let greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ./greaterThanEqual.dhall++let listMin =+        missing+          sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+      ? ./listMin.dhall++let List/partition =+        missing+          sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+      ? ../List/partition.dhall++let Accumulator = { sorted : List Natural, rest : List Natural }++let partitionMinima =+      λ(xs : List Natural) →+        merge+          { Some =+              λ(m : Natural) → List/partition Natural (greaterThanEqual m) xs+          , None = { true = [] : List Natural, false = [] : List Natural }+          }+          (listMin xs)++let test0 =+        assert+      : partitionMinima [ 2, 1, 1, 3 ] ≡ { true = [ 1, 1 ], false = [ 2, 3 ] }++let step =+      λ(x : Accumulator) →+        let p = partitionMinima x.rest++        in  { sorted = x.sorted # p.true, rest = p.false }++let test1 =+        assert+      :   step { sorted = [ 1, 1 ], rest = [ 2, 3 ] }+        ≡ { sorted = [ 1, 1, 2 ], rest = [ 3 ] }++let sort+    : List Natural → List Natural+    = λ(xs : List Natural) →+        let x =+              Natural/fold+                (List/length Natural xs)+                Accumulator+                step+                { sorted = [] : List Natural, rest = xs }++        in  x.sorted++let example0 = assert : sort ([] : List Natural) ≡ ([] : List Natural)++let example1 = assert : sort [ 1 ] ≡ [ 1 ]++let example2 = assert : sort [ 3, 2, 1, 3, 2, 1 ] ≡ [ 1, 1, 2, 2, 3, 3 ]++in  sort
+ dhall-lang/Prelude/Natural/subtract view
@@ -0,0 +1,3 @@+  missing+    sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+? ./subtract.dhall
+ dhall-lang/Prelude/Natural/subtract.dhall view
@@ -0,0 +1,18 @@+--| `subtract m n` computes `n - m`, truncating to `0` if `m > n`+let subtract+    : Natural → Natural → Natural+    = Natural/subtract++let example0 = assert : subtract 1 2 ≡ 1++let example1 = assert : subtract 1 1 ≡ 0++let example2 = assert : subtract 2 1 ≡ 0++let property0 = λ(n : Natural) → assert : subtract 0 n ≡ n++let property1 = λ(n : Natural) → assert : subtract n 0 ≡ 0++let property2 = λ(n : Natural) → assert : subtract n n ≡ 0++in  subtract
+ dhall-lang/Prelude/Natural/sum view
@@ -0,0 +1,3 @@+  missing+    sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037+? ./sum.dhall
+ dhall-lang/Prelude/Natural/sum.dhall view
@@ -0,0 +1,11 @@+--| Add all the numbers in a `List`+let sum+    : List Natural → Natural+    = λ(xs : List Natural) →+        List/fold Natural xs Natural (λ(l : Natural) → λ(r : Natural) → l + r) 0++let example = assert : sum [ 2, 3, 5 ] ≡ 10++let example = assert : sum ([] : List Natural) ≡ 0++in  sum
+ dhall-lang/Prelude/Natural/toDouble view
@@ -0,0 +1,3 @@+  missing+    sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81+? ./toDouble.dhall
+ dhall-lang/Prelude/Natural/toDouble.dhall view
@@ -0,0 +1,10 @@+--| Convert a `Natural` number to the corresponding `Double`+let toDouble+    : Natural → Double+    = λ(n : Natural) → Integer/toDouble (Natural/toInteger n)++let example0 = assert : toDouble 3 ≡ 3.0++let example1 = assert : toDouble 0 ≡ 0.0++in  toDouble
+ dhall-lang/Prelude/Natural/toInteger view
@@ -0,0 +1,3 @@+  missing+    sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f+? ./toInteger.dhall
+ dhall-lang/Prelude/Natural/toInteger.dhall view
@@ -0,0 +1,10 @@+--| Convert a `Natural` number to the corresponding `Integer`+let toInteger+    : Natural → Integer+    = Natural/toInteger++let example0 = assert : toInteger 3 ≡ +3++let example1 = assert : toInteger 0 ≡ +0++in  toInteger
+ dhall-lang/Prelude/NonEmpty/Type.dhall view
@@ -0,0 +1,9 @@+{-|+A `NonEmpty` list has at least one element and supports many of the same+operations as `List`s+-}+let NonEmpty+    : Type → Type+    = λ(a : Type) → { head : a, tail : List a }++in  NonEmpty
+ dhall-lang/Prelude/NonEmpty/all.dhall view
@@ -0,0 +1,34 @@+{-|+Returns `True` if the supplied function returns `True` for all elements in the+`NonEmpty` list+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ./toList.dhall++let all+    : ∀(a : Type) → (a → Bool) → NonEmpty a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : NonEmpty a) →+        List/fold+          a+          (NonEmpty/toList a xs)+          Bool+          (λ(x : a) → λ(r : Bool) → f x && r)+          True++let example0 =+      assert : all Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ False++let example1 =+        assert+      : all Natural Natural/even { head = 2, tail = [] : List Natural } ≡ True++in  all
+ dhall-lang/Prelude/NonEmpty/any.dhall view
@@ -0,0 +1,34 @@+{-|+Returns `True` if the supplied function returns `True` for any element in the+`NonEmpty` list+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ./toList.dhall++let any+    : ∀(a : Type) → (a → Bool) → NonEmpty a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : NonEmpty a) →+        List/fold+          a+          (NonEmpty/toList a xs)+          Bool+          (λ(x : a) → λ(r : Bool) → f x || r)+          False++let example0 =+      assert : any Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ True++let example1 =+        assert+      : any Natural Natural/even { head = 3, tail = [] : List Natural } ≡ False++in  any
+ dhall-lang/Prelude/NonEmpty/concat.dhall view
@@ -0,0 +1,61 @@+{-|+Concatenate a `NonEmpty` list of `NonEmpty` lists into a single `NonEmpty`+list+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ./toList.dhall++let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let concat+    : ∀(a : Type) → NonEmpty (NonEmpty a) → NonEmpty a+    = λ(a : Type) →+      λ(xss : NonEmpty (NonEmpty a)) →+        { head = xss.head.head+        , tail =+              xss.head.tail+            # List/concatMap (NonEmpty a) a (NonEmpty/toList a) xss.tail+        }++let example0 =+        assert+      :   concat+            Natural+            { head = { head = 0, tail = [ 1, 2 ] }+            , tail =+              [ { head = 3, tail = [ 4 ] }, { head = 5, tail = [ 6, 7, 8 ] } ]+            }+        ≡ { head = 0, tail = [ 1, 2, 3, 4, 5, 6, 7, 8 ] }++let example1 =+        assert+      :   concat+            Natural+            { head = { head = 0, tail = [] : List Natural }+            , tail =+              [ { head = 1, tail = [] : List Natural }+              , { head = 2, tail = [] : List Natural }+              ]+            }+        ≡ { head = 0, tail = [ 1, 2 ] : List Natural }++let example2 =+        assert+      :   concat+            Natural+            { head = { head = 0, tail = [] : List Natural }+            , tail = [] : List (NonEmpty Natural)+            }+        ≡ { head = 0, tail = [] : List Natural }++in  concat
+ dhall-lang/Prelude/NonEmpty/concatMap.dhall view
@@ -0,0 +1,56 @@+{-|+Transform a `NonEmpty` list by applying a function to each element and+flattening the results+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ./toList.dhall++let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let concatMap+    : ∀(a : Type) → ∀(b : Type) → (a → NonEmpty b) → NonEmpty a → NonEmpty b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → NonEmpty b) →+      λ(xs : NonEmpty a) →+        let ys = f xs.head++        in  { head = ys.head+            , tail =+                  ys.tail+                # List/concatMap+                    a+                    b+                    (λ(x : a) → NonEmpty/toList b (f x))+                    xs.tail+            }++let example0 =+        assert+      :   concatMap+            Natural+            Natural+            (λ(n : Natural) → { head = n, tail = [ n ] })+            { head = 2, tail = [ 3, 5 ] }+        ≡ { head = 2, tail = [ 2, 3, 3, 5, 5 ] }++let example1 =+        assert+      :   concatMap+            Natural+            Natural+            (λ(n : Natural) → { head = n, tail = [ n ] })+            { head = 2, tail = [] : List Natural }+        ≡ { head = 2, tail = [ 2 ] }++in  concatMap
+ dhall-lang/Prelude/NonEmpty/head.dhall view
@@ -0,0 +1,13 @@+--| Retrieve the first element of the `NonEmpty` list+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let head+    : ∀(a : Type) → NonEmpty a → a+    = λ(a : Type) → λ(xs : NonEmpty a) → xs.head++let example = assert : head Natural { head = 0, tail = [ 1, 2 ] } ≡ 0++in  head
+ dhall-lang/Prelude/NonEmpty/index.dhall view
@@ -0,0 +1,33 @@+--| Retrieve an element from a `NonEmpty` list using its 0-based index+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let List/index =+        missing+          sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+      ? ../List/index.dhall++let index+    : Natural → ∀(a : Type) → NonEmpty a → Optional a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(xs : NonEmpty a) →+        if    Natural/isZero n+        then  Some xs.head+        else  List/index (Natural/subtract 1 n) a xs.tail++let property =+      λ(n : Natural) →+      λ(a : Type) →+      λ(xs : NonEmpty a) →+        assert : index 0 a xs ≡ Some xs.head++let example0 = assert : index 1 Natural { head = 2, tail = [ 3, 5 ] } ≡ Some 3++let example1 =+        assert+      : index 1 Natural { head = 2, tail = [] : List Natural } ≡ None Natural++in  index
+ dhall-lang/Prelude/NonEmpty/indexed.dhall view
@@ -0,0 +1,41 @@+--| Tag each element of the `NonEmpty` list with its index+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let indexed+    : ∀(a : Type) → NonEmpty a → NonEmpty { index : Natural, value : a }+    = λ(a : Type) →+      λ(xs : NonEmpty a) →+        { head = { index = 0, value = xs.head }+        , tail =+            List/map+              { index : Natural, value : a }+              { index : Natural, value : a }+              ( λ(ix : { index : Natural, value : a }) →+                  { index = ix.index + 1, value = ix.value }+              )+              (List/indexed a xs.tail)+        }++let example0 =+        assert+      :   indexed Bool { head = True, tail = [ False, True ] }+        ≡ { head = { index = 0, value = True }+          , tail = [ { index = 1, value = False }, { index = 2, value = True } ]+          }++let example1 =+        assert+      :   indexed Bool { head = True, tail = [] : List Bool }+        ≡ { head = { index = 0, value = True }+          , tail = [] : List { index : Natural, value : Bool }+          }++in  indexed
+ dhall-lang/Prelude/NonEmpty/last.dhall view
@@ -0,0 +1,17 @@+--| Retrieve the last element of the `NonEmpty` list+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let last+    : ∀(a : Type) → NonEmpty a → a+    = λ(a : Type) →+      λ(xs : NonEmpty a) →+        merge { Some = λ(x : a) → x, None = xs.head } (List/last a xs.tail)++let example0 = assert : last Natural { head = 0, tail = [ 1, 2 ] } ≡ 2++let example1 = assert : last Natural { head = 0, tail = [] : List Natural } ≡ 0++in  last
+ dhall-lang/Prelude/NonEmpty/length.dhall view
@@ -0,0 +1,16 @@+--| Returns the number of elements in a `NonEmpty` list+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let length+    : ∀(a : Type) → NonEmpty a → Natural+    = λ(a : Type) → λ(xs : NonEmpty a) → List/length a xs.tail + 1++let example0 = assert : length Natural { head = 0, tail = [ 1, 2 ] } ≡ 3++let example1 =+      assert : length Natural { head = 0, tail = [] : List Natural } ≡ 1++in  length
+ dhall-lang/Prelude/NonEmpty/make.dhall view
@@ -0,0 +1,18 @@+{-|+Create a `NonEmpty` list using a function instead of a record++This might come in handy if you want to decouple the `NonEmpty` list+construction from the specific names of the fields.+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let make+    : ∀(a : Type) → ∀(head : a) → ∀(tail : List a) → NonEmpty a+    = λ(a : Type) → λ(head : a) → λ(tail : List a) → { head, tail }++let example = assert : make Natural 1 [ 2, 3 ] ≡ { head = 1, tail = [ 2, 3 ] }++in  make
+ dhall-lang/Prelude/NonEmpty/map.dhall view
@@ -0,0 +1,30 @@+--| Transform a `NonEmpty` list by applying a function to each element+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let map+    : ∀(a : Type) → ∀(b : Type) → (a → b) → NonEmpty a → NonEmpty b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → b) →+      λ(xs : NonEmpty a) →+        { head = f xs.head, tail = List/map a b f xs.tail }++let example0 =+        assert+      :   map Natural Bool Natural/even { head = 2, tail = [ 3, 5 ] }+        ≡ { head = True, tail = [ False, False ] }++let example1 =+        assert+      :   map Natural Bool Natural/even { head = 2, tail = [] : List Natural }+        ≡ { head = True, tail = [] : List Bool }++in  map
+ dhall-lang/Prelude/NonEmpty/package.dhall view
@@ -0,0 +1,73 @@+{ Type =+      missing+        sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+    ? ./Type.dhall+, all =+      missing+        sha256:f2f9389d94f4deb5b918b2e50c1093b57e00b37ddd3ab2b43959993b1cb519b6+    ? ./all.dhall+, any =+      missing+        sha256:7662b665840e41b12a28190eec3aaab9201fcb90c00a8ec3666d549e1020992f+    ? ./any.dhall+, concat =+      missing+        sha256:6d55181938c06c6b806877028f6a241912e9c0935d9a10dd958775bf21e0f64d+    ? ./concat.dhall+, concatMap =+      missing+        sha256:fc33fa9449dc8f74dd8c8be379b7b7c4b0433e2b65650370d81d9a7111a590e2+    ? ./concatMap.dhall+, head =+      missing+        sha256:6b9551c97b89fe666d2e03392a4af5e87abfdbdb0aa0e29fc4b3aa1b318474e7+    ? ./head.dhall+, index =+      missing+        sha256:0ba2fcc9227fab10676cd61b47a18d779818a19c16727c7cc4b4c78e114fd663+    ? ./index.dhall+, indexed =+      missing+        sha256:9dae2c1fecd142df837e98769b5bbdd0bfe25c35a93af1064b4e62f9c780ae6b+    ? ./indexed.dhall+, last =+      missing+        sha256:f83115492b6e408d0b662a68440620f7f3df07b56e7ed66dab77a6e65b121250+    ? ./last.dhall+, length =+      missing+        sha256:eef3b857a164487cfdb960e3298c4731970b7a430011289cba35a9ad722ac989+    ? ./length.dhall+, make =+      missing+        sha256:549de393673c4773c80a50ea578ea50d7f2c4c2eda31956e73fabc4e486f3b1e+    ? ./make.dhall+, map =+      missing+        sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+    ? ./map.dhall+, reverse =+      missing+        sha256:a6d810cdd3badffd4e7ca82091609a855cffac900c82d7ff3724463fbc2d5ff2+    ? ./reverse.dhall+, shifted =+      missing+        sha256:36156973d6916aed10cfd8c59be7c019516bf0a2c47b499a17a8ef0611e1c189+    ? ./shifted.dhall+, singleton =+      missing+        sha256:c9197aabe97695f7ca66f7419bf172d806b2c915594a8fc0d2ff6495db496ff2+    ? ./singleton.dhall+, toList =+      missing+        sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+    ? ./toList.dhall+, unzip =+      missing+        sha256:d0b925bea32a29aad5cb48a84e8ef8cff750308afe1dd20b24eca19e4e999abc+    ? ./unzip.dhall+, zip =+      missing+        sha256:073f8b4808b6d1db84964f772f6291e6ea193602163438db43fa282c560c01e4+    ? ./zip.dhall+}
+ dhall-lang/Prelude/NonEmpty/reverse.dhall view
@@ -0,0 +1,35 @@+--| Reverse a `NonEmpty` list+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let List/drop =+        missing+          sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+      ? ../List/drop.dhall++let reverse+    : ∀(a : Type) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(xs : NonEmpty a) →+        let ys = List/reverse a xs.tail++        in  merge+              { Some =+                  λ(y : a) → { head = y, tail = List/drop 1 a ys # [ xs.head ] }+              , None = { head = xs.head, tail = [] : List a }+              }+              (List/head a ys)++let example =+        assert+      :   reverse Natural { head = 0, tail = [ 1, 2 ] }+        ≡ { head = 2, tail = [ 1, 0 ] }++let example1 =+        assert+      :   reverse Natural { head = 0, tail = [] : List Natural }+        ≡ { head = 0, tail = [] : List Natural }++in  reverse
+ dhall-lang/Prelude/NonEmpty/shifted.dhall view
@@ -0,0 +1,101 @@+{-|+Combine a `NonEmpty` list of `NonEmpty` lists, offsetting the `index` of each+element by the number of elements in preceding lists+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ./toList.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let List/shifted =+        missing+          sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+      ? ../List/shifted.dhall++let shifted+    : ∀(a : Type) →+      NonEmpty (NonEmpty { index : Natural, value : a }) →+        NonEmpty { index : Natural, value : a }+    = λ(a : Type) →+      λ(kvss : NonEmpty (NonEmpty { index : Natural, value : a })) →+        { head = kvss.head.head+        , tail =+            List/shifted+              a+              (   [ kvss.head.tail ]+                # List/map+                    (NonEmpty { index : Natural, value : a })+                    (List { index : Natural, value : a })+                    ( λ(kvs : NonEmpty { index : Natural, value : a }) →+                        List/map+                          { index : Natural, value : a }+                          { index : Natural, value : a }+                          ( λ(kv : { index : Natural, value : a }) →+                              { index = kv.index + 1, value = kv.value }+                          )+                          (NonEmpty/toList { index : Natural, value : a } kvs)+                    )+                    kvss.tail+              )+        }++let example0 =+        assert+      :   shifted+            Bool+            { head =+              { head = { index = 0, value = True }+              , tail =+                [ { index = 1, value = True }, { index = 2, value = True } ]+              }+            , tail =+              [ { head = { index = 0, value = False }+                , tail = [ { index = 1, value = False } ]+                }+              , { head = { index = 0, value = True }+                , tail =+                  [ { index = 1, value = True }+                  , { index = 2, value = True }+                  , { index = 3, value = True }+                  ]+                }+              ]+            }+        ≡ { head = { index = 0, value = True }+          , tail =+            [ { index = 1, value = True }+            , { index = 2, value = True }+            , { index = 3, value = False }+            , { index = 4, value = False }+            , { index = 5, value = True }+            , { index = 6, value = True }+            , { index = 7, value = True }+            , { index = 8, value = True }+            ]+          }++let example1 =+        assert+      :   shifted+            Bool+            { head =+              { head = { index = 0, value = True }+              , tail = [] : List { index : Natural, value : Bool }+              }+            , tail = [] : List (NonEmpty { index : Natural, value : Bool })+            }+        ≡ { head = { index = 0, value = True }+          , tail = [] : List { index : Natural, value : Bool }+          }++in  shifted
+ dhall-lang/Prelude/NonEmpty/singleton.dhall view
@@ -0,0 +1,14 @@+--| Create a `NonEmpty` list with just one element+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let singleton+    : ∀(a : Type) → a → NonEmpty a+    = λ(a : Type) → λ(x : a) → { head = x, tail = [] : List a }++let example =+      assert : singleton Natural 2 ≡ { head = 2, tail = [] : List Natural }++in  singleton
+ dhall-lang/Prelude/NonEmpty/toList.dhall view
@@ -0,0 +1,17 @@+--| Convert a `NonEmpty` list into the equivalent `List`+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let toList+    : ∀(a : Type) → NonEmpty a → List a+    = λ(a : Type) → λ(xs : NonEmpty a) → [ xs.head ] # xs.tail++let example0 =+      assert : toList Natural { head = 2, tail = [ 3, 5 ] } ≡ [ 2, 3, 5 ]++let example1 =+      assert : toList Natural { head = 2, tail = [] : List Natural } ≡ [ 2 ]++in  toList
+ dhall-lang/Prelude/NonEmpty/unzip.dhall view
@@ -0,0 +1,58 @@+--| Unzip a `NonEmpty` list into two separate `NonEmpty` lists+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let NonEmpty/map =+        missing+          sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+      ? ./map.dhall++let unzip+    : ∀(a : Type) →+      ∀(b : Type) →+      NonEmpty { _1 : a, _2 : b } →+        { _1 : NonEmpty a, _2 : NonEmpty b }+    = λ(a : Type) →+      λ(b : Type) →+      λ(xs : NonEmpty { _1 : a, _2 : b }) →+        { _1 =+            NonEmpty/map+              { _1 : a, _2 : b }+              a+              (λ(x : { _1 : a, _2 : b }) → x._1)+              xs+        , _2 =+            NonEmpty/map+              { _1 : a, _2 : b }+              b+              (λ(x : { _1 : a, _2 : b }) → x._2)+              xs+        }++let example0 =+        assert+      :   unzip+            Text+            Bool+            { head = { _1 = "ABC", _2 = True }+            , tail = [ { _1 = "DEF", _2 = False }, { _1 = "GHI", _2 = True } ]+            }+        ≡ { _1 = { head = "ABC", tail = [ "DEF", "GHI" ] }+          , _2 = { head = True, tail = [ False, True ] }+          }++let example1 =+        assert+      :   unzip+            Text+            Bool+            { head = { _1 = "ABC", _2 = True }+            , tail = [] : List { _1 : Text, _2 : Bool }+            }+        ≡ { _1 = { head = "ABC", tail = [] : List Text }+          , _2 = { head = True, tail = [] : List Bool }+          }++in  unzip
+ dhall-lang/Prelude/NonEmpty/zip.dhall view
@@ -0,0 +1,63 @@+{-|+Zip two `NonEmpty` lists into a single `NonEmpty`++The resulting `NonEmpty` will have the length of the shortest of its arguments.+-}+let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ./Type.dhall++let List/zip =+        missing+          sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+      ? ../List/zip.dhall++let zip+    : ∀(a : Type) →+      NonEmpty a →+      ∀(b : Type) →+      NonEmpty b →+        NonEmpty { _1 : a, _2 : b }+    = λ(a : Type) →+      λ(xs : NonEmpty a) →+      λ(b : Type) →+      λ(ys : NonEmpty b) →+        { head = { _1 = xs.head, _2 = ys.head }+        , tail = List/zip a xs.tail b ys.tail+        }++let example0 =+        assert+      :   zip+            Text+            { head = "ABC", tail = [ "DEF", "GHI" ] }+            Natural+            { head = 1, tail = [ 2, 3 ] }+        ≡ { head = { _1 = "ABC", _2 = 1 }+          , tail = [ { _1 = "DEF", _2 = 2 }, { _1 = "GHI", _2 = 3 } ]+          }++let example1 =+        assert+      :   zip+            Text+            { head = "ABC", tail = [ "DEF" ] }+            Bool+            { head = True, tail = [] : List Bool }+        ≡ { head = { _1 = "ABC", _2 = True }+          , tail = [] : List { _1 : Text, _2 : Bool }+          }++let example2 =+        assert+      :   zip+            Text+            { head = "ABC", tail = [] : List Text }+            Natural+            { head = 1, tail = [ 2 ] }+        ≡ { head = { _1 = "ABC", _2 = 1 }+          , tail = [] : List { _1 : Text, _2 : Natural }+          }++in  zip
+ dhall-lang/Prelude/Operator/package.dhall view
@@ -0,0 +1,85 @@+{-+Note: This package does not use one file per function because the operator+names contain symbols such as `*` that may cause problems.+-}+let {-+        `+` m n++    computes `m + n`+    -} `+`+    : Natural → Natural → Natural+    = λ(m : Natural) → λ(n : Natural) → m + n++let example1 = assert : `+` 2 1 ≡ 3++let {-+        `*` m n++    computes `m * n`+    -} `*`+    : Natural → Natural → Natural+    = λ(m : Natural) → λ(n : Natural) → m * n++let example2 = assert : `*` 21 2 ≡ 42++let {-+        `++` m n++    computes `m ++ n`+    -} `++`+    : Text → Text → Text+    = λ(m : Text) → λ(n : Text) → m ++ n++let example3 = assert : `++` "Hello" "Dhall" ≡ "HelloDhall"++let {-+        `#` Type m n++    computes `m # n`+    -} `#`+    : ∀(type : Type) → List type → List type → List type+    = λ(type : Type) → λ(m : List type) → λ(n : List type) → m # n++let example4 = assert : `#` Natural [ 1, 2 ] [ 3 ] ≡ [ 1, 2, 3 ]++let {-+        `==` m n++    computes `m == n`+    -} `==`+    : Bool → Bool → Bool+    = λ(m : Bool) → λ(n : Bool) → m == n++let example5 = assert : `==` True False ≡ False++let {-+        `!=` m n++    computes `m != n`+    -} `!=`+    : Bool → Bool → Bool+    = λ(m : Bool) → λ(n : Bool) → m != n++let example6 = assert : `!=` True False ≡ True++let {-+        `&&` m n++    computes `m && n`+    -} `&&`+    : Bool → Bool → Bool+    = λ(m : Bool) → λ(n : Bool) → m && n++let example7 = assert : `&&` False True ≡ False++let {-+        `||` m n++    computes `m || n`+    -} `||`+    : Bool → Bool → Bool+    = λ(m : Bool) → λ(n : Bool) → m || n++let example8 = assert : `||` False True ≡ True++in  { `+`, `*`, `++`, `#`, `==`, `!=`, `&&`, `||` }
+ dhall-lang/Prelude/Optional/all view
@@ -0,0 +1,3 @@+  missing+    sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+? ./all.dhall
+ dhall-lang/Prelude/Optional/all.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `False` if the supplied function returns `False` for a present element+and `True` otherwise:+-}+let all+    : ∀(a : Type) → (a → Bool) → Optional a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : Optional a) →+        merge { Some = f, None = True } xs++let example0 = assert : all Natural Natural/even (Some 3) ≡ False++let example1 = assert : all Natural Natural/even (None Natural) ≡ True++in  all
+ dhall-lang/Prelude/Optional/any view
@@ -0,0 +1,3 @@+  missing+    sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+? ./any.dhall
+ dhall-lang/Prelude/Optional/any.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `True` if the supplied function returns `True` for a present element and+`False` otherwise+-}+let any+    : ∀(a : Type) → (a → Bool) → Optional a → Bool+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : Optional a) →+        merge { Some = f, None = False } xs++let example0 = assert : any Natural Natural/even (Some 2) ≡ True++let example1 = assert : any Natural Natural/even (None Natural) ≡ False++in  any
+ dhall-lang/Prelude/Optional/build view
@@ -0,0 +1,3 @@+  missing+    sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+? ./build.dhall
+ dhall-lang/Prelude/Optional/build.dhall view
@@ -0,0 +1,41 @@+--| `build` is the inverse of `fold`+let build+    : ∀(a : Type) →+      ( ∀(optional : Type) →+        ∀(some : a → optional) →+        ∀(none : optional) →+          optional+      ) →+        Optional a+    = λ(a : Type) →+      λ ( build+        : ∀(optional : Type) →+          ∀(some : a → optional) →+          ∀(none : optional) →+            optional+        ) →+        build (Optional a) (λ(x : a) → Some x) (None a)++let example0 =+        assert+      :   build+            Natural+            ( λ(optional : Type) →+              λ(some : Natural → optional) →+              λ(none : optional) →+                some 1+            )+        ≡ Some 1++let example1 =+        assert+      :   build+            Natural+            ( λ(optional : Type) →+              λ(some : Natural → optional) →+              λ(none : optional) →+                none+            )+        ≡ None Natural++in  build
+ dhall-lang/Prelude/Optional/concat view
@@ -0,0 +1,3 @@+  missing+    sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+? ./concat.dhall
+ dhall-lang/Prelude/Optional/concat.dhall view
@@ -0,0 +1,14 @@+--| Flatten two `Optional` layers into a single `Optional` layer+let concat+    : ∀(a : Type) → Optional (Optional a) → Optional a+    = λ(a : Type) →+      λ(x : Optional (Optional a)) →+        merge { Some = λ(y : Optional a) → y, None = None a } x++let example0 = assert : concat Natural (Some (Some 1)) ≡ Some 1++let example1 = assert : concat Natural (Some (None Natural)) ≡ None Natural++let example2 = assert : concat Natural (None (Optional Natural)) ≡ None Natural++in  concat
+ dhall-lang/Prelude/Optional/concatMap.dhall view
@@ -0,0 +1,23 @@+--| Transform the value with a function and flatten the resulting `Optional`+let concatMap+    : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → Optional a → Optional b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+      λ(o : Optional a) →+        merge { Some = f, None = None b } o++let exampleFun+    : Natural → Optional Natural+    = λ(n : Natural) → if Natural/even n then Some (n + 1) else None Natural++let example0 =+      assert : concatMap Natural Natural exampleFun (Some 1) ≡ None Natural++let example1 = assert : concatMap Natural Natural exampleFun (Some 2) ≡ Some 3++let example2 =+        assert+      : concatMap Natural Natural exampleFun (None Natural) ≡ None Natural++in  concatMap
+ dhall-lang/Prelude/Optional/default view
@@ -0,0 +1,3 @@+  missing+    sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+? ./default.dhall
+ dhall-lang/Prelude/Optional/default.dhall view
@@ -0,0 +1,13 @@+--| Unpack an `Optional`, returning the default when it's `None`.+let default+    : ∀(a : Type) → a → Optional a → a+    = λ(a : Type) →+      λ(default : a) →+      λ(o : Optional a) →+        merge { Some = λ(x : a) → x, None = default } o++let example0 = assert : default Bool False (None Bool) ≡ False++let example1 = assert : default Bool False (Some True) ≡ True++in  default
+ dhall-lang/Prelude/Optional/equal.dhall view
@@ -0,0 +1,24 @@+let Optional/fold =+        missing+          sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+      ? ./fold.dhall++let Optional/null =+        missing+          sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+      ? ./null.dhall++let equal+    : forall (a : Type) -> (a -> a -> Bool) -> Optional a -> Optional a -> Bool+    = \(a : Type) ->+      \(compare : a -> a -> Bool) ->+      \(ox : Optional a) ->+      \(oy : Optional a) ->+        Optional/fold+          a+          ox+          Bool+          (\(x : a) -> Optional/fold a oy Bool (compare x) False)+          (Optional/null a oy)++in  equal
+ dhall-lang/Prelude/Optional/filter view
@@ -0,0 +1,3 @@+  missing+    sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+? ./filter.dhall
+ dhall-lang/Prelude/Optional/filter.dhall view
@@ -0,0 +1,29 @@+--| Only keep an `Optional` element if the supplied function returns `True`+let filter+    : ∀(a : Type) → (a → Bool) → Optional a → Optional a+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : Optional a) →+        ( λ(a : Type) →+          λ ( build+            : ∀(optional : Type) →+              ∀(some : a → optional) →+              ∀(none : optional) →+                optional+            ) →+            build (Optional a) (λ(x : a) → Some x) (None a)+        )+          a+          ( λ(optional : Type) →+            λ(some : a → optional) →+            λ(none : optional) →+              merge+                { Some = λ(x : a) → if f x then some x else none, None = none }+                xs+          )++let example0 = assert : filter Natural Natural/even (Some 2) ≡ Some 2++let example1 = assert : filter Natural Natural/odd (Some 2) ≡ None Natural++in  filter
+ dhall-lang/Prelude/Optional/fold view
@@ -0,0 +1,3 @@+  missing+    sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+? ./fold.dhall
+ dhall-lang/Prelude/Optional/fold.dhall view
@@ -0,0 +1,20 @@+--| `fold` is the primitive function for consuming `Optional` values+let fold+    : ∀(a : Type) →+      Optional a →+      ∀(optional : Type) →+      ∀(some : a → optional) →+      ∀(none : optional) →+        optional+    = λ(a : Type) →+      λ(o : Optional a) →+      λ(optional : Type) →+      λ(some : a → optional) →+      λ(none : optional) →+        merge { Some = some, None = none } o++let example0 = assert : fold Natural (Some 2) Text Natural/show "0" ≡ "2"++let example1 = assert : fold Natural (None Natural) Text Natural/show "0" ≡ "0"++in  fold
+ dhall-lang/Prelude/Optional/head view
@@ -0,0 +1,3 @@+  missing+    sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+? ./head.dhall
+ dhall-lang/Prelude/Optional/head.dhall view
@@ -0,0 +1,24 @@+--| Returns the first non-empty `Optional` value in a `List`+let head+    : ∀(a : Type) → List (Optional a) → Optional a+    = λ(a : Type) →+      λ(xs : List (Optional a)) →+        List/fold+          (Optional a)+          xs+          (Optional a)+          ( λ(l : Optional a) →+            λ(r : Optional a) →+              merge { Some = λ(x : a) → Some x, None = r } l+          )+          (None a)++let example0 = assert : head Natural [ None Natural, Some 1, Some 2 ] ≡ Some 1++let example1 =+      assert : head Natural [ None Natural, None Natural ] ≡ None Natural++let example2 =+      assert : head Natural ([] : List (Optional Natural)) ≡ None Natural++in  head
+ dhall-lang/Prelude/Optional/last view
@@ -0,0 +1,3 @@+  missing+    sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+? ./last.dhall
+ dhall-lang/Prelude/Optional/last.dhall view
@@ -0,0 +1,24 @@+--| Returns the last non-empty `Optional` value in a `List`+let last+    : ∀(a : Type) → List (Optional a) → Optional a+    = λ(a : Type) →+      λ(xs : List (Optional a)) →+        List/fold+          (Optional a)+          xs+          (Optional a)+          ( λ(l : Optional a) →+            λ(r : Optional a) →+              merge { Some = λ(x : a) → Some x, None = l } r+          )+          (None a)++let example0 = assert : last Natural [ None Natural, Some 1, Some 2 ] ≡ Some 2++let example1 =+      assert : last Natural [ None Natural, None Natural ] ≡ None Natural++let example2 =+      assert : last Natural ([] : List (Optional Natural)) ≡ None Natural++in  last
+ dhall-lang/Prelude/Optional/length view
@@ -0,0 +1,3 @@+  missing+    sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+? ./length.dhall
+ dhall-lang/Prelude/Optional/length.dhall view
@@ -0,0 +1,14 @@+{-|+Returns `1` if the `Optional` value is present and `0` if the value is absent+-}+let length+    : ∀(a : Type) → Optional a → Natural+    = λ(a : Type) →+      λ(xs : Optional a) →+        merge { Some = λ(_ : a) → 1, None = 0 } xs++let example0 = assert : length Natural (Some 2) ≡ 1++let example1 = assert : length Natural (None Natural) ≡ 0++in  length
+ dhall-lang/Prelude/Optional/map view
@@ -0,0 +1,3 @@+  missing+    sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+? ./map.dhall
+ dhall-lang/Prelude/Optional/map.dhall view
@@ -0,0 +1,14 @@+--| Transform an `Optional` value with a function+let map+    : ∀(a : Type) → ∀(b : Type) → (a → b) → Optional a → Optional b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → b) →+      λ(o : Optional a) →+        merge { Some = λ(x : a) → Some (f x), None = None b } o++let example0 = assert : map Natural Bool Natural/even (Some 3) ≡ Some False++let example1 = assert : map Natural Bool Natural/even (None Natural) ≡ None Bool++in  map
+ dhall-lang/Prelude/Optional/null view
@@ -0,0 +1,3 @@+  missing+    sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+? ./null.dhall
+ dhall-lang/Prelude/Optional/null.dhall view
@@ -0,0 +1,12 @@+--| Returns `True` if the `Optional` value is absent and `False` if present+let null+    : ∀(a : Type) → Optional a → Bool+    = λ(a : Type) →+      λ(xs : Optional a) →+        merge { Some = λ(_ : a) → False, None = True } xs++let example0 = assert : null Natural (Some 2) ≡ False++let example1 = assert : null Natural (None Natural) ≡ True++in  null
+ dhall-lang/Prelude/Optional/package.dhall view
@@ -0,0 +1,65 @@+{ all =+      missing+        sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+    ? ./all.dhall+, any =+      missing+        sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+    ? ./any.dhall+, build =+      missing+        sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+    ? ./build.dhall+, concat =+      missing+        sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+    ? ./concat.dhall+, concatMap =+      missing+        sha256:c06ae93e900a99299c9b4ec4912ca5395a0103ea88292205b08dd7e345632818+    ? ./concatMap.dhall+, default =+      missing+        sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+    ? ./default.dhall+, equal =+      missing+        sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+    ? ./equal.dhall+, filter =+      missing+        sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+    ? ./filter.dhall+, fold =+      missing+        sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+    ? ./fold.dhall+, head =+      missing+        sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+    ? ./head.dhall+, last =+      missing+        sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+    ? ./last.dhall+, length =+      missing+        sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+    ? ./length.dhall+, map =+      missing+        sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+    ? ./map.dhall+, null =+      missing+        sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+    ? ./null.dhall+, toList =+      missing+        sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+    ? ./toList.dhall+, unzip =+      missing+        sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+    ? ./unzip.dhall+}
+ dhall-lang/Prelude/Optional/toList view
@@ -0,0 +1,3 @@+  missing+    sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+? ./toList.dhall
+ dhall-lang/Prelude/Optional/toList.dhall view
@@ -0,0 +1,12 @@+--| Convert an `Optional` value into the equivalent `List`+let toList+    : ∀(a : Type) → Optional a → List a+    = λ(a : Type) →+      λ(o : Optional a) →+        merge { Some = λ(x : a) → [ x ] : List a, None = [] : List a } o++let example0 = assert : toList Natural (Some 1) ≡ [ 1 ]++let example1 = assert : toList Natural (None Natural) ≡ ([] : List Natural)++in  toList
+ dhall-lang/Prelude/Optional/unzip view
@@ -0,0 +1,3 @@+  missing+    sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+? ./unzip.dhall
+ dhall-lang/Prelude/Optional/unzip.dhall view
@@ -0,0 +1,30 @@+--| Unzip an `Optional` value into two separate `Optional` values+let unzip+    : ∀(a : Type) →+      ∀(b : Type) →+      Optional { _1 : a, _2 : b } →+        { _1 : Optional a, _2 : Optional b }+    = λ(a : Type) →+      λ(b : Type) →+      λ(xs : Optional { _1 : a, _2 : b }) →+        { _1 =+            merge+              { Some = λ(x : { _1 : a, _2 : b }) → Some x._1, None = None a }+              xs+        , _2 =+            merge+              { Some = λ(x : { _1 : a, _2 : b }) → Some x._2, None = None b }+              xs+        }++let example0 =+        assert+      :   unzip Text Bool (Some { _1 = "ABC", _2 = True })+        ≡ { _1 = Some "ABC", _2 = Some True }++let example1 =+        assert+      :   unzip Text Bool (None { _1 : Text, _2 : Bool })+        ≡ { _1 = None Text, _2 = None Bool }++in  unzip
+ dhall-lang/Prelude/Text/concat view
@@ -0,0 +1,3 @@+  missing+    sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+? ./concat.dhall
+ dhall-lang/Prelude/Text/concat.dhall view
@@ -0,0 +1,11 @@+--| Concatenate all the `Text` values in a `List`+let concat+    : List Text → Text+    = λ(xs : List Text) →+        List/fold Text xs Text (λ(x : Text) → λ(y : Text) → x ++ y) ""++let example0 = assert : concat [ "ABC", "DEF", "GHI" ] ≡ "ABCDEFGHI"++let example1 = assert : concat ([] : List Text) ≡ ""++in  concat
+ dhall-lang/Prelude/Text/concatMap view
@@ -0,0 +1,3 @@+  missing+    sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+? ./concatMap.dhall
+ dhall-lang/Prelude/Text/concatMap.dhall view
@@ -0,0 +1,22 @@+--| Transform each value in a `List` into `Text` and concatenate the result+let concatMap+    : ∀(a : Type) → (a → Text) → List a → Text+    = λ(a : Type) →+      λ(f : a → Text) →+      λ(xs : List a) →+        List/fold a xs Text (λ(x : a) → λ(y : Text) → f x ++ y) ""++let example0 =+        assert+      :   concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]+        ≡ "0 1 2 "++let example1 =+        assert+      :   concatMap+            Natural+            (λ(n : Natural) → "${Natural/show n} ")+            ([] : List Natural)+        ≡ ""++in  concatMap
+ dhall-lang/Prelude/Text/concatMapSep view
@@ -0,0 +1,3 @@+  missing+    sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+? ./concatMapSep.dhall
+ dhall-lang/Prelude/Text/concatMapSep.dhall view
@@ -0,0 +1,38 @@+{-|+Transform each value in a `List` to `Text` and then concatenate them with a+separator in between each value+-}+let Status = < Empty | NonEmpty : Text >++let concatMapSep+    : ∀(separator : Text) → ∀(a : Type) → (a → Text) → List a → Text+    = λ(separator : Text) →+      λ(a : Type) →+      λ(f : a → Text) →+      λ(elements : List a) →+        let status =+              List/fold+                a+                elements+                Status+                ( λ(x : a) →+                  λ(status : Status) →+                    merge+                      { Empty = Status.NonEmpty (f x)+                      , NonEmpty =+                          λ(result : Text) →+                            Status.NonEmpty (f x ++ separator ++ result)+                      }+                      status+                )+                Status.Empty++        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 =+      assert : concatMapSep ", " Natural Natural/show [ 0, 1, 2 ] ≡ "0, 1, 2"++let example1 =+      assert : concatMapSep ", " Natural Natural/show ([] : List Natural) ≡ ""++in  concatMapSep
+ dhall-lang/Prelude/Text/concatSep view
@@ -0,0 +1,3 @@+  missing+    sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+? ./concatSep.dhall
+ dhall-lang/Prelude/Text/concatSep.dhall view
@@ -0,0 +1,31 @@+--| Concatenate a `List` of `Text` values with a separator in between each value+let Status = < Empty | NonEmpty : Text >++let concatSep+    : ∀(separator : Text) → ∀(elements : List Text) → Text+    = λ(separator : Text) →+      λ(elements : List Text) →+        let status =+              List/fold+                Text+                elements+                Status+                ( λ(element : Text) →+                  λ(status : Status) →+                    merge+                      { Empty = Status.NonEmpty element+                      , NonEmpty =+                          λ(result : Text) →+                            Status.NonEmpty (element ++ separator ++ result)+                      }+                      status+                )+                Status.Empty++        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 = assert : concatSep ", " [ "ABC", "DEF", "GHI" ] ≡ "ABC, DEF, GHI"++let example1 = assert : concatSep ", " ([] : List Text) ≡ ""++in  concatSep
+ dhall-lang/Prelude/Text/default view
@@ -0,0 +1,3 @@+  missing+    sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+? ./default.dhall
+ dhall-lang/Prelude/Text/default.dhall view
@@ -0,0 +1,10 @@+--| Unwrap an `Optional` `Text` value, defaulting `None` to `""`+let default+    : Optional Text → Text+    = λ(o : Optional Text) → merge { Some = λ(t : Text) → t, None = "" } o++let example0 = assert : default (Some "ABC") ≡ "ABC"++let example1 = assert : default (None Text) ≡ ""++in  default
+ dhall-lang/Prelude/Text/defaultMap view
@@ -0,0 +1,3 @@+  missing+    sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+? ./defaultMap.dhall
+ dhall-lang/Prelude/Text/defaultMap.dhall view
@@ -0,0 +1,13 @@+--| Transform the value in an `Optional` into `Text`, defaulting `None` to `""`+let defaultMap+    : ∀(a : Type) → (a → Text) → Optional a → Text+    = λ(a : Type) →+      λ(f : a → Text) →+      λ(o : Optional a) →+        merge { Some = f, None = "" } o++let example0 = assert : defaultMap Natural Natural/show (Some 0) ≡ "0"++let example1 = assert : defaultMap Natural Natural/show (None Natural) ≡ ""++in  defaultMap
+ dhall-lang/Prelude/Text/lowerASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Lowercase all ASCII characters++Note that this will also lowercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let lowerASCII+    : Text → Text+    = List/fold+        (Text → Text)+        [ Text/replace "A" "a"+        , Text/replace "B" "b"+        , Text/replace "C" "c"+        , Text/replace "D" "d"+        , Text/replace "E" "e"+        , Text/replace "F" "f"+        , Text/replace "G" "g"+        , Text/replace "H" "h"+        , Text/replace "I" "i"+        , Text/replace "J" "j"+        , Text/replace "K" "k"+        , Text/replace "L" "l"+        , Text/replace "M" "m"+        , Text/replace "N" "n"+        , Text/replace "O" "o"+        , Text/replace "P" "p"+        , Text/replace "Q" "q"+        , Text/replace "R" "r"+        , Text/replace "S" "s"+        , Text/replace "T" "t"+        , Text/replace "U" "u"+        , Text/replace "V" "v"+        , Text/replace "W" "w"+        , Text/replace "X" "x"+        , Text/replace "Y" "y"+        , Text/replace "Z" "z"+        ]+        Text+        (λ(replacement : Text → Text) → replacement)++let example0 = assert : lowerASCII "ABCdef" ≡ "abcdef"++let -- This does not lowercase precomposed Unicode characters+    --+    -- • The `Á` in the following example is U+00C1+    example1 =+      assert : lowerASCII "Á" ≡ "Á"++let -- … but this does lowercase decomposed Unicode characters+    --+    -- • The `Á` in the following example is U+0041 U+0301+    -- • The `á` in the following example is U+0061 U+0301+    example1 =+      assert : lowerASCII "Á" ≡ "á"++in  lowerASCII
+ dhall-lang/Prelude/Text/package.dhall view
@@ -0,0 +1,53 @@+{ concat =+      missing+        sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+    ? ./concat.dhall+, concatMap =+      missing+        sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+    ? ./concatMap.dhall+, concatMapSep =+      missing+        sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+    ? ./concatMapSep.dhall+, concatSep =+      missing+        sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+    ? ./concatSep.dhall+, default =+      missing+        sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+    ? ./default.dhall+, defaultMap =+      missing+        sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+    ? ./defaultMap.dhall+, lowerASCII =+      missing+        sha256:26b076651120b907e869396bd3dc16271f2e12433062b2f26f296968a69515e7+    ? ./lowerASCII.dhall+, replace =+      missing+        sha256:7d132df0e091a43817bba8afa06d1bb487ee51c091430404ad6f8c78bc0328a6+    ? ./replace.dhall+, replicate =+      missing+        sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+    ? ./replicate.dhall+, shell-escape =+      missing+        sha256:d53521b3f478cb18a7d63730bc0e3153c2124b70d6ac9a1f610ce7db67cfc7a2+    ? ./shell-escape.dhall+, show =+      missing+        sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+    ? ./show.dhall+, spaces =+      missing+        sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+    ? ./spaces.dhall+, upperASCII =+      missing+        sha256:45ae4fbd814b0474e65c28a4ee92b23b979892fa5bb73730bc99675ae790ca29+    ? ./upperASCII.dhall+}
+ dhall-lang/Prelude/Text/replace.dhall view
@@ -0,0 +1,14 @@+{-+Replace a section of `Text` with another inside a `Text` literal.+-}+let replace+    : ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text+    = Text/replace++let example0 = assert : replace "-" "_" "foo-bar" ≡ "foo_bar"++let example1 = assert : replace "💣" "💥" "💣💣💣" ≡ "💥💥💥"++let example2 = assert : replace "👨" "👩" "👨‍👩‍👧‍👦" ≡ "👩‍👩‍👧‍👦"++in  replace
+ dhall-lang/Prelude/Text/replicate view
@@ -0,0 +1,3 @@+  missing+    sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+? ./replicate.dhall
+ dhall-lang/Prelude/Text/replicate.dhall view
@@ -0,0 +1,20 @@+--| Build a Text by copying the given Text the specified number of times+let concat =+        missing+          sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+      ? ./concat.dhall++let List/replicate =+        missing+          sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+      ? ../List/replicate.dhall++let replicate+    : Natural → Text → Text+    = λ(num : Natural) → λ(text : Text) → concat (List/replicate num Text text)++let example0 = assert : replicate 3 "foo" ≡ "foofoofoo"++let property = λ(text : Text) → assert : replicate 0 text ≡ ""++in  replicate
+ dhall-lang/Prelude/Text/shell-escape.dhall view
@@ -0,0 +1,16 @@+{-|+Escape a Text value such that it can be used safely in shells.+The escaping is done by replacing all `'` with `'"'"'` and wraps that string in+single quotes.++This works for all POSIX-compliant shells and some other shells like csh.+-}+let shell-escape+    : Text -> Text+    = \(xs : Text) -> "'${Text/replace "'" "'\"'\"'" xs}'"++let example0 = assert : shell-escape "foo" === "'foo'"++let example1 = assert : shell-escape "foo'bar" === "'foo'\"'\"'bar'"++in  shell-escape
+ dhall-lang/Prelude/Text/show view
@@ -0,0 +1,3 @@+  missing+    sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+? ./show.dhall
+ dhall-lang/Prelude/Text/show.dhall view
@@ -0,0 +1,19 @@+{-+Render a `Text` literal as its own representation as Dhall source code (i.e. a+double-quoted string literal)+-}+let show+    : Text → Text+    = Text/show++let example0 = assert : show "ABC" ≡ "\"ABC\""++let example1 =+        assert+      :   show+            ''+            ${"\u0000"} $ \ +            ${" "}☺''+        ≡ "\"\\u0000 \\u0024 \\\\ \\n ☺\""++in  show
+ dhall-lang/Prelude/Text/spaces view
@@ -0,0 +1,3 @@+  missing+    sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+? ./spaces.dhall
+ dhall-lang/Prelude/Text/spaces.dhall view
@@ -0,0 +1,20 @@+{-|+Return a Text with the number of spaces specified.++This function is particularly helpful when trying to generate Text where+whitespace is significant, i.e. with nested indentation.+-}+let replicate =+        missing+          sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+      ? ./replicate.dhall++let spaces+    : Natural → Text+    = λ(a : Natural) → replicate a " "++let example0 = assert : spaces 1 ≡ " "++let example1 = assert : spaces 0 ≡ ""++in  spaces
+ dhall-lang/Prelude/Text/upperASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Uppercase all ASCII characters++Note that this will also uppercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let upperASCII+    : Text → Text+    = List/fold+        (Text → Text)+        [ Text/replace "a" "A"+        , Text/replace "b" "B"+        , Text/replace "c" "C"+        , Text/replace "d" "D"+        , Text/replace "e" "E"+        , Text/replace "f" "F"+        , Text/replace "g" "G"+        , Text/replace "h" "H"+        , Text/replace "i" "I"+        , Text/replace "j" "J"+        , Text/replace "k" "K"+        , Text/replace "l" "L"+        , Text/replace "m" "M"+        , Text/replace "n" "N"+        , Text/replace "o" "O"+        , Text/replace "p" "P"+        , Text/replace "q" "Q"+        , Text/replace "r" "R"+        , Text/replace "s" "S"+        , Text/replace "t" "T"+        , Text/replace "u" "U"+        , Text/replace "v" "V"+        , Text/replace "w" "W"+        , Text/replace "x" "X"+        , Text/replace "y" "Y"+        , Text/replace "z" "Z"+        ]+        Text+        (λ(replacement : Text → Text) → replacement)++let example0 = assert : upperASCII "ABCdef" ≡ "ABCDEF"++let -- This does not uppercase precomposed Unicode characters+    --+    -- • The `á` in the following example is U+00E1+    example1 =+      assert : upperASCII "á" ≡ "á"++let -- … but this does uppercase decomposed Unicode characters+    --+    -- • The `Á` in the following example is U+0041 U+0301+    -- • The `á` in the following example is U+0061 U+0301+    example1 =+      assert : upperASCII "á" ≡ "Á"++in  upperASCII
+ dhall-lang/Prelude/Time/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:8cabfe35dd0ee25ca65708105e860cbf4b789e0d73134aa905580799e2a46719+    ? ./show.dhall+}
+ dhall-lang/Prelude/Time/show.dhall view
@@ -0,0 +1,15 @@+{-+Render a `Time` as `Text` using the same representation as Dhall source code+(i.e. `hh:mm:ss`)+-}+let show+    : Time → Text+    = Time/show++let example0 = assert : show 03:15:47.90 ≡ "03:15:47.90"++let example1 = assert : show 00:00:00 ≡ "00:00:00"++let example2 = assert : show 11:59:59 ≡ "11:59:59"++in  show
+ dhall-lang/Prelude/TimeZone/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:d183361f1c4c656bad3b170ec8b8d6705f564faebf94e4ef10c76061104ff061+    ? ./show.dhall+}
+ dhall-lang/Prelude/TimeZone/show.dhall view
@@ -0,0 +1,15 @@+{-+Render a `TimeZone` as `Text` using the same representation as Dhall source code+(i.e. `±HH:MM`)+-}+let show+    : TimeZone → Text+    = TimeZone/show++let example0 = assert : show +07:00 ≡ "+07:00"++let example1 = assert : show +00:00 ≡ "+00:00"++let example2 = assert : show -05:00 ≡ "-05:00"++in  show
+ dhall-lang/Prelude/XML/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+? ./Type.dhall
+ dhall-lang/Prelude/XML/Type.dhall view
@@ -0,0 +1,65 @@+{-|+Dhall encoding of an arbitrary XML element++For example, the following XML element:++```+<foo n="1"><bar>baz</bar></foo>+```++... corresponds to the following Dhall expression:+++```+λ(XML : Type)+ → λ ( xml+     : { text :+           Text → XML+       , rawText :+           Text → XML+       , element :+             { attributes :+                 List { mapKey : Text, mapValue : Text }+             , content :+                 List XML+             , name :+                 Text+             }+           → XML+       }+     )+ → xml.element+   { attributes =+       [ { mapKey = "n", mapValue = "1" } ]+   , content =+       [ xml.element+         { attributes =+             [] : List { mapKey : Text, mapValue : Text }+         , content =+             [ xml.text "baz" ]+         , name =+             "bar"+         }+       ]+   , name =+       "foo"+   }+```+-}+let XML/Type+    : Type+    = ∀(XML : Type) →+      ∀ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        XML++in  XML/Type
+ dhall-lang/Prelude/XML/attribute view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ./attribute.dhall
+ dhall-lang/Prelude/XML/attribute.dhall view
@@ -0,0 +1,6 @@+--| Builds a key-value record with a Text key and value.+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ dhall-lang/Prelude/XML/element view
@@ -0,0 +1,3 @@+  missing+    sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+? ./element.dhall
+ dhall-lang/Prelude/XML/element.dhall view
@@ -0,0 +1,59 @@+{-|+Create an XML element value.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "foo"+      , attributes = XML.emptyAttributes+      , content =+          [ XML.leaf { name = "bar", attributes = [ XML.attribute "n" "1" ] }+          , XML.leaf { name = "baz", attributes = [ XML.attribute "n" "2" ] }+          ]+      }+    )++= "<foo><bar n=\"1\"/><baz n=\"2\"/></foo>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let Args =+        { attributes : List { mapKey : Text, mapValue : Text }+        , name : Text+        , content : List XML+        }+      : Type++let element+    : Args → XML+    = λ(elem : Args) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.element+          { attributes = elem.attributes+          , name = elem.name+          , content = List/map XML@1 XML (λ(x : XML@1) → x XML xml) elem.content+          }++in  element
+ dhall-lang/Prelude/XML/emptyAttributes view
@@ -0,0 +1,3 @@+  missing+    sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+? ./emptyAttributes.dhall
+ dhall-lang/Prelude/XML/emptyAttributes.dhall view
@@ -0,0 +1,2 @@+--| Create an empty XML attribute List.+[] : List { mapKey : Text, mapValue : Text }
+ dhall-lang/Prelude/XML/leaf view
@@ -0,0 +1,3 @@+  missing+    sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506+? ./leaf.dhall
+ dhall-lang/Prelude/XML/leaf.dhall view
@@ -0,0 +1,30 @@+{-|+Create an XML element value without child elements.++```+let XML = ./package.dhall++in  XML.render (XML.leaf { name = "foobar", attributes = XML.emptyAttributes })++= "<foobar/>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let element =+        missing+          sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+      ? ./element.dhall++let leaf+    : { attributes : List { mapKey : Text, mapValue : Text }, name : Text } →+        XML+    = λ ( elem+        : { attributes : List { mapKey : Text, mapValue : Text }, name : Text }+        ) →+        element (elem ⫽ { content = [] : List XML })++in  leaf
+ dhall-lang/Prelude/XML/package.dhall view
@@ -0,0 +1,33 @@+{ Type =+      missing+        sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+    ? ./Type.dhall+, attribute =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./attribute.dhall+, render =+      missing+        sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66+    ? ./render.dhall+, element =+      missing+        sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+    ? ./element.dhall+, leaf =+      missing+        sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506+    ? ./leaf.dhall+, text =+      missing+        sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+    ? ./text.dhall+, rawText =+      missing+        sha256:2af9d72c151677d4110039e361b7e9faaf2947e6c9d29aa72aea351ad797e05d+    ? ./rawText.dhall+, emptyAttributes =+      missing+        sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+    ? ./emptyAttributes.dhall+}
+ dhall-lang/Prelude/XML/rawText.dhall view
@@ -0,0 +1,40 @@+{-|+Create a Text value to be inserted into an XML element as content with no+character escaping.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "location"+      , attributes = XML.emptyAttributes+      , content = [ XML.rawText "<bar n=\"1\"/>" ]+      }+    )+= "<foo><bar n=\"1\"/></foo>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let rawText+    : Text → XML+    = λ(d : Text) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.rawText d++in  rawText
+ dhall-lang/Prelude/XML/render view
@@ -0,0 +1,3 @@+  missing+    sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66+? ./render.dhall
+ dhall-lang/Prelude/XML/render.dhall view
@@ -0,0 +1,140 @@+{-|+Render an `XML` value as `Text`++For indentation and schema validation, see the `xmllint` utility+bundled with libxml2.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "foo"+      , attributes = [ XML.attribute "a" "x", XML.attribute "b" (Natural/show 2) ]+      , content = [ XML.leaf { name = "bar", attributes = XML.emptyAttributes } ]+      }+    )+= "<foo a=\"x\" b=\"2\"><bar/></foo>"+```++-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let Text/concatMap =+        missing+          sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+      ? ../Text/concatMap.dhall++let Text/concat =+        missing+          sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+      ? ../Text/concat.dhall++let element =+        missing+          sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+      ? ./element.dhall++let text =+        missing+          sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+      ? ./text.dhall++let emptyAttributes =+        missing+          sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+      ? ./emptyAttributes.dhall++let Attr = { mapKey : Text, mapValue : Text }++let esc = λ(x : Text) → λ(y : Text) → Text/replace x "&${y};"++let `escape&` = esc "&" "amp"++let `escape<` = esc "<" "lt"++let `escape>` = esc ">" "gt"++let `escape'` = esc "'" "apos"++let `escape"` = esc "\"" "quot"++let escapeCommon = λ(text : Text) → `escape<` (`escape&` text)++let escapeAttr = λ(text : Text) → `escape"` (`escape'` (escapeCommon text))++let escapeText = λ(text : Text) → `escape>` (escapeCommon text)++let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${escapeAttr x.mapValue}\""++let render+    : XML → Text+    = λ(x : XML) →+        x+          Text+          { text = escapeText+          , rawText = λ(t : Text) → t+          , element =+              λ ( elem+                : { attributes : List { mapKey : Text, mapValue : Text }+                  , content : List Text+                  , name : Text+                  }+                ) →+                let attribs = Text/concatMap Attr renderAttr elem.attributes++                in      "<${elem.name}${attribs}"+                    ++  ( if    Natural/isZero (List/length Text elem.content)+                          then  "/>"+                          else  ">${Text/concat elem.content}</${elem.name}>"+                        )+          }++let simple =+      λ(name : Text) →+      λ(content : List XML) →+        element { name, attributes = emptyAttributes, content }++let example0 =+        assert+      :   render+            ( simple+                "note"+                [ simple "to" [ text "Tove" ]+                , simple "from" [ text "Jani" ]+                , simple "heading" [ text "Reminder" ]+                , simple "body" [ text "Don't forget me this weekend!" ]+                ]+            )+        ≡ Text/replace+            "\n"+            ""+            ''+            <note>+            <to>Tove</to>+            <from>Jani</from>+            <heading>Reminder</heading>+            <body>Don't forget me this weekend!</body>+            </note>+            ''++let example1 =+        assert+      :   render+            ( element+                { name = "escape"+                , attributes = toMap { attribute = "<>'\"&" }+                , content = [ text "<>'\"&" ]+                }+            )+        ≡ Text/replace+            "\n"+            ""+            ''+            <escape attribute="&lt;>&apos;&quot;&amp;">&lt;&gt;'"&amp;</escape>+            ''++in  render
+ dhall-lang/Prelude/XML/text view
@@ -0,0 +1,3 @@+  missing+    sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+? ./text.dhall
+ dhall-lang/Prelude/XML/text.dhall view
@@ -0,0 +1,39 @@+{-|+Create a Text value to be inserted into an XML element as content.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "location"+      , attributes = XML.emptyAttributes+      , content = [ XML.text "/foo/bar" ]+      }+    )+= "<location>/foo/bar</location>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let text+    : Text → XML+    = λ(d : Text) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.text d++in  text
+ dhall-lang/Prelude/package.dhall view
@@ -0,0 +1,73 @@+{ Bool =+      missing+        sha256:dde2b9b71afdd26878c06e90cd2cde4488063457d5fbe30e02baed3bec5eede6+    ? ./Bool/package.dhall+, Date =+      missing+        sha256:fc0c5efc924fa99aa8e5dea5d78c3dc1a24cb550028342b90149ea78cb5ca873+    ? ./Date/package.dhall+, Double =+      missing+        sha256:b8d20ab3216083622ae371fb42a6732bc67bb2d66e84989c8ddba7556a336cf7+    ? ./Double/package.dhall+, Function =+      missing+        sha256:f4ca848f69034f9d7a74e12c556c3a3396966c1de3a9427a102d1aff4580192f+    ? ./Function/package.dhall+, Integer =+      missing+        sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0+    ? ./Integer/package.dhall+, JSON =+      missing+        sha256:5f98b7722fd13509ef448b075e02b9ff98312ae7a406cf53ed25012dbc9990ac+    ? ./JSON/package.dhall+, List =+      missing+        sha256:26d1b4cd800219d8b67043c638926aa6e5517ea74a0bd3e371974514621bca04+    ? ./List/package.dhall+, Location =+      missing+        sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470+    ? ./Location/package.dhall+, Map =+      missing+        sha256:c5e79a9de642644a09b96a2ec3147c5d8662b7926f09610e751c0c0f6ed0b30a+    ? ./Map/package.dhall+, Monoid =+      missing+        sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+    ? ./Monoid.dhall+, Natural =+      missing+        sha256:ee9ed2b28a417ed4e9a0c284801b928bf91b3fbdc1a68616347678c1821f1ddf+    ? ./Natural/package.dhall+, NonEmpty =+      missing+        sha256:c24686a230a4b3cd51e5a57cd4510b4f8242f813d7823d41bac5954e7af56f7a+    ? ./NonEmpty/package.dhall+, Operator =+      missing+        sha256:861f724704a7b4755c96f173e54d03f314492a2d046723404c31ff612b7bf2e6+    ? ./Operator/package.dhall+, Optional =+      missing+        sha256:74331dfe59c09db65edc7ec4498bff92473c8c06d92752f9470d26e25f91320c+    ? ./Optional/package.dhall+, Text =+      missing+        sha256:79b671a70ac459b799a53bbb8a383cc8b81b40421745c54bf0fb1143168cbd6f+    ? ./Text/package.dhall+, Time =+      missing+        sha256:6715c4c71a113429fef8b94e4561a93c288942dad9dfd75ac545de96c5b5652a+    ? ./Time/package.dhall+, TimeZone =+      missing+        sha256:c17fd403c637856f34c8287168b92974e8c1a3a7331967f75276d179057084fd+    ? ./TimeZone/package.dhall+, XML =+      missing+        sha256:2e111f0952087d42072b059f0bf4c95861a46bffa67ad4c8c39086edf405f32e+    ? ./XML/package.dhall+}
+ dhall-lang/tests/alpha-normalization/success/regression/preludeBoolFoldA.dhall view
@@ -0,0 +1,6 @@+-- For https://github.com/dhall-lang/dhall-haskell/issues/929+  λ(b : Bool)+→ λ(bool : Type)+→ λ(true : bool)+→ λ(false : bool)+→ if b then true else false
+ dhall-lang/tests/alpha-normalization/success/regression/preludeBoolFoldB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → λ(_ : Type) → λ(_ : _) → λ(_ : _@1) → if _@3 then _@1 else _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingUnderscoreA.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingUnderscoreB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingXA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingXB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(_ : Natural) → x
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → λ(_ : Natural) → _@1
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> \(x: Bool) -> x && x@1
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → λ(_ : Bool) → _ && _@1
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXFreeA.dhall view
@@ -0,0 +1,4 @@+{-+    This test has free variables, so it doesn't typecheck+-}+\(x: Bool) -> \(x: Bool) -> [x, x@0, x@1, x@2, x@3]
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXFreeB.dhall view
@@ -0,0 +1,1 @@+\(_: Bool) -> \(_: Bool) -> [_, _, _@1, x, x@1]
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXYA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> \(y: Bool) -> x && y
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXYB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → λ(_ : Bool) → _@1 && _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingUnderscoreA.dhall view
@@ -0,0 +1,1 @@+Bool → Natural
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingUnderscoreB.dhall view
@@ -0,0 +1,1 @@+Bool → Natural
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingXA.dhall view
@@ -0,0 +1,1 @@+∀(x : Type) → x
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingXB.dhall view
@@ -0,0 +1,1 @@+Type → _
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeNestedBindingXA.dhall view
@@ -0,0 +1,1 @@+∀(x : Type) → Type → x
+ dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeNestedBindingXB.dhall view
@@ -0,0 +1,1 @@+Type → Type → _@1
+ dhall-lang/tests/binary-decode/failure/unit/ApplyNoArgs.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/LambdaExplicitlyNamedUnderscore.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/ListOneWithAnnotation.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/NaturalNegativeOne.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/binary-decode/failure/unit/OperatorOrTooFewArgs.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/OperatorOrTooManyArgs.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/OperatorUnknownOpcode.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/PiExplicitlyNamedUnderscore.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/failure/unit/VariableExplicitlyNamedUnderscore.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/success/unit/AnnotationA.dhallb view
@@ -0,0 +1,1 @@+ƒ‚gNatural
+ dhall-lang/tests/binary-decode/success/unit/AnnotationB.dhall view
@@ -0,0 +1,1 @@+5 : Natural
+ dhall-lang/tests/binary-decode/success/unit/ApplicationA.dhallb view

binary file changed (absent → 16 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ApplicationB.dhall view
@@ -0,0 +1,1 @@+Natural/show _
+ dhall-lang/tests/binary-decode/success/unit/ApplicationMultipleA.dhallb view

binary file changed (absent → 18 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ApplicationMultipleB.dhall view
@@ -0,0 +1,1 @@+f x y z
+ dhall-lang/tests/binary-decode/success/unit/AssertA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/AssertB.dhall view
@@ -0,0 +1,1 @@+assert : _
+ dhall-lang/tests/binary-decode/success/unit/BoolFalseA.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/binary-decode/success/unit/BoolFalseB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/binary-decode/success/unit/BoolIfA.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/binary-decode/success/unit/BoolIfB.dhall view
@@ -0,0 +1,1 @@+if True then x else y
+ dhall-lang/tests/binary-decode/success/unit/BoolTrueA.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/binary-decode/success/unit/BoolTrueB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/binary-decode/success/unit/BuiltinNaturalShowA.dhallb view
@@ -0,0 +1,1 @@+lNatural/show
+ dhall-lang/tests/binary-decode/success/unit/BuiltinNaturalShowB.dhall view
@@ -0,0 +1,1 @@+Natural/show
+ dhall-lang/tests/binary-decode/success/unit/BuiltinNaturalSubtractA.dhallb view
@@ -0,0 +1,1 @@+pNatural/subtract
+ dhall-lang/tests/binary-decode/success/unit/BuiltinNaturalSubtractB.dhall view
@@ -0,0 +1,1 @@+Natural/subtract
+ dhall-lang/tests/binary-decode/success/unit/BytesA.dhallb view

binary file changed (absent → 114 bytes)

+ dhall-lang/tests/binary-decode/success/unit/BytesB.dhall view
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
+ dhall-lang/tests/binary-decode/success/unit/CompletionA.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/binary-decode/success/unit/CompletionB.dhall view
@@ -0,0 +1,1 @@+T::r
+ dhall-lang/tests/binary-decode/success/unit/DateA.dhallb view
@@ -0,0 +1,1 @@+„Ð
+ dhall-lang/tests/binary-decode/success/unit/DateB.dhall view
@@ -0,0 +1,1 @@+2000-01-01
+ dhall-lang/tests/binary-decode/success/unit/DoubleDoubleA.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/binary-decode/success/unit/DoubleDoubleB.dhall view
@@ -0,0 +1,6 @@+{-+The CBOR for this is an (oversized) double-precision number.  It could have been+stored as single- (or even half-) precision, but we require decoders to accept+it anyway.+-}+2.0
+ dhall-lang/tests/binary-decode/success/unit/DoubleHalfA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/DoubleHalfB.dhall view
@@ -0,0 +1,7 @@+{-+The CBOR for this is a half-precision number.  Although dhall specifies that+encoders should only use half-precision for infinities and NaN, it also+specifies that decoders should tolerate floating point numbers with any+precision.+-}+1.0
+ dhall-lang/tests/binary-decode/success/unit/DoubleInfinityA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/DoubleInfinityB.dhall view
@@ -0,0 +1,1 @@+Infinity
+ dhall-lang/tests/binary-decode/success/unit/DoubleNegativeInfinityA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/DoubleNegativeInfinityB.dhall view
@@ -0,0 +1,1 @@+-Infinity
+ dhall-lang/tests/binary-decode/success/unit/DoubleSingleA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/DoubleSingleB.dhall view
@@ -0,0 +1,4 @@+{-+The CBOR for this is a single-precision number+-}+2.0
+ dhall-lang/tests/binary-decode/success/unit/IntegerBigNegativeA.dhallb view
@@ -0,0 +1,1 @@+‚ÃIÿÿÿÿÿÿÿÿ
+ dhall-lang/tests/binary-decode/success/unit/IntegerBigNegativeB.dhall view
@@ -0,0 +1,2 @@+{- -2^65 -}+-36893488147419103232
+ dhall-lang/tests/binary-decode/success/unit/IntegerBigPositiveA.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/binary-decode/success/unit/IntegerBigPositiveB.dhall view
@@ -0,0 +1,2 @@+{- 2^65 -}++36893488147419103232
+ dhall-lang/tests/binary-decode/success/unit/IntegerNegativeOneA.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/binary-decode/success/unit/IntegerNegativeOneB.dhall view
@@ -0,0 +1,1 @@+-1
+ dhall-lang/tests/binary-decode/success/unit/IntegerZeroA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/IntegerZeroB.dhall view
@@ -0,0 +1,1 @@++0
+ dhall-lang/tests/binary-decode/success/unit/LambdaNamedXA.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/binary-decode/success/unit/LambdaNamedXB.dhall view
@@ -0,0 +1,1 @@+λ(x : _) → x
+ dhall-lang/tests/binary-decode/success/unit/LambdaUnderscoreA.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/binary-decode/success/unit/LambdaUnderscoreB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Natural) → _
+ dhall-lang/tests/binary-decode/success/unit/LetMultipleA.dhallb view

binary file changed (absent → 26 bytes)

+ dhall-lang/tests/binary-decode/success/unit/LetMultipleB.dhall view
@@ -0,0 +1,1 @@+let x : Natural = 1 let y = 2 in x
+ dhall-lang/tests/binary-decode/success/unit/LetOneTypedA.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/binary-decode/success/unit/LetOneTypedB.dhall view
@@ -0,0 +1,1 @@+let x : Natural = 1 in x
+ dhall-lang/tests/binary-decode/success/unit/LetOneUntypedA.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/binary-decode/success/unit/LetOneUntypedB.dhall view
@@ -0,0 +1,1 @@+let x = 1 in x
+ dhall-lang/tests/binary-decode/success/unit/ListEmpty0A.dhallb view
@@ -0,0 +1,1 @@+‚gNatural
+ dhall-lang/tests/binary-decode/success/unit/ListEmpty0B.dhall view
@@ -0,0 +1,1 @@+[] : List Natural
+ dhall-lang/tests/binary-decode/success/unit/ListEmpty1A.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ListEmpty1B.dhall view
@@ -0,0 +1,1 @@+[] : x
+ dhall-lang/tests/binary-decode/success/unit/ListOneA.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ListOneB.dhall view
@@ -0,0 +1,1 @@+[ _ ]
+ dhall-lang/tests/binary-decode/success/unit/MergeAnnotatedA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/MergeAnnotatedB.dhall view
@@ -0,0 +1,1 @@+merge _ _@1 : _@2
+ dhall-lang/tests/binary-decode/success/unit/MergeUnannotatedA.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/success/unit/MergeUnannotatedB.dhall view
@@ -0,0 +1,1 @@+merge _ _@1
+ dhall-lang/tests/binary-decode/success/unit/NaturalBigA.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/binary-decode/success/unit/NaturalBigB.dhall view
@@ -0,0 +1,2 @@+{- 2^65 -}+36893488147419103232
+ dhall-lang/tests/binary-decode/success/unit/NaturalTwentyFourA.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/binary-decode/success/unit/NaturalTwentyFourB.dhall view
@@ -0,0 +1,5 @@+{-+24 is the first natural number that has a different CBOR encoding, hence the+separate test here.+-}+24
+ dhall-lang/tests/binary-decode/success/unit/NaturalZeroA.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/binary-decode/success/unit/NaturalZeroB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/binary-decode/success/unit/OperatorAndA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorAndB.dhall view
@@ -0,0 +1,1 @@+_ && _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorCombineA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorCombineB.dhall view
@@ -0,0 +1,1 @@+_ ∧ _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorCombineTypesA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorCombineTypesB.dhall view
@@ -0,0 +1,1 @@+_ ⩓ _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorEqA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorEqB.dhall view
@@ -0,0 +1,1 @@+_ == _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorEquivA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorEquivB.dhall view
@@ -0,0 +1,1 @@+_ ≡ _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorImportAltA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorImportAltB.dhall view
@@ -0,0 +1,1 @@+_ ? _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorListAppendA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorListAppendB.dhall view
@@ -0,0 +1,1 @@+_ # _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorNeqA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorNeqB.dhall view
@@ -0,0 +1,1 @@+_ != _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorOrA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorOrB.dhall view
@@ -0,0 +1,1 @@+_ || _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorPlusA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorPlusB.dhall view
@@ -0,0 +1,1 @@+_ + _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorPreferA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorPreferB.dhall view
@@ -0,0 +1,1 @@+_ ⫽ _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorTextAppendA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorTextAppendB.dhall view
@@ -0,0 +1,1 @@+_ ++ _@1
+ dhall-lang/tests/binary-decode/success/unit/OperatorTimesA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/OperatorTimesB.dhall view
@@ -0,0 +1,1 @@+_ * _@1
+ dhall-lang/tests/binary-decode/success/unit/PiNamedXA.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/binary-decode/success/unit/PiNamedXB.dhall view
@@ -0,0 +1,1 @@+∀(x : Natural) → _
+ dhall-lang/tests/binary-decode/success/unit/PiUnderscoreA.dhallb view
@@ -0,0 +1,1 @@+ƒgNaturaldText
+ dhall-lang/tests/binary-decode/success/unit/PiUnderscoreB.dhall view
@@ -0,0 +1,1 @@+Natural → Text
+ dhall-lang/tests/binary-decode/success/unit/RecordFieldAccessA.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/binary-decode/success/unit/RecordFieldAccessB.dhall view
@@ -0,0 +1,1 @@+_.x
+ dhall-lang/tests/binary-decode/success/unit/RecordLiteralA.dhallb view
@@ -0,0 +1,1 @@+‚¢axgNaturalaydBool
+ dhall-lang/tests/binary-decode/success/unit/RecordLiteralB.dhall view
@@ -0,0 +1,1 @@+{ x = Natural, y = Bool }
+ dhall-lang/tests/binary-decode/success/unit/RecordProjectFieldsA.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/binary-decode/success/unit/RecordProjectFieldsB.dhall view
@@ -0,0 +1,1 @@+r.{ x, y, z }
+ dhall-lang/tests/binary-decode/success/unit/RecordTypeA.dhallb view
@@ -0,0 +1,1 @@+‚¢axgNaturalaydBool
+ dhall-lang/tests/binary-decode/success/unit/RecordTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Natural, y : Bool }
+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORX2A.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORX2B.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORX3A.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORX3B.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORXA.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/binary-decode/success/unit/SelfDescribeCBORXB.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/binary-decode/success/unit/SomeA.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/binary-decode/success/unit/SomeB.dhall view
@@ -0,0 +1,1 @@+Some _
+ dhall-lang/tests/binary-decode/success/unit/TextInterpolatedA.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/binary-decode/success/unit/TextInterpolatedB.dhall view
@@ -0,0 +1,1 @@+"foo${_}bar"
+ dhall-lang/tests/binary-decode/success/unit/TextSimpleA.dhallb view
@@ -0,0 +1,1 @@+‚cfoo
+ dhall-lang/tests/binary-decode/success/unit/TextSimpleB.dhall view
@@ -0,0 +1,1 @@+"foo"
+ dhall-lang/tests/binary-decode/success/unit/TimeA.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/binary-decode/success/unit/TimeB.dhall view
@@ -0,0 +1,1 @@+12:00:00
+ dhall-lang/tests/binary-decode/success/unit/TimeZoneA.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/success/unit/TimeZoneB.dhall view
@@ -0,0 +1,1 @@++08:00
+ dhall-lang/tests/binary-decode/success/unit/ToMapA.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ToMapAnnotatedA.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/binary-decode/success/unit/ToMapAnnotatedB.dhall view
@@ -0,0 +1,1 @@+toMap e : T
+ dhall-lang/tests/binary-decode/success/unit/ToMapB.dhall view
@@ -0,0 +1,1 @@+toMap e
+ dhall-lang/tests/binary-decode/success/unit/UnionTypeA.dhallb view
@@ -0,0 +1,1 @@+‚¢axgNaturalayö
+ dhall-lang/tests/binary-decode/success/unit/UnionTypeB.dhall view
@@ -0,0 +1,1 @@+< x : Natural | y >
+ dhall-lang/tests/binary-decode/success/unit/VariableNamedA.dhallb view
@@ -0,0 +1,1 @@+‚ax
+ dhall-lang/tests/binary-decode/success/unit/VariableNamedB.dhall view
@@ -0,0 +1,1 @@+x@1
+ dhall-lang/tests/binary-decode/success/unit/VariableNamedOversizedIntA.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/binary-decode/success/unit/VariableNamedOversizedIntB.dhall view
@@ -0,0 +1,16 @@+{-++This file tests that a number encoded as a type larger than required is still+read successfully.  In this case, the .dhallb file has the bytes:++    8261 781b 0000 0000 0000 0001++which means the array ["x", uint64(1)].  This could have been stored in fewer+bytes as++    8261 7801++but decoders are required to allow the oversized representation.++-}+x@1
+ dhall-lang/tests/binary-decode/success/unit/VariableUnderscoreA.dhallb view
@@ -0,0 +1,1 @@+
+ dhall-lang/tests/binary-decode/success/unit/VariableUnderscoreB.dhall view
@@ -0,0 +1,1 @@+_@4
+ dhall-lang/tests/binary-decode/success/unit/VariableUnderscoreOversizedIntA.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/binary-decode/success/unit/VariableUnderscoreOversizedIntB.dhall view
@@ -0,0 +1,13 @@+{-++This file tests that a number encoded as a type larger than required is still+read successfully.  In this case, the .dhallb file has the bytes:++    1b00 0000 0000 0000 01++which means a uint64 with value 1.  The number 1 could have been stored in a+single byte as 01, but decoders are required to allow the oversized+representation.++-}+_@1
+ dhall-lang/tests/binary-decode/success/unit/imports/EnvironmentVariableA.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/EnvironmentVariableB.dhall view
@@ -0,0 +1,1 @@+env:FOO
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpImportWithQueryA.dhallb view

binary file changed (absent → 41 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpImportWithQueryB.dhall view
@@ -0,0 +1,1 @@+http://foo:bar@baz:123/path1/path2?query
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpImportWithoutQueryA.dhallb view

binary file changed (absent → 36 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpImportWithoutQueryB.dhall view
@@ -0,0 +1,1 @@+http://foo:bar@baz:123/path1/path2
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithEmptyQueryA.dhallb view

binary file changed (absent → 36 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithEmptyQueryB.dhall view
@@ -0,0 +1,2 @@+{- an empty query string is not the same as an absent query string -}+https://foo:bar@baz:123/path1/path2?
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithQueryA.dhallb view

binary file changed (absent → 41 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithQueryB.dhall view
@@ -0,0 +1,1 @@+https://foo:bar@baz:123/path1/path2?query
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithTrickyPathCharsA.dhallb view

binary file changed (absent → 46 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithTrickyPathCharsB.dhall view
@@ -0,0 +1,1 @@+https://authority/path:with!funny-characters
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithTrickyQueryCharsA.dhallb view

binary file changed (absent → 32 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithTrickyQueryCharsB.dhall view
@@ -0,0 +1,1 @@+https://authority/path?a%23b%5Bc
+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithoutQueryA.dhallb view

binary file changed (absent → 36 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/HttpsImportWithoutQueryB.dhall view
@@ -0,0 +1,1 @@+https://foo:bar@baz:123/path1/path2
+ dhall-lang/tests/binary-decode/success/unit/imports/LocalHereImportA.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/LocalHereImportB.dhall view
@@ -0,0 +1,1 @@+./path0/path1/path2/file
+ dhall-lang/tests/binary-decode/success/unit/imports/LocalHomeImportA.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/LocalHomeImportB.dhall view
@@ -0,0 +1,1 @@+~/path0/path1/path2/file
+ dhall-lang/tests/binary-decode/success/unit/imports/LocalParentImportA.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/LocalParentImportB.dhall view
@@ -0,0 +1,1 @@+../path0/path1/path2/file
+ dhall-lang/tests/binary-decode/success/unit/imports/LocalRootImportA.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/LocalRootImportB.dhall view
@@ -0,0 +1,1 @@+/path0/path1/path2/file
+ dhall-lang/tests/binary-decode/success/unit/imports/MissingA.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/binary-decode/success/unit/imports/MissingB.dhall view
@@ -0,0 +1,1 @@+missing
+ dhall-lang/tests/binary-decode/success/unit/recordProjectionByExpressionA.dhallb view
@@ -0,0 +1,2 @@+‚¢aa‚ab‚‚¡aagNatural
+ dhall-lang/tests/binary-decode/success/unit/recordProjectionByExpressionB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }.({ a : Natural })
+ dhall-lang/tests/import/cache/dhall/12203871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc view

binary file changed (absent → 42 bytes)

+ dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21 view
@@ -0,0 +1,1 @@+‚xevil string from bad cache
+ dhall-lang/tests/import/data/cors/AllowedAll.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/AllowedAll.dhall
+ dhall-lang/tests/import/data/cors/Empty.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Empty.dhall
+ dhall-lang/tests/import/data/cors/NoCORS.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
+ dhall-lang/tests/import/data/cors/Null.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Null.dhall
+ dhall-lang/tests/import/data/cors/OnlyGithub.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyGithub.dhall
+ dhall-lang/tests/import/data/cors/OnlyOther.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyOther.dhall
+ dhall-lang/tests/import/data/cors/OnlySelf.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlySelf.dhall
+ dhall-lang/tests/import/data/cors/Prelude.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/length
+ dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/data/cors/SelfImportRelative.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
+ dhall-lang/tests/import/data/cycle.dhall view
@@ -0,0 +1,1 @@+../failure/unit/Cycle.dhall
+ dhall-lang/tests/import/data/doesNotParse.dhall view
@@ -0,0 +1,1 @@+[
+ dhall-lang/tests/import/data/doesNotTypecheck.dhall view
@@ -0,0 +1,1 @@+0 0
+ dhall-lang/tests/import/data/example.bin view
@@ -0,0 +1,1 @@+#Eg‰«Íï
+ dhall-lang/tests/import/data/example.txt view
@@ -0,0 +1,1 @@+Hello, world!
+ dhall-lang/tests/import/data/file with spaces.txt view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/import/data/importBoundary.dhall view
@@ -0,0 +1,3 @@+-- This file contains a free variable. This should be a type error, even if the variable+-- is in scope in the importing expression+x
+ dhall-lang/tests/import/data/nested.dhall view
@@ -0,0 +1,1 @@+{ x = ./simple.dhall sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2 }
+ dhall-lang/tests/import/data/poisonedCache.dhall view
@@ -0,0 +1,4 @@+{- This file has a poisoned cache entry.  We want to+   ensure we ignore cache entries which don't match+   the hash -}+"Correct benign content"
+ dhall-lang/tests/import/data/referentiallyOpaque.dhall view
@@ -0,0 +1,18 @@+{- This is a "referentially opaque" import (i.e. an import that is not+   globally addressable), which cannot be imported by a "referentially+   transparent" import (i.e. an import that is globally addressable).++   This test file is used in a failing test to verify that referentially+   transparent imports cannot import referentially opaque imports.  In the test+   suite this file is actually imported via its GitHub URL (not its local file+   path), so it plays the role of the referentially transparent import.  Then,+   this file attempts to import a referentially opaque import (an environment+   variable in this case) to verify that the import fails.++   For this test file we need to select a referentially opaque import that+   would succeed if imported on its own, so that a non-compliant implementation+   doesn't fail this test for the wrong reason (i.e. due to the import not+   being present).  We thus use the `DHALL_TEST_VAR` environment variable, that+   is expected to be set when running import tests.+-}+env:DHALL_TEST_VAR as Text
+ dhall-lang/tests/import/data/simple.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/data/simpleLocation.dhall view
@@ -0,0 +1,1 @@+./simple.dhall as Location
+ dhall-lang/tests/import/data/userAgent.dhall view
@@ -0,0 +1,1 @@+"Dhall (from import)"
+ dhall-lang/tests/import/failure/alternativeEnv.dhall view
@@ -0,0 +1,1 @@+env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3
+ dhall-lang/tests/import/failure/alternativeEnvMissing.dhall view
@@ -0,0 +1,1 @@+env:UNSET ? missing
+ dhall-lang/tests/import/failure/customHeadersUsingBoundVariable.dhall view
@@ -0,0 +1,15 @@+{- This is a type error because the custom headers are type-checked with an+   empty context.  This is necessary because:++   * import resolution precedes β-normalization+   * we also don't want custom headers to leak program state anyway++   This should fail due to the `x` within the custom header being an unbound+   variable+-}++let x = "Bar"++in https://httpbin.org/headers+     using [ { mapKey = "Foo", mapValue = x } ]+     as Text
+ dhall-lang/tests/import/failure/originHeadersFromRemote.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/failure/originHeadersFromRemoteENV.dhall view
@@ -0,0 +1,11 @@+-- Use of a remote import causes Cyclic Import on env:DHALL_HEADERS+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = http://example.com as Text+        }+      }+      ''+  }
+ dhall-lang/tests/import/failure/unit/404.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/nonexistent-file.dhall
+ dhall-lang/tests/import/failure/unit/Cycle.dhall view
@@ -0,0 +1,1 @@+../../data/cycle.dhall
+ dhall-lang/tests/import/failure/unit/DontRecoverCycle.dhall view
@@ -0,0 +1,1 @@+../../data/cycle.dhall ? 0
+ dhall-lang/tests/import/failure/unit/DontRecoverHashMismatch.dhall view
@@ -0,0 +1,3 @@+-- This fails because the `?` operator does not recover from integrity check+-- failures+../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ? 0
+ dhall-lang/tests/import/failure/unit/DontRecoverParseError.dhall view
@@ -0,0 +1,1 @@+../../data/doesNotParse.dhall ? 0
+ dhall-lang/tests/import/failure/unit/DontRecoverTypeError.dhall view
@@ -0,0 +1,1 @@+../../data/doesNotTypecheck.dhall ? 0
+ dhall-lang/tests/import/failure/unit/EnvFromRemote.dhall view
@@ -0,0 +1,13 @@+{- The following remote import attempts to import an environment variable, which+   must be disallowed by the referential sanity check++   One reason for doing this is to protect against remote imports exfiltrating+   environment variables (such as via custom headers).  Only referentially+   opaque imports (i.e. local imports) have permission to refer to other+   referentially opaque imports in order to protect against this attack.++   The referential sanity check also ensures that remote imports are+   referentially transparent.  Or in other words, any import that is globally+   addressable must have a meaning that is not context-sensitive.+-}+https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/data/referentiallyOpaque.dhall
+ dhall-lang/tests/import/failure/unit/EnvUnset.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET
+ dhall-lang/tests/import/failure/unit/EnvUnsetAsText.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET as Text
+ dhall-lang/tests/import/failure/unit/FileMissing.dhall view
@@ -0,0 +1,1 @@+./not-a-file.dhall
+ dhall-lang/tests/import/failure/unit/HashMismatch.dhall view
@@ -0,0 +1,1 @@+../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ dhall-lang/tests/import/failure/unit/HashMismatch2.dhall view
@@ -0,0 +1,2 @@+-- This ensures that even if the file gets imported without hash first, the hash check is not skipped later+../../data/simple.dhall + ../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ../../data/simple.dhall
+ dhall-lang/tests/import/failure/unit/Missing.dhall view
@@ -0,0 +1,1 @@+missing
+ dhall-lang/tests/import/failure/unit/VarAcrossImportBoundary.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> ../../data/importBoundary.dhall
+ dhall-lang/tests/import/failure/unit/cors/Empty.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Empty.dhall
+ dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/NoCORS.dhall
+ dhall-lang/tests/import/failure/unit/cors/Null.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Null.dhall
+ dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyOther.dhall
+ dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall
+ dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsFail.dhall
+ dhall-lang/tests/import/home/hello.dhall view
@@ -0,0 +1,1 @@+"hello"
+ dhall-lang/tests/import/success/customHeadersA.dhall view
@@ -0,0 +1,3 @@+https://httpbin.org/user-agent+  using [ { mapKey = "User-Agent", mapValue = "Dhall" } ]+  as Text
+ dhall-lang/tests/import/success/customHeadersB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall"+}+''
+ dhall-lang/tests/import/success/hashFromCacheA.dhall view
@@ -0,0 +1,11 @@+{-+An import with an integrity check MUST be fetched from the cache if possible.++If you have set XDG_CACHE_HOME as described in tests/README.md, this hash will+be available in the cache, so even though this is a `missing` import, it can be+resolved by its hash.++(If you're interested, the value is a fully-αβ-normalized copy of+Prelude/Optional/null)+-}+missing sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
+ dhall-lang/tests/import/success/hashFromCacheB.dhall view
@@ -0,0 +1,3 @@+λ(_ : Type) →+λ(_ : Optional _) →+  merge { None = True, Some = λ(_ : _@1) → False } _
+ dhall-lang/tests/import/success/headerForwardingA.dhall view
@@ -0,0 +1,12 @@+{- This test verifies that header-forwarding works correctly for relative+   imports within the same domain++   `test.dhall-lang.org/foo` returns `./bar` and `test.dhall-lang.org/foo`+   returns `True`, and both URLs reject all requests without a `Test` header.++   This test requires that the initial import to+   `https://test.dhall-lang.org/foo` forwards the `Test` header+   to the transitive relative import of `https://test.dhall-lang.org/bar` in+   order to succeed.+-}+https://test.dhall-lang.org/foo using (toMap { Test = "Example" })
+ dhall-lang/tests/import/success/headerForwardingB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/import/success/nestedHashA.dhall view
@@ -0,0 +1,1 @@+../data/nested.dhall sha256:add9792d79d9e03918e3236f32c6f8e89dbc05efac3451eb835676275f2c20a5
+ dhall-lang/tests/import/success/nestedHashB.dhall view
@@ -0,0 +1,1 @@+{ x = 3 }
+ dhall-lang/tests/import/success/noHeaderForwardingA.dhall view
@@ -0,0 +1,6 @@+{- The purpose of this test is to verify that the custom headers supplied to+   this import are not forwarded to the transitive import of+   https://httpbin.org/user-agent+-}+https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/success/customHeadersA.dhall+  using [ { mapKey = "User-Agent", mapValue = "Secret" } ]
+ dhall-lang/tests/import/success/noHeaderForwardingB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall"+}+''
+ dhall-lang/tests/import/success/originHeadersA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall"+}+''
+ dhall-lang/tests/import/success/originHeadersENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = "Dhall"+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/originHeadersImportA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersImportB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall (from import)"+}+''
+ dhall-lang/tests/import/success/originHeadersImportENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = ./dhall-lang/tests/import/data/userAgent.dhall+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/originHeadersImportFromEnvA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersImportFromEnvB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall (from env)"+}+''
+ dhall-lang/tests/import/success/originHeadersImportFromEnvENV.dhall view
@@ -0,0 +1,11 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = env:USER_AGENT as Text+        }+      }+      ''+      , USER_AGENT = "Dhall (from env)"+  }
+ dhall-lang/tests/import/success/originHeadersOverrideA.dhall view
@@ -0,0 +1,3 @@+https://httpbin.org/user-agent+  using [ { mapKey = "User-Agent", mapValue = "inline-header" } ]+  as Text
+ dhall-lang/tests/import/success/originHeadersOverrideB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "user-header"+}+''
+ dhall-lang/tests/import/success/originHeadersOverrideENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = "user-header"+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/unit/AlternativeChain1A.dhall view
@@ -0,0 +1,1 @@+missing ? missing ? 42
+ dhall-lang/tests/import/success/unit/AlternativeChain1B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeChain2A.dhall view
@@ -0,0 +1,1 @@+missing ? 42 ? 10
+ dhall-lang/tests/import/success/unit/AlternativeChain2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeEnvA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET ? 42
+ dhall-lang/tests/import/success/unit/AlternativeEnvB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeImportErrorA.dhall view
@@ -0,0 +1,1 @@+missing ? 42
+ dhall-lang/tests/import/success/unit/AlternativeImportErrorB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNestedImportErrorA.dhall view
@@ -0,0 +1,1 @@+../../failure/missing.dhall ? 42
+ dhall-lang/tests/import/success/unit/AlternativeNestedImportErrorB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError1A.dhall view
@@ -0,0 +1,1 @@+42 ? 10
+ dhall-lang/tests/import/success/unit/AlternativeNoError1B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError2A.dhall view
@@ -0,0 +1,1 @@+42 ? missing
+ dhall-lang/tests/import/success/unit/AlternativeNoError2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError3A.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR ? 10
+ dhall-lang/tests/import/success/unit/AlternativeNoError3B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeSubExprA.dhall view
@@ -0,0 +1,1 @@+missing + 10 ? 42
+ dhall-lang/tests/import/success/unit/AlternativeSubExprB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableA.dhall view
@@ -0,0 +1,1 @@+let x = 0 in (missing ? x)
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableB.dhall view
@@ -0,0 +1,1 @@+let x = 0 in x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> x ? y
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> (y + missing) ? x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/AsBytesA.dhall view
@@ -0,0 +1,1 @@+../../data/example.bin as Bytes
+ dhall-lang/tests/import/success/unit/AsBytesB.dhall view
@@ -0,0 +1,1 @@+0x"0123456789abcdef"
+ dhall-lang/tests/import/success/unit/AsTextA.dhall view
@@ -0,0 +1,1 @@+../../data/example.txt as Text
+ dhall-lang/tests/import/success/unit/AsTextB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/DontCacheIfHashA.dhall view
@@ -0,0 +1,5 @@+-- The let triggers a loading of `simple.dhall` in the cache,+-- but the second import uses a hash that corresponds to a different file already in the content-addressed store.+-- This test ensures that we retrieve the value corresponding to the hash and not the path even if the path is in cache.+let x = ../../data/simple.dhall+in ../../data/simple.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
+ dhall-lang/tests/import/success/unit/DontCacheIfHashB.dhall view
@@ -0,0 +1,1 @@+let x = 3 in λ(_ : Type) → λ(_ : Optional _) → merge { `None` = True, `Some` = λ(_ : _@1) → False } _
+ dhall-lang/tests/import/success/unit/EnvSetA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR
+ dhall-lang/tests/import/success/unit/EnvSetAsTextA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR as Text
+ dhall-lang/tests/import/success/unit/EnvSetAsTextB.dhall view
@@ -0,0 +1,1 @@+"6 * 7"
+ dhall-lang/tests/import/success/unit/EnvSetB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/FilenameWithSpacesA.dhall view
@@ -0,0 +1,1 @@+../../data/"file with spaces.txt"
+ dhall-lang/tests/import/success/unit/FilenameWithSpacesB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/import/success/unit/IgnorePoisonedCacheA.dhall view
@@ -0,0 +1,1 @@+../../data/poisonedCache.dhall sha256:618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21
+ dhall-lang/tests/import/success/unit/IgnorePoisonedCacheB.dhall view
@@ -0,0 +1,1 @@+"Correct benign content"
+ dhall-lang/tests/import/success/unit/ImportRelativeToHomeA.dhall view
@@ -0,0 +1,1 @@+~/hello.dhall ++ " world"
+ dhall-lang/tests/import/success/unit/ImportRelativeToHomeB.dhall view
@@ -0,0 +1,1 @@+"hello" ++ " world"
+ dhall-lang/tests/import/success/unit/MixImportModesA.dhall view
@@ -0,0 +1,2 @@+-- This is to ensure caching doesn't accidentally confuse import modes+{ n = ../../data/simple.dhall, txt = ../../data/simple.dhall as Text, loc = ../../data/simple.dhall as Location }
+ dhall-lang/tests/import/success/unit/MixImportModesB.dhall view
@@ -0,0 +1,1 @@+{ loc = < Environment: Text | Local: Text | Missing | Remote: Text >.Local "./dhall-lang/tests/import/data/simple.dhall", n = 3, txt = "3\n" }
+ dhall-lang/tests/import/success/unit/NormalizeA.dhall view
@@ -0,0 +1,1 @@+../../../../../dhall-lang/tests/normalization/success/unit/OperatorPlusOneAndOneA.dhall
+ dhall-lang/tests/import/success/unit/NormalizeB.dhall view
@@ -0,0 +1,1 @@+2
+ dhall-lang/tests/import/success/unit/QuotedPathA.dhall view
@@ -0,0 +1,1 @@+../".."/"data"/"example.txt" as Text
+ dhall-lang/tests/import/success/unit/QuotedPathB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureA.dhall view
@@ -0,0 +1,1 @@+../../failure/unit/FileMissing.dhall ? 0
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/import/success/unit/RemoteAsTextA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/example.txt as Text
+ dhall-lang/tests/import/success/unit/RemoteAsTextB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/SimpleA.dhall view
@@ -0,0 +1,1 @@+../../data/simple.dhall
+ dhall-lang/tests/import/success/unit/SimpleB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/SimpleHashA.dhall view
@@ -0,0 +1,1 @@+../../data/simple.dhall sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/import/success/unit/SimpleHashB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/SimpleRemoteA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simple.dhall
+ dhall-lang/tests/import/success/unit/SimpleRemoteB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/asLocation/AbsoluteA.dhall view
@@ -0,0 +1,1 @@+/absolute/import as Location
+ dhall-lang/tests/import/success/unit/asLocation/AbsoluteB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "/absolute/import"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize1A.dhall view
@@ -0,0 +1,1 @@+./foo/./bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize2A.dhall view
@@ -0,0 +1,1 @@+./foo/baz/../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize3A.dhall view
@@ -0,0 +1,1 @@+./../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize4A.dhall view
@@ -0,0 +1,1 @@+../../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize4B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize5A.dhall view
@@ -0,0 +1,1 @@+./foo/../../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize5B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain1A.dhall view
@@ -0,0 +1,1 @@+./Relative1A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain2A.dhall view
@@ -0,0 +1,1 @@+./Canonicalize4A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain3A.dhall view
@@ -0,0 +1,1 @@+../asLocation/Canonicalize4A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/DontTryResolvingA.dhall view
@@ -0,0 +1,1 @@+(missing as Location) ? 42  -- `missing` fails as an import, but definitely resolves as Location
+ dhall-lang/tests/import/success/unit/asLocation/DontTryResolvingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/asLocation/EnvA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR as Location
+ dhall-lang/tests/import/success/unit/asLocation/EnvB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Environment+  "DHALL_TEST_VAR"
+ dhall-lang/tests/import/success/unit/asLocation/HashA.dhall view
@@ -0,0 +1,6 @@+{-+  If you have set XDG_CACHE_HOME as described in tests/README.md, this hash will+  be available in the cache. Since this is an `as Location` test however, you+  mustn't use the cache value here.+-}+./some/import.dhall sha256:efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd as Location
+ dhall-lang/tests/import/success/unit/asLocation/HashB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/HomeA.dhall view
@@ -0,0 +1,1 @@+~/some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/HomeB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "~/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/MissingA.dhall view
@@ -0,0 +1,1 @@+missing as Location
+ dhall-lang/tests/import/success/unit/asLocation/MissingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/asLocation/Relative1A.dhall view
@@ -0,0 +1,1 @@+./some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Relative1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Relative2A.dhall view
@@ -0,0 +1,1 @@+../some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Relative2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize1A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/./bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize2A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/bar/../baz/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/baz/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize3A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/bar/../../baz/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/baz/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize4A.dhall view
@@ -0,0 +1,4 @@+{-+  The standardized behaviour does not respect https://tools.ietf.org/html/rfc3986#section-5.2 .+-}+https://example.com/../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize4B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/../bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain1A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simpleLocation.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simple.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain2A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/Canonicalize3A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain3A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/Canonicalize5A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainEnvA.dhall view
@@ -0,0 +1,5 @@+{-+    This test verifies that `env:VAR as Location` isn't rejected as referentially opaque,+    as `env:VAR` on its own would.+-}+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/EnvA.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainEnvB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Environment+  "HOME"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainMissingA.dhall view
@@ -0,0 +1,6 @@+{- This test verifies that `missing as Location` succeeds when chained since:+   * The `missing` is never actually resolved (due to the `as Location`)+   * The `missing` should be treated as referentially transparent (and therefore+     be a valid transitive dependency of a remote import)+-}+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/MissingA.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainMissingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/AllowedAll.dhall
+ dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
+ dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall
+ dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/PreludeA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/acee30866a179c9e9bb3fc02ec8be2883685eb14/tests/import/data/cors/Prelude.dhall
+ dhall-lang/tests/import/success/unit/cors/PreludeB.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportRelative.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsSuccess.dhall
+ dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/normalization/success/WithRecordValueA.dhall view
@@ -0,0 +1,12 @@+{-  This test illustrates that `with a = { c = 2 }` is not the same thing as+    `with a.c = 2`:++    * `with a = { c = 2 }` overrides the entire value of the field `a` with a new+      record containing only `c = 2`++    * `with a.c = 2` extends or updates the record stored underneath `a` to+      set the field `c` to `2`.++    Compare this to the `WithNested` test, which contains the `a.c = 2` case+-}+{ a.b = 1 } with a = { c = 2 }
+ dhall-lang/tests/normalization/success/WithRecordValueB.dhall view
@@ -0,0 +1,1 @@+{ a = { c = 2 } }
+ dhall-lang/tests/normalization/success/haskell-tutorial/access/0A.dhall view
@@ -0,0 +1,1 @@+{ x = "foo" }.x
+ dhall-lang/tests/normalization/success/haskell-tutorial/access/0B.dhall view
@@ -0,0 +1,1 @@+"foo"
+ dhall-lang/tests/normalization/success/haskell-tutorial/access/1A.dhall view
@@ -0,0 +1,1 @@+< Foo : Text | Bar : Natural >.Foo
+ dhall-lang/tests/normalization/success/haskell-tutorial/access/1B.dhall view
@@ -0,0 +1,1 @@+< Bar : Natural | Foo : Text >.Foo
+ dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/0A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/0B.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text, baz : Bool }, qux : Integer }
+ dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/1A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/1B.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text, baz : Bool }, qux : Integer }
+ dhall-lang/tests/normalization/success/haskell-tutorial/prefer/0A.dhall view
@@ -0,0 +1,1 @@+{ foo = 1, bar = "ABC" } // { baz = True }
+ dhall-lang/tests/normalization/success/haskell-tutorial/prefer/0B.dhall view
@@ -0,0 +1,1 @@+{ bar = "ABC", baz = True, foo = 1 }
+ dhall-lang/tests/normalization/success/haskell-tutorial/projection/0A.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = True, z = "ABC" }.{ x, y }
+ dhall-lang/tests/normalization/success/haskell-tutorial/projection/0B.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = True }
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationA.dhall view
@@ -0,0 +1,1 @@+\(foo: { x: Bool, y: Bool }) -> \(bar: { x: Bool }) -> (foo.{x, y} // bar).{ x }
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationB.dhall view
@@ -0,0 +1,3 @@+λ(foo : { x : Bool, y : Bool }) →+λ(bar : { x : Bool }) →+  (foo.{ x, y } ⫽ bar).{ x }
+ dhall-lang/tests/normalization/success/regression/NaturalFoldExtraArgA.dhall view
@@ -0,0 +1,2 @@+{- Checks that builtins don't accidentally discard further arguments than their arity -}+Natural/fold 0 (Bool -> Bool) (λ(_ : (Bool -> Bool)) → λ(_ : Bool) → True) (λ(_ : Bool) → False) True
+ dhall-lang/tests/normalization/success/regression/NaturalFoldExtraArgB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall view
@@ -0,0 +1,1 @@+toMap { `if` = 0, `foo%bar` = 1 }
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall view
@@ -0,0 +1,1 @@+[ { mapKey = "foo%bar", mapValue = 1 }, { mapKey = "if", mapValue = 0 } ]
+ dhall-lang/tests/normalization/success/regression/TrickyBinderIdentityA.dhall view
@@ -0,0 +1,1 @@+let T = Natural let ap = λ(f : T → List T) -> λ(x : T) -> f x in ap (λ(x : T) -> ap (λ(y : T) -> [x, y]) 1) 0
+ dhall-lang/tests/normalization/success/regression/TrickyBinderIdentityB.dhall view
@@ -0,0 +1,1 @@+[ 0, 1 ]
+ dhall-lang/tests/normalization/success/regression/UnsaturatedBuiltinsA.dhall view
@@ -0,0 +1,16 @@+{-  The Haskell implementation was incorrectly normalizing partially+    saturated `Natural/fold` and `List/fold` built-ins even though the standard+    requires built-ins to be fully saturated before normalization.++    For example, the Haskell implementation was normalizing `Natural/fold 0` to:++          λ(natural : Type)+        → λ(succ : natural → natural)+        → λ(zero : natural)+        → zero++    ... when the correct result should have been `Natural/fold 0` (no change)+-}+{ example0 = Natural/fold 0+, example1 = List/fold Bool [ True ]+}
+ dhall-lang/tests/normalization/success/regression/UnsaturatedBuiltinsB.dhall view
@@ -0,0 +1,3 @@+{ example0 = Natural/fold 0+, example1 = List/fold Bool [ True ]+}
+ dhall-lang/tests/normalization/success/remoteSystemsA.dhall view
@@ -0,0 +1,51 @@+let Text/concatMap = ../../../Prelude/Text/concatMap.dhall++let Text/concatSep = ../../../Prelude/Text/concatSep.dhall++let Row =+      { cores :+          Natural+      , host :+          Text+      , key :+          Text+      , mandatoryFeatures :+          List Text+      , platforms :+          List Text+      , speedFactor :+          Natural+      , supportedFeatures :+          List Text+      , user :+          Optional Text+      }++let renderRow =+        λ ( row+          : Row+          )+      → let host =+              merge+                { None = row.host+                , Some = λ(user : Text) → "${user}@${row.host}"+                }+                row.user+        +        let platforms = Text/concatSep "," row.platforms+        +        let key = row.key+        +        let cores = Integer/show (Natural/toInteger row.cores)+        +        let speedFactor = Integer/show (Natural/toInteger row.speedFactor)+        +        let supportedFeatures = Text/concatSep "," row.supportedFeatures+        +        let mandatoryFeatures = Text/concatSep "," row.mandatoryFeatures+        +        in  ''+            ${host} ${platforms} ${key} ${cores} ${speedFactor} ${supportedFeatures} ${mandatoryFeatures}+            ''++in  Text/concatMap Row renderRow
+ dhall-lang/tests/normalization/success/remoteSystemsB.dhall view
@@ -0,0 +1,166 @@+  λ ( xs+    : List+      { cores :+          Natural+      , host :+          Text+      , key :+          Text+      , mandatoryFeatures :+          List Text+      , platforms :+          List Text+      , speedFactor :+          Natural+      , supportedFeatures :+          List Text+      , user :+          Optional Text+      }+    )+→ List/fold+  { cores :+      Natural+  , host :+      Text+  , key :+      Text+  , mandatoryFeatures :+      List Text+  , platforms :+      List Text+  , speedFactor :+      Natural+  , supportedFeatures :+      List Text+  , user :+      Optional Text+  }+  xs+  Text+  (   λ ( x+        : { cores :+              Natural+          , host :+              Text+          , key :+              Text+          , mandatoryFeatures :+              List Text+          , platforms :+              List Text+          , speedFactor :+              Natural+          , supportedFeatures :+              List Text+          , user :+              Optional Text+          }+        )+    → λ(y : Text)+    →     ''+          ${merge+            { None = x.host, Some = λ(user : Text) → "${user}@${x.host}" }+            x.user} ${merge+                      { Empty = "", NonEmpty = λ(result : Text) → result }+                      ( List/fold+                        Text+                        x.platforms+                        < Empty | NonEmpty : Text >+                        (   λ(element : Text)+                          → λ(status : < Empty | NonEmpty : Text >)+                          → merge+                            { Empty =+                                < Empty | NonEmpty : Text >.NonEmpty element+                            , NonEmpty =+                                  λ(result : Text)+                                → < Empty | NonEmpty : Text >.NonEmpty+                                  ("${element},${result}")+                            }+                            status+                        )+                        < Empty | NonEmpty : Text >.Empty+                      )} ${x.key} ${Integer/show+                                    ( Natural/toInteger x.cores+                                    )} ${Integer/show+                                         ( Natural/toInteger x.speedFactor+                                         )} ${merge+                                              { Empty =+                                                  ""+                                              , NonEmpty =+                                                  λ(result : Text) → result+                                              }+                                              ( List/fold+                                                Text+                                                x.supportedFeatures+                                                < Empty | NonEmpty : Text >+                                                (   λ(element : Text)+                                                  → λ ( status+                                                      : < Empty+                                                        | NonEmpty :+                                                            Text+                                                        >+                                                      )+                                                  → merge+                                                    { Empty =+                                                        < Empty+                                                        | NonEmpty :+                                                            Text+                                                        >.NonEmpty+                                                        element+                                                    , NonEmpty =+                                                          λ(result : Text)+                                                        → < Empty+                                                          | NonEmpty :+                                                              Text+                                                          >.NonEmpty+                                                          "${element},${result}"+                                                    }+                                                    status+                                                )+                                                < Empty+                                                | NonEmpty :+                                                    Text+                                                >.Empty+                                              )} ${merge+                                                   { Empty =+                                                       ""+                                                   , NonEmpty =+                                                       λ(result : Text) → result+                                                   }+                                                   ( List/fold+                                                     Text+                                                     x.mandatoryFeatures+                                                     < Empty | NonEmpty : Text >+                                                     (   λ(element : Text)+                                                       → λ ( status+                                                           : < Empty+                                                             | NonEmpty :+                                                                 Text+                                                             >+                                                           )+                                                       → merge+                                                         { Empty =+                                                             < Empty+                                                             | NonEmpty :+                                                                 Text+                                                             >.NonEmpty+                                                             element+                                                         , NonEmpty =+                                                               λ(result : Text)+                                                             → < Empty+                                                               | NonEmpty :+                                                                   Text+                                                               >.NonEmpty+                                                               "${element},${result}"+                                                         }+                                                         status+                                                     )+                                                     < Empty+                                                     | NonEmpty :+                                                         Text+                                                     >.Empty+                                                   )}+          ${y}''+  )+  ""
+ dhall-lang/tests/normalization/success/simple/completionA.dhall view
@@ -0,0 +1,10 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  { example0 = Example::{=}+    , example1 = Example::{ name = "John Doe" }+    , example2 = Example::{ id = Some 0 }+    , example3 = Example::{ name = "Mary Jane", id = Some 0 }+    }
+ dhall-lang/tests/normalization/success/simple/completionB.dhall view
@@ -0,0 +1,5 @@+{ example0 = { id = None Natural, name = "" }+, example1 = { id = None Natural, name = "John Doe" }+, example2 = { id = Some 0, name = "" }+, example3 = { id = Some 0, name = "Mary Jane" }+}
+ dhall-lang/tests/normalization/success/simple/doubleShowA.dhall view
@@ -0,0 +1,6 @@+{ example0 = Double/show -0.42+, example1 = Double/show 13.37+, example2 = Double/show NaN+, example3 = Double/show Infinity+, example4 = Double/show -Infinity+}
+ dhall-lang/tests/normalization/success/simple/doubleShowB.dhall view
@@ -0,0 +1,11 @@+{ example0 =+    "-0.42"+, example1 =+    "13.37"+, example2 =+    "NaN"+, example3 =+    "Infinity"+, example4 =+    "-Infinity"+}
+ dhall-lang/tests/normalization/success/simple/enumA.dhall view
@@ -0,0 +1,8 @@+let Role = < Wizard | Fighter | Rogue >++let show : Role → Text+         =+        λ(x : Role)+      → merge { Wizard = "Wizard", Fighter = "Fighter", Rogue = "Rogue" } x++in  show Role.Wizard
+ dhall-lang/tests/normalization/success/simple/enumB.dhall view
@@ -0,0 +1,1 @@+"Wizard"
+ dhall-lang/tests/normalization/success/simple/equalNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == False
+ dhall-lang/tests/normalization/success/simple/equalNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == False
+ dhall-lang/tests/normalization/success/simple/integerShowA.dhall view
@@ -0,0 +1,4 @@+{ example0 = Integer/show +1337+, example1 = Integer/show -42+, example2 = Integer/show +0+}
+ dhall-lang/tests/normalization/success/simple/integerShowB.dhall view
@@ -0,0 +1,1 @@+{ example0 = "+1337", example1 = "-42", example2 = "+0" }
+ dhall-lang/tests/normalization/success/simple/integerToDoubleA.dhall view
@@ -0,0 +1,10 @@+[ Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944++, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944+]
+ dhall-lang/tests/normalization/success/simple/integerToDoubleB.dhall view
@@ -0,0 +1,9 @@+[ Infinity+, 1.7976931348623157e308+, 1.7976931348623157e308+, 1.7976931348623155e308+, -Infinity+, -1.7976931348623157e308+, -1.7976931348623157e308+, -1.7976931348623155e308+]
+ dhall-lang/tests/normalization/success/simple/letAvoidCaptureA.dhall view
@@ -0,0 +1,3 @@+\(x: Natural)+-> let var = x+   in \(x: Bool) -> var
+ dhall-lang/tests/normalization/success/simple/letAvoidCaptureB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(x : Bool) → x@1
+ dhall-lang/tests/normalization/success/simple/letenumA.dhall view
@@ -0,0 +1,3 @@+let enum = < x >.x+in+merge { x = 1 } enum
+ dhall-lang/tests/normalization/success/simple/letenumB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/simple/letletA.dhall view
@@ -0,0 +1,3 @@+let l = λ(n : Natural) → λ(m : Natural) → λ(x : Natural) → n + m * x+let f = l 2 3+in  f 445
+ dhall-lang/tests/normalization/success/simple/letletB.dhall view
@@ -0,0 +1,1 @@+1337
+ dhall-lang/tests/normalization/success/simple/listBuildA.dhall view
@@ -0,0 +1,22 @@+{ example0 =+    List/build+    Bool+    (   λ(list : Type)+      → λ(cons : Bool → list → list)+      → λ(nil : list)+      → cons True (cons False nil)+    )+, example1 =+    List/build+    Bool+    (λ(x : Type) → λ(x : Bool → x → x) → λ(x : x@1) → x@1 True (x@1 False x))+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → List/build+      Bool+      (   λ(list : Type)+        → λ(cons : Bool → list → list)+        → λ(nil : list)+        → id list (cons True (cons False nil))+      )+}
+ dhall-lang/tests/normalization/success/simple/listBuildB.dhall view
@@ -0,0 +1,7 @@+{ example0 =+    [ True, False ]+, example1 =+    [ True, False ]+, example2 =+    λ(id : ∀(a : Type) → a → a) → id (List Bool) [ True, False ]+}
+ dhall-lang/tests/normalization/success/simple/multiLineA.dhall view
@@ -0,0 +1,4 @@+''+ foo+bar+''
+ dhall-lang/tests/normalization/success/simple/multiLineB.dhall view
@@ -0,0 +1,4 @@+''+ foo+bar+''
+ dhall-lang/tests/normalization/success/simple/naturalBuildA.dhall view
@@ -0,0 +1,18 @@+{ example0 =+    Natural/build+    (   λ(natural : Type)+      → λ(succ : natural → natural)+      → λ(zero : natural)+      → succ zero+    )+, example1 =+    Natural/build (λ(x : Type) → λ(x : x → x) → λ(x : x@1) → x@1 x)+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → Natural/build+      (   λ(natural : Type)+        → λ(succ : natural → natural)+        → λ(zero : natural)+        → id natural (succ zero)+      )+}
+ dhall-lang/tests/normalization/success/simple/naturalBuildB.dhall view
@@ -0,0 +1,7 @@+{ example0 =+    1+, example1 =+    1+, example2 =+    λ(id : ∀(a : Type) → a → a) → id Natural 1+}
+ dhall-lang/tests/normalization/success/simple/notEqualNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != True
+ dhall-lang/tests/normalization/success/simple/notEqualNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != True
+ dhall-lang/tests/normalization/success/simple/plusNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x + 1
+ dhall-lang/tests/normalization/success/simple/plusNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x + 1
+ dhall-lang/tests/normalization/success/simple/simpleAdditionA.dhall view
@@ -0,0 +1,1 @@+(\(x: Natural) -> x + 1) 0
+ dhall-lang/tests/normalization/success/simple/simpleAdditionB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/simple/sortOperatorA.dhall view
@@ -0,0 +1,1 @@+{ b = 2 } // { a = 1 }
+ dhall-lang/tests/normalization/success/simple/sortOperatorB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }
+ dhall-lang/tests/normalization/success/simple/timesNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 2
+ dhall-lang/tests/normalization/success/simple/timesNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 2
+ dhall-lang/tests/normalization/success/simplifications/andA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x && True+, example1 = λ(x : Bool) → True && x+, example2 = λ(x : Bool) → x && False+, example3 = λ(x : Bool) → False && x+, example4 = λ(x : Bool) → x && x+}
+ dhall-lang/tests/normalization/success/simplifications/andB.dhall view
@@ -0,0 +1,11 @@+{ example0 =+    λ(x : Bool) → x+, example1 =+    λ(x : Bool) → x+, example2 =+    λ(x : Bool) → False+, example3 =+    λ(x : Bool) → False+, example4 =+    λ(x : Bool) → x+}
+ dhall-lang/tests/normalization/success/simplifications/eqA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x == True+, example1 = λ(x : Bool) → True == x+, example2 = λ(x : Bool) → x == x+}
+ dhall-lang/tests/normalization/success/simplifications/eqB.dhall view
@@ -0,0 +1,7 @@+{ example0 =+    λ(x : Bool) → x+, example1 =+    λ(x : Bool) → x+, example2 =+    λ(x : Bool) → True+}
+ dhall-lang/tests/normalization/success/simplifications/ifThenElseA.dhall view
@@ -0,0 +1,3 @@+{ example0 = λ(x : Bool) → if x then True else False+, example1 = λ(x : Bool) → λ(y : Text) → if x then y else y+}
+ dhall-lang/tests/normalization/success/simplifications/ifThenElseB.dhall view
@@ -0,0 +1,1 @@+{ example0 = λ(x : Bool) → x, example1 = λ(x : Bool) → λ(y : Text) → y }
+ dhall-lang/tests/normalization/success/simplifications/issue661A.dhall view
@@ -0,0 +1,17 @@+let T1 = { a : Natural }+let T2 = { a : Natural, b : Text }+let T3 = { z : List { a : Natural, b : Text } }+let T4 = { z : List { b : Text, c : List Natural } }++let Prelude/List/map = ../../../../Prelude/List/map++let f = λ(old : T1) → old ⫽ { b = "Hello" }+let g = λ(old : T2) → { z = [ old, old.{ a } ⫽ { b = "Bye" } ] : List T2 }+let h_ = λ(old : T2) → old.{ b } ⫽ { c = [ old.a ] : List Natural }+let h =+        λ(old : T3)+      → { z = Prelude/List/map T2 { b : Text, c : List Natural } h_ old.z }++let k = λ(old : T1) → h (g (f old))++in k
+ dhall-lang/tests/normalization/success/simplifications/issue661B.dhall view
@@ -0,0 +1,2 @@+  λ(old : { a : Natural })+→ { z = [ { b = "Hello", c = [ old.a ] }, { b = "Bye", c = [ old.a ] } ] }
+ dhall-lang/tests/normalization/success/simplifications/neA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x != False+, example1 = λ(x : Bool) → False != x+, example2 = λ(x : Bool) → x != x+}
+ dhall-lang/tests/normalization/success/simplifications/neB.dhall view
@@ -0,0 +1,7 @@+{ example0 =+    λ(x : Bool) → x+, example1 =+    λ(x : Bool) → x+, example2 =+    λ(x : Bool) → False+}
+ dhall-lang/tests/normalization/success/simplifications/orA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x || True+, example1 = λ(x : Bool) → True || x+, example2 = λ(x : Bool) → x || False+, example3 = λ(x : Bool) → False || x+, example4 = λ(x : Bool) → x || x+}
+ dhall-lang/tests/normalization/success/simplifications/orB.dhall view
@@ -0,0 +1,11 @@+{ example0 =+    λ(x : Bool) → True+, example1 =+    λ(x : Bool) → True+, example2 =+    λ(x : Bool) → x+, example3 =+    λ(x : Bool) → x+, example4 =+    λ(x : Bool) → x+}
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).{ a, c }.c
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → 0
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).({ a : Bool, c : Natural }).a
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → x.a
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : {} }) → (x ⫽ { b = 0 } ∧ { a = { c = 1 } }).b
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : {} }) → 0
+ dhall-lang/tests/normalization/success/unit/AssertNormalizeArgumentA.dhall view
@@ -0,0 +1,1 @@+assert : (1 + 1) === (1 + 1)
+ dhall-lang/tests/normalization/success/unit/AssertNormalizeArgumentB.dhall view
@@ -0,0 +1,1 @@+assert : 2 ≡ 2
+ dhall-lang/tests/normalization/success/unit/BareInterpolationA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "${x}"
+ dhall-lang/tests/normalization/success/unit/BareInterpolationB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/BoolA.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/normalization/success/unit/BoolB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/normalization/success/unit/BytesA.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/normalization/success/unit/BytesB.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/normalization/success/unit/BytesLiteralA.dhall view
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
+ dhall-lang/tests/normalization/success/unit/BytesLiteralB.dhall view
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
+ dhall-lang/tests/normalization/success/unit/CompletionA.dhall view
@@ -0,0 +1,1 @@+{ default = {=}, Type = {} }::{=}
+ dhall-lang/tests/normalization/success/unit/CompletionB.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/DoubleA.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/normalization/success/unit/DoubleB.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/normalization/success/unit/DoubleLiteralA.dhall view
@@ -0,0 +1,1 @@+1.2
+ dhall-lang/tests/normalization/success/unit/DoubleLiteralB.dhall view
@@ -0,0 +1,1 @@+1.2
+ dhall-lang/tests/normalization/success/unit/DoubleShowA.dhall view
@@ -0,0 +1,1 @@+Double/show
+ dhall-lang/tests/normalization/success/unit/DoubleShowB.dhall view
@@ -0,0 +1,1 @@+Double/show
+ dhall-lang/tests/normalization/success/unit/DoubleShowValueA.dhall view
@@ -0,0 +1,1 @@+Double/show 1.2
+ dhall-lang/tests/normalization/success/unit/DoubleShowValueB.dhall view
@@ -0,0 +1,1 @@+"1.2"
+ dhall-lang/tests/normalization/success/unit/EmptyAlternativeA.dhall view
@@ -0,0 +1,1 @@+merge { x = 1, y = 2 } (< x | y >.x)
+ dhall-lang/tests/normalization/success/unit/EmptyAlternativeB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/unit/EmptyToMapA.dhall view
@@ -0,0 +1,1 @@+toMap {=} : List {mapKey : Text, mapValue : Natural}
+ dhall-lang/tests/normalization/success/unit/EmptyToMapB.dhall view
@@ -0,0 +1,1 @@+[] : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/normalization/success/unit/EquivalenceNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+(1 + 1) === (1 + 2)
+ dhall-lang/tests/normalization/success/unit/EquivalenceNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+2 ≡ 3
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationCaptureA.dhall view
@@ -0,0 +1,1 @@+(λ(_ : Bool) → λ(_ : Bool) → _@1) True False
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationCaptureB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationNoSubstituteA.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → (λ(x : Bool) → y) True
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationNoSubstituteB.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → y
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationNormalizeArgumentsA.dhall view
@@ -0,0 +1,3 @@+  λ(f : Bool → Natural)+→ λ(x : Bool)+→ (if True then f else f) (if True then x else x)
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(f : Bool → Natural) → λ(x : Bool) → f x
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationSubstituteA.dhall view
@@ -0,0 +1,1 @@+(λ(x : Bool) → x) True
+ dhall-lang/tests/normalization/success/unit/FunctionApplicationSubstituteB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/FunctionNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+let id = λ(X : Type) → X in λ(x : id Bool) → if True then x else x
+ dhall-lang/tests/normalization/success/unit/FunctionNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/FunctionTypeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+let id = λ(X : Type) → X in id Bool → id Natural
+ dhall-lang/tests/normalization/success/unit/FunctionTypeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool → Natural
+ dhall-lang/tests/normalization/success/unit/IfAlternativesIdenticalA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Natural) → if x then y else y
+ dhall-lang/tests/normalization/success/unit/IfAlternativesIdenticalB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Natural) → y
+ dhall-lang/tests/normalization/success/unit/IfFalseA.dhall view
@@ -0,0 +1,1 @@+if False then 1 else 2
+ dhall-lang/tests/normalization/success/unit/IfFalseB.dhall view
@@ -0,0 +1,1 @@+2
+ dhall-lang/tests/normalization/success/unit/IfNormalizePredicateAndBranchesA.dhall view
@@ -0,0 +1,4 @@+  λ(b : Bool)+→ λ(x : Natural)+→ λ(y : Natural)+→ if if True then b else b then if True then x else x else if True then y else y
+ dhall-lang/tests/normalization/success/unit/IfNormalizePredicateAndBranchesB.dhall view
@@ -0,0 +1,1 @@+λ(b : Bool) → λ(x : Natural) → λ(y : Natural) → if b then x else y
+ dhall-lang/tests/normalization/success/unit/IfTrivialA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → if x then True else False
+ dhall-lang/tests/normalization/success/unit/IfTrivialB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/IfTrueA.dhall view
@@ -0,0 +1,1 @@+if True then 1 else 2
+ dhall-lang/tests/normalization/success/unit/IfTrueB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/unit/IntegerA.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/normalization/success/unit/IntegerB.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/normalization/success/unit/IntegerClampA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/normalization/success/unit/IntegerClampB.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/normalization/success/unit/IntegerClampNegativeA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp -6
+ dhall-lang/tests/normalization/success/unit/IntegerClampNegativeB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/IntegerClampPositiveA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp +5
+ dhall-lang/tests/normalization/success/unit/IntegerClampPositiveB.dhall view
@@ -0,0 +1,1 @@+5
+ dhall-lang/tests/normalization/success/unit/IntegerClampZeroA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp +0
+ dhall-lang/tests/normalization/success/unit/IntegerClampZeroB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/IntegerNegateA.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/normalization/success/unit/IntegerNegateB.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/normalization/success/unit/IntegerNegateNegativeA.dhall view
@@ -0,0 +1,1 @@+Integer/negate -7
+ dhall-lang/tests/normalization/success/unit/IntegerNegateNegativeB.dhall view
@@ -0,0 +1,1 @@++7
+ dhall-lang/tests/normalization/success/unit/IntegerNegatePositiveA.dhall view
@@ -0,0 +1,1 @@+Integer/negate +3
+ dhall-lang/tests/normalization/success/unit/IntegerNegatePositiveB.dhall view
@@ -0,0 +1,1 @@+-3
+ dhall-lang/tests/normalization/success/unit/IntegerNegateZeroA.dhall view
@@ -0,0 +1,1 @@+Integer/negate +0
+ dhall-lang/tests/normalization/success/unit/IntegerNegateZeroB.dhall view
@@ -0,0 +1,1 @@++0
+ dhall-lang/tests/normalization/success/unit/IntegerNegativeA.dhall view
@@ -0,0 +1,1 @@+-1
+ dhall-lang/tests/normalization/success/unit/IntegerNegativeB.dhall view
@@ -0,0 +1,1 @@+-1
+ dhall-lang/tests/normalization/success/unit/IntegerPositiveA.dhall view
@@ -0,0 +1,1 @@++1
+ dhall-lang/tests/normalization/success/unit/IntegerPositiveB.dhall view
@@ -0,0 +1,1 @@++1
+ dhall-lang/tests/normalization/success/unit/IntegerShow-12A.dhall view
@@ -0,0 +1,1 @@+Integer/show -12
+ dhall-lang/tests/normalization/success/unit/IntegerShow-12B.dhall view
@@ -0,0 +1,1 @@+"-12"
+ dhall-lang/tests/normalization/success/unit/IntegerShow12A.dhall view
@@ -0,0 +1,1 @@+Integer/show +12
+ dhall-lang/tests/normalization/success/unit/IntegerShow12B.dhall view
@@ -0,0 +1,1 @@+"+12"
+ dhall-lang/tests/normalization/success/unit/IntegerShowA.dhall view
@@ -0,0 +1,1 @@+Integer/show
+ dhall-lang/tests/normalization/success/unit/IntegerShowB.dhall view
@@ -0,0 +1,1 @@+Integer/show
+ dhall-lang/tests/normalization/success/unit/IntegerToDouble-12A.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble -12
+ dhall-lang/tests/normalization/success/unit/IntegerToDouble-12B.dhall view
@@ -0,0 +1,1 @@+-12.0
+ dhall-lang/tests/normalization/success/unit/IntegerToDouble12A.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble +12
+ dhall-lang/tests/normalization/success/unit/IntegerToDouble12B.dhall view
@@ -0,0 +1,1 @@+12.0
+ dhall-lang/tests/normalization/success/unit/IntegerToDoubleA.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble
+ dhall-lang/tests/normalization/success/unit/IntegerToDoubleB.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble
+ dhall-lang/tests/normalization/success/unit/KindA.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/normalization/success/unit/KindB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/normalization/success/unit/LetA.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → let x = y in x
+ dhall-lang/tests/normalization/success/unit/LetB.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → y
+ dhall-lang/tests/normalization/success/unit/LetWithTypeA.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → let x : Bool = y in x
+ dhall-lang/tests/normalization/success/unit/LetWithTypeB.dhall view
@@ -0,0 +1,1 @@+λ(y : Bool) → y
+ dhall-lang/tests/normalization/success/unit/ListA.dhall view
@@ -0,0 +1,1 @@+List
+ dhall-lang/tests/normalization/success/unit/ListB.dhall view
@@ -0,0 +1,1 @@+List
+ dhall-lang/tests/normalization/success/unit/ListBuildA.dhall view
@@ -0,0 +1,1 @@+List/build
+ dhall-lang/tests/normalization/success/unit/ListBuildB.dhall view
@@ -0,0 +1,1 @@+List/build
+ dhall-lang/tests/normalization/success/unit/ListBuildFoldFusionA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → List/build T (List/fold T x)
+ dhall-lang/tests/normalization/success/unit/ListBuildFoldFusionB.dhall view
@@ -0,0 +1,8 @@+  λ(T : Type)+→ λ(x : List T)+→ List/fold+    T+    x+    (List T)+    (λ(a : T) → λ(`as` : List T) → [ a ] # `as`)+    ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListBuildImplementationA.dhall view
@@ -0,0 +1,3 @@+  λ(T : Type)+→ λ(f : ∀(list : Type) → (T → list → list) → list → list)+→ List/build T f
+ dhall-lang/tests/normalization/success/unit/ListBuildImplementationB.dhall view
@@ -0,0 +1,3 @@+  λ(T : Type)+→ λ(f : ∀(list : Type) → (T → list → list) → list → list)+→ f (List T) (λ(a : T) → λ(`as` : List T) → [ a ] # `as`) ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListFoldA.dhall view
@@ -0,0 +1,1 @@+List/fold
+ dhall-lang/tests/normalization/success/unit/ListFoldB.dhall view
@@ -0,0 +1,1 @@+List/fold
+ dhall-lang/tests/normalization/success/unit/ListFoldEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool → Bool) → List/fold T ([] : List T) Bool f True
+ dhall-lang/tests/normalization/success/unit/ListFoldEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool → Bool) → True
+ dhall-lang/tests/normalization/success/unit/ListFoldOneA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool → Bool) → λ(x : T) → List/fold T [ x ] Bool f True
+ dhall-lang/tests/normalization/success/unit/ListFoldOneB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool → Bool) → λ(x : T) → f x True
+ dhall-lang/tests/normalization/success/unit/ListHeadA.dhall view
@@ -0,0 +1,1 @@+List/head
+ dhall-lang/tests/normalization/success/unit/ListHeadB.dhall view
@@ -0,0 +1,1 @@+List/head
+ dhall-lang/tests/normalization/success/unit/ListHeadEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → List/head T ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListHeadEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → None T
+ dhall-lang/tests/normalization/success/unit/ListHeadTwoA.dhall view
@@ -0,0 +1,1 @@+List/head Natural [ 1, 2 ]
+ dhall-lang/tests/normalization/success/unit/ListHeadTwoB.dhall view
@@ -0,0 +1,1 @@+Some 1
+ dhall-lang/tests/normalization/success/unit/ListIndexedA.dhall view
@@ -0,0 +1,1 @@+List/indexed
+ dhall-lang/tests/normalization/success/unit/ListIndexedB.dhall view
@@ -0,0 +1,1 @@+List/indexed
+ dhall-lang/tests/normalization/success/unit/ListIndexedEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → List/indexed T ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListIndexedEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → [] : List { index : Natural, value : T }
+ dhall-lang/tests/normalization/success/unit/ListIndexedOneA.dhall view
@@ -0,0 +1,1 @@+List/indexed Natural [ 1 ]
+ dhall-lang/tests/normalization/success/unit/ListIndexedOneB.dhall view
@@ -0,0 +1,1 @@+[ { index = 0, value = 1 } ]
+ dhall-lang/tests/normalization/success/unit/ListLastA.dhall view
@@ -0,0 +1,1 @@+List/last
+ dhall-lang/tests/normalization/success/unit/ListLastB.dhall view
@@ -0,0 +1,1 @@+List/last
+ dhall-lang/tests/normalization/success/unit/ListLastEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → List/last T ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListLastEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → None T
+ dhall-lang/tests/normalization/success/unit/ListLastTwoA.dhall view
@@ -0,0 +1,1 @@+List/last Natural [ 1, 2 ]
+ dhall-lang/tests/normalization/success/unit/ListLastTwoB.dhall view
@@ -0,0 +1,1 @@+Some 2
+ dhall-lang/tests/normalization/success/unit/ListLengthA.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/normalization/success/unit/ListLengthB.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/normalization/success/unit/ListLengthEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → List/length T ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListLengthEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → 0
+ dhall-lang/tests/normalization/success/unit/ListLengthOneA.dhall view
@@ -0,0 +1,1 @@+List/length Natural [ 1 ]
+ dhall-lang/tests/normalization/success/unit/ListLengthOneB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/unit/ListNormalizeElementsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → [ if True then x else x ]
+ dhall-lang/tests/normalization/success/unit/ListNormalizeElementsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → [ x ]
+ dhall-lang/tests/normalization/success/unit/ListNormalizeTypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+[] : { x = List Bool }.x
+ dhall-lang/tests/normalization/success/unit/ListNormalizeTypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+[] : List Bool
+ dhall-lang/tests/normalization/success/unit/ListReverseA.dhall view
@@ -0,0 +1,1 @@+List/reverse
+ dhall-lang/tests/normalization/success/unit/ListReverseB.dhall view
@@ -0,0 +1,1 @@+List/reverse
+ dhall-lang/tests/normalization/success/unit/ListReverseEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → List/reverse T ([] : List T)
+ dhall-lang/tests/normalization/success/unit/ListReverseEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → [] : List T
+ dhall-lang/tests/normalization/success/unit/ListReverseTwoA.dhall view
@@ -0,0 +1,1 @@+List/reverse Natural [ 1, 2 ]
+ dhall-lang/tests/normalization/success/unit/ListReverseTwoB.dhall view
@@ -0,0 +1,1 @@+[ 2, 1 ]
+ dhall-lang/tests/normalization/success/unit/MergeA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → merge { a = f } (< a : T >.a x)
+ dhall-lang/tests/normalization/success/unit/MergeB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → f x
+ dhall-lang/tests/normalization/success/unit/MergeEmptyAlternativeA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → merge { a = x } < a >.a
+ dhall-lang/tests/normalization/success/unit/MergeEmptyAlternativeB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/MergeNoneA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (None Bool)
+ dhall-lang/tests/normalization/success/unit/MergeNoneB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/unit/MergeNormalizeArgumentsA.dhall view
@@ -0,0 +1,3 @@+  λ(x : { a : Bool })+→ λ(y : < a >)+→ merge (if True then x else x) (if True then y else y)
+ dhall-lang/tests/normalization/success/unit/MergeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : < a >) → merge x y
+ dhall-lang/tests/normalization/success/unit/MergeSomeA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (Some True)
+ dhall-lang/tests/normalization/success/unit/MergeSomeB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/MergeWithTypeA.dhall view
@@ -0,0 +1,4 @@+  λ(T : Type)+→ λ(f : T → Bool)+→ λ(x : T)+→ merge { a = f } (< a : T >.a x) : Bool
+ dhall-lang/tests/normalization/success/unit/MergeWithTypeB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → f x
+ dhall-lang/tests/normalization/success/unit/MergeWithTypeNormalizeArgumentsA.dhall view
@@ -0,0 +1,5 @@+let id = λ(X : Type) → X++in    λ(x : { a : Bool })+    → λ(y : < a >)+    → merge (if True then x else x) (if True then y else y) : id Bool
+ dhall-lang/tests/normalization/success/unit/MergeWithTypeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : < a >) → merge x y : Bool
+ dhall-lang/tests/normalization/success/unit/NaturalA.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/normalization/success/unit/NaturalB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/normalization/success/unit/NaturalBuildA.dhall view
@@ -0,0 +1,1 @@+Natural/build
+ dhall-lang/tests/normalization/success/unit/NaturalBuildB.dhall view
@@ -0,0 +1,1 @@+Natural/build
+ dhall-lang/tests/normalization/success/unit/NaturalBuildFoldFusionA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/build (Natural/fold x)
+ dhall-lang/tests/normalization/success/unit/NaturalBuildFoldFusionB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/fold x Natural (λ(x : Natural) → x + 1) 0
+ dhall-lang/tests/normalization/success/unit/NaturalBuildImplementationA.dhall view
@@ -0,0 +1,2 @@+  λ(f : ∀(natural : Type) → (natural → natural) → natural → natural)+→ Natural/build f
+ dhall-lang/tests/normalization/success/unit/NaturalBuildImplementationB.dhall view
@@ -0,0 +1,2 @@+  λ(f : ∀(natural : Type) → (natural → natural) → natural → natural)+→ f Natural (λ(x : Natural) → x + 1) 0
+ dhall-lang/tests/normalization/success/unit/NaturalEvenA.dhall view
@@ -0,0 +1,1 @@+Natural/even
+ dhall-lang/tests/normalization/success/unit/NaturalEvenB.dhall view
@@ -0,0 +1,1 @@+Natural/even
+ dhall-lang/tests/normalization/success/unit/NaturalEvenOneA.dhall view
@@ -0,0 +1,1 @@+Natural/even 1
+ dhall-lang/tests/normalization/success/unit/NaturalEvenOneB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/unit/NaturalEvenZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/even 0
+ dhall-lang/tests/normalization/success/unit/NaturalEvenZeroB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/NaturalFoldA.dhall view
@@ -0,0 +1,1 @@+Natural/fold
+ dhall-lang/tests/normalization/success/unit/NaturalFoldB.dhall view
@@ -0,0 +1,1 @@+Natural/fold
+ dhall-lang/tests/normalization/success/unit/NaturalFoldOneA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Natural/fold 1 Bool (λ(_ : Bool) → True) x
+ dhall-lang/tests/normalization/success/unit/NaturalFoldOneB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True
+ dhall-lang/tests/normalization/success/unit/NaturalFoldZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Natural/fold 0 Bool (λ(_ : Bool) → True) x
+ dhall-lang/tests/normalization/success/unit/NaturalFoldZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/isZero
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroB.dhall view
@@ -0,0 +1,1 @@+Natural/isZero
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroOneA.dhall view
@@ -0,0 +1,1 @@+Natural/isZero 1
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroOneB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/isZero 0
+ dhall-lang/tests/normalization/success/unit/NaturalIsZeroZeroB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/NaturalLiteralA.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/unit/NaturalLiteralB.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/normalization/success/unit/NaturalOddA.dhall view
@@ -0,0 +1,1 @@+Natural/odd
+ dhall-lang/tests/normalization/success/unit/NaturalOddB.dhall view
@@ -0,0 +1,1 @@+Natural/odd
+ dhall-lang/tests/normalization/success/unit/NaturalOddOneA.dhall view
@@ -0,0 +1,1 @@+Natural/odd 1
+ dhall-lang/tests/normalization/success/unit/NaturalOddOneB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/NaturalOddZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/odd 0
+ dhall-lang/tests/normalization/success/unit/NaturalOddZeroB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/unit/NaturalShowA.dhall view
@@ -0,0 +1,1 @@+Natural/show
+ dhall-lang/tests/normalization/success/unit/NaturalShowB.dhall view
@@ -0,0 +1,1 @@+Natural/show
+ dhall-lang/tests/normalization/success/unit/NaturalShowOneA.dhall view
@@ -0,0 +1,1 @@+Natural/show 1
+ dhall-lang/tests/normalization/success/unit/NaturalShowOneB.dhall view
@@ -0,0 +1,1 @@+"1"
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractEquivalentA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract x x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractEquivalentB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractFromZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract x 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractFromZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractGreaterA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 3 10
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractGreaterB.dhall view
@@ -0,0 +1,1 @@+7
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractLessA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 3 2
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractLessB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractNormalizeA.dhall view
@@ -0,0 +1,3 @@+  λ(x : Natural)+→ λ(y : Natural)+→ Natural/subtract (if True then x else y) (10 + 20)
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractNormalizeB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → Natural/subtract x 30
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero0A.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract 0 x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero0B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero1A.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero1B.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 0
+ dhall-lang/tests/normalization/success/unit/NaturalToIntegerA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger
+ dhall-lang/tests/normalization/success/unit/NaturalToIntegerB.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger
+ dhall-lang/tests/normalization/success/unit/NaturalToIntegerOneA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger 1
+ dhall-lang/tests/normalization/success/unit/NaturalToIntegerOneB.dhall view
@@ -0,0 +1,1 @@++1
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }.{ a }
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a }
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionByTypeA.dhall view
@@ -0,0 +1,2 @@+  λ(x : { a : Bool, b : Bool, c : Bool })+→ x.({ a : Bool, b : Bool }).({ a : Bool })
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionByTypeB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a }
+ dhall-lang/tests/normalization/success/unit/NoneA.dhall view
@@ -0,0 +1,1 @@+None
+ dhall-lang/tests/normalization/success/unit/NoneB.dhall view
@@ -0,0 +1,1 @@+None
+ dhall-lang/tests/normalization/success/unit/OperatorAndEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x && x
+ dhall-lang/tests/normalization/success/unit/OperatorAndEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorAndLhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False && x
+ dhall-lang/tests/normalization/success/unit/OperatorAndLhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False
+ dhall-lang/tests/normalization/success/unit/OperatorAndLhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True && x
+ dhall-lang/tests/normalization/success/unit/OperatorAndLhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorAndNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → True && x && (True && y)
+ dhall-lang/tests/normalization/success/unit/OperatorAndNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → x && y
+ dhall-lang/tests/normalization/success/unit/OperatorAndRhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x && False
+ dhall-lang/tests/normalization/success/unit/OperatorAndRhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False
+ dhall-lang/tests/normalization/success/unit/OperatorAndRhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x && True
+ dhall-lang/tests/normalization/success/unit/OperatorAndRhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorEqualEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == x
+ dhall-lang/tests/normalization/success/unit/OperatorEqualEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True
+ dhall-lang/tests/normalization/success/unit/OperatorEqualLhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == True
+ dhall-lang/tests/normalization/success/unit/OperatorEqualLhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → True == x == (True == y)
+ dhall-lang/tests/normalization/success/unit/OperatorEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → x == y
+ dhall-lang/tests/normalization/success/unit/OperatorEqualRhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True == x
+ dhall-lang/tests/normalization/success/unit/OperatorEqualRhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → x # ([] : List T)
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → x
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateListListA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : T) → λ(y : T) → [ x ] # [ y ]
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateListListB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : T) → λ(y : T) → [ x, y ]
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateNormalizeArgumentsA.dhall view
@@ -0,0 +1,4 @@+  λ(T : Type)+→ λ(x : List T)+→ λ(y : List T)+→ ([] : List T) # x # (([] : List T) # y)
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → λ(y : List T) → x # y
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → ([] : List T) # x
+ dhall-lang/tests/normalization/success/unit/OperatorListConcatenateRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → λ(x : List T) → x
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != x
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualLhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False != x
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualLhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → False != x != (False != y)
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → x != y
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualRhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != False
+ dhall-lang/tests/normalization/success/unit/OperatorNotEqualRhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorOrEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x || x
+ dhall-lang/tests/normalization/success/unit/OperatorOrEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorOrLhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → False || x
+ dhall-lang/tests/normalization/success/unit/OperatorOrLhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorOrLhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True || x
+ dhall-lang/tests/normalization/success/unit/OperatorOrLhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True
+ dhall-lang/tests/normalization/success/unit/OperatorOrNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → False || x || (False || y)
+ dhall-lang/tests/normalization/success/unit/OperatorOrNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → x || y
+ dhall-lang/tests/normalization/success/unit/OperatorOrRhsFalseA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x || False
+ dhall-lang/tests/normalization/success/unit/OperatorOrRhsFalseB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/OperatorOrRhsTrueA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x || True
+ dhall-lang/tests/normalization/success/unit/OperatorOrRhsTrueB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → True
+ dhall-lang/tests/normalization/success/unit/OperatorPlusLhsZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0 + x
+ dhall-lang/tests/normalization/success/unit/OperatorPlusLhsZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/OperatorPlusNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → 0 + x + (0 + y)
+ dhall-lang/tests/normalization/success/unit/OperatorPlusNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → x + y
+ dhall-lang/tests/normalization/success/unit/OperatorPlusOneAndOneA.dhall view
@@ -0,0 +1,1 @@+1 + 1
+ dhall-lang/tests/normalization/success/unit/OperatorPlusOneAndOneB.dhall view
@@ -0,0 +1,1 @@+2
+ dhall-lang/tests/normalization/success/unit/OperatorPlusRhsZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x + 0
+ dhall-lang/tests/normalization/success/unit/OperatorPlusRhsZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "" ++ x
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsNonEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "hai" ++ x
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsNonEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "hai${x}"
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x ++ ""
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsNonEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x ++ "hai"
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsNonEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "${x}hai"
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateTextTextA.dhall view
@@ -0,0 +1,1 @@+"x" ++ "y"
+ dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateTextTextB.dhall view
@@ -0,0 +1,1 @@+"xy"
+ dhall-lang/tests/normalization/success/unit/OperatorTimesLhsOneA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 1 * x
+ dhall-lang/tests/normalization/success/unit/OperatorTimesLhsOneB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/OperatorTimesLhsZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0 * x
+ dhall-lang/tests/normalization/success/unit/OperatorTimesLhsZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/OperatorTimesNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → 1 * x * (1 * y)
+ dhall-lang/tests/normalization/success/unit/OperatorTimesNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → x * y
+ dhall-lang/tests/normalization/success/unit/OperatorTimesRhsOneA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 1
+ dhall-lang/tests/normalization/success/unit/OperatorTimesRhsOneB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/OperatorTimesRhsZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 0
+ dhall-lang/tests/normalization/success/unit/OperatorTimesRhsZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/OperatorTimesTwoAndTwoA.dhall view
@@ -0,0 +1,1 @@+2 * 2
+ dhall-lang/tests/normalization/success/unit/OperatorTimesTwoAndTwoB.dhall view
@@ -0,0 +1,1 @@+4
+ dhall-lang/tests/normalization/success/unit/OptionalA.dhall view
@@ -0,0 +1,1 @@+Optional
+ dhall-lang/tests/normalization/success/unit/OptionalB.dhall view
@@ -0,0 +1,1 @@+Optional
+ dhall-lang/tests/normalization/success/unit/RecordA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → { a = if True then x else x, b = x }
+ dhall-lang/tests/normalization/success/unit/RecordB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → { a = x, b = x }
+ dhall-lang/tests/normalization/success/unit/RecordEmptyA.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/RecordEmptyB.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/RecordLitAllSugarsA.dhall view
@@ -0,0 +1,1 @@+let x = { y = 1 } in { x, x.z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitAllSugarsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 1, z = 2 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x.y.z = True }
+ dhall-lang/tests/normalization/success/unit/RecordLitDottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = { z = True } } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDuplicateFieldsNoCollisionsA.dhall view
@@ -0,0 +1,9 @@+{-  This expression desugars to:++        { x = { y = 0 } ∧ { z = 0 } }++    ... which then β-normalizes to:++        { x = { y = 0, z = 0 } }+-}+{ x = { y = 0 }, x = { z = 0 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDuplicateFieldsNoCollisionsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 0, z = 0 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitNixLikeA.dhall view
@@ -0,0 +1,4 @@+{- The purpose of this test is to verify that the Nix-like idiom of setting+   multiple overlapping dotted fields works correctly+-}+{ x.y = 1, x.z = True }
+ dhall-lang/tests/normalization/success/unit/RecordLitNixLikeB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 1, z = True } }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun1A.dhall view
@@ -0,0 +1,1 @@+let x = 0 in { x }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun1B.dhall view
@@ -0,0 +1,1 @@+{ x = 0 }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun2A.dhall view
@@ -0,0 +1,1 @@+let x = 0 let y = 1 in { x, y, z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun2B.dhall view
@@ -0,0 +1,1 @@+{ x = 0, y = 1, z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitTriplicateFieldsA.dhall view
@@ -0,0 +1,7 @@+{-  This test ensures that an implementation handles more than one duplicate+    field correctly and combines them with the correct order and associativity+-}+  λ(a : { x : Natural })+→ λ(b : { y : Natural })+→ λ(c : { z : Natural })+→ { k = a, k = b, k = c }
+ dhall-lang/tests/normalization/success/unit/RecordLitTriplicateFieldsB.dhall view
@@ -0,0 +1,4 @@+  λ(a : { x : Natural })+→ λ(b : { y : Natural })+→ λ(c : { z : Natural })+→ { k = a ∧ b ∧ c }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionA.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = 2, z = 3 }.{ x, z }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionB.dhall view
@@ -0,0 +1,1 @@+{ x = 1, z = 3 }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10 }.({})
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNonEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10, c = [ "text" ]}.({ a : Natural, b : Optional Natural })
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNonEmptyB.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10 }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNormalizeProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.({ a : Bool, b : Bool })
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNormalizeProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeWithinFieldSelectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.({ a : Bool, b : Bool }).a
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeWithinFieldSelectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.a
+ dhall-lang/tests/normalization/success/unit/RecordProjectionEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x.{}
+ dhall-lang/tests/normalization/success/unit/RecordProjectionEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → {=}
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → (if True then x else x).{ a, b }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeFieldsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ c, a }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeFieldsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, c }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionWithinFieldSelectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }.a
+ dhall-lang/tests/normalization/success/unit/RecordProjectionWithinFieldSelectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.a
+ dhall-lang/tests/normalization/success/unit/RecordSelectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → { a = x }.a
+ dhall-lang/tests/normalization/success/unit/RecordSelectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/RecordSelectionNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { a : Bool }) → (if True then x else y).a
+ dhall-lang/tests/normalization/success/unit/RecordSelectionNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x.a
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b = 1, a = 0 }
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a = 0, b = 1 }
+ dhall-lang/tests/normalization/success/unit/RecordTypeA.dhall view
@@ -0,0 +1,1 @@+let id = λ(X : Type) → X in λ(T : Type) → { a : id Bool, b : T }
+ dhall-lang/tests/normalization/success/unit/RecordTypeB.dhall view
@@ -0,0 +1,1 @@+λ(T : Type) → { a : Bool, b : T }
+ dhall-lang/tests/normalization/success/unit/RecordTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/normalization/success/unit/RecordTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b : Bool, a : Natural }
+ dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Bool }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x = { z = 1 } } ∧ { x = { y = 2 } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeCollisionB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 2, z = 1 } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → {=} ∧ x
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNoCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = 1 } } ∧ { y = { b = 2 } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNoCollisionB.dhall view
@@ -0,0 +1,1 @@+{ x = { a = 1 }, y = { b = 2 } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { b : Bool }) → x ∧ {=} ∧ ({=} ∧ y)
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { b : Bool }) → x ∧ y
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x ∧ {=}
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → (x ∧ { a = 0, b = 1 }).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → (x ∧ { a = 0 }).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → (x ∧ { a = 1 }).b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection2A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → ({ a = 1 } ∧ x).b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection2B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection3A.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → ({ a = 0, b = 1 } ∧ x).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection3B.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → ({ a = 0 } ∧ x).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x : { z : Bool } } ⩓ { x : { y : Natural } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeCollisionB.dhall view
@@ -0,0 +1,1 @@+{ x : { y : Natural, z : Bool } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeDeepA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool } } } ⩓ { a : { b : { y : Bool } } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeDeepB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool, y : Bool } } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{} ⩓ { a : Bool }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ a : Bool }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNoCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool } } ⩓ { y : { b : Natural } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNoCollisionB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool }, y : { b : Natural } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+{ a : Bool } ⩓ {} ⩓ ({} ⩓ { b : Bool })
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+{ a : Bool, b : Bool }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a : Bool } ⩓ {}
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ a : Bool }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeSortsA.dhall view
@@ -0,0 +1,1 @@+{ a : Kind } ⩓ { b : Kind }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeSortsB.dhall view
@@ -0,0 +1,1 @@+{ a : Kind, b : Kind }
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x ⫽ x
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → (x ⫽ { a = 0 }).a
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → 0
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → (x ⫽ { a = 0 }).b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection2A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → λ(y : Bool) → ({ a = y } ⫽ x).b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection2B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → λ(y : Bool) → x.b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection3A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → ({ a = 0, b = 1 } ⫽ x).a
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection3B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → ({ a = 0 } ⫽ x).a
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = 2 } ⫽ { x = 2 }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeCollisionB.dhall view
@@ -0,0 +1,1 @@+{ x = 2, y = 2 }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → {=} ⫽ x
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNoCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = 2 } ⫽ { a = 2 }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNoCollisionB.dhall view
@@ -0,0 +1,1 @@+{ a = 2, x = 1, y = 2 }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x ⫽ {=} ⫽ (y ⫽ {=})
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x ⫽ y
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x ⫽ {=}
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeWithinRecordProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Natural }) → (x ⫽ { a = 1, b = 2 }).{ a, c }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeWithinRecordProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Natural }) → x.{ c } ⫽ { a = 1 }
+ dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor <A>.A
+ dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyB.dhall view
@@ -0,0 +1,1 @@+"A"
+ dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
+ dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyB.dhall view
@@ -0,0 +1,1 @@+"A"
+ dhall-lang/tests/normalization/success/unit/SomeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → Some (if True then x else y)
+ dhall-lang/tests/normalization/success/unit/SomeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → λ(y : Bool) → Some x
+ dhall-lang/tests/normalization/success/unit/SortA.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/normalization/success/unit/SortB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/normalization/success/unit/TextA.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/normalization/success/unit/TextB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/normalization/success/unit/TextInterpolateA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "s${"b${x}"}"
+ dhall-lang/tests/normalization/success/unit/TextInterpolateB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "sb${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested1A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${""}${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested1B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/TextLitNested2A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${"${x}"}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested2B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/TextLitNested3A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${"${""}"}${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested3B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/TextLiteralA.dhall view
@@ -0,0 +1,1 @@+"s"
+ dhall-lang/tests/normalization/success/unit/TextLiteralB.dhall view
@@ -0,0 +1,1 @@+"s"
+ dhall-lang/tests/normalization/success/unit/TextNormalizeInterpolationsA.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → λ(y : Text) → "s${if True then x else y}"
+ dhall-lang/tests/normalization/success/unit/TextNormalizeInterpolationsB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → λ(y : Text) → "s${x}"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation works with an abstract "replacement".+-}+λ(x : Text) → Text/replace "a" "-${x}-" "_a__a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "_-${x}-__-${x}-_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackA.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation does not beta normalize with an+   abstract "haystack".+-}+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1A.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1B.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2A.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+  Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2B.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+  Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3A.dhall view
@@ -0,0 +1,3 @@+λ(replacement : Text) →+λ(haystack : Text) →+  Text/replace "" replacement haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3B.dhall view
@@ -0,0 +1,1 @@+λ(replacement : Text) → λ(haystack : Text) → haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceMultipleA.dhall view
@@ -0,0 +1,1 @@+Text/replace "foo" "bar" "foobazfoo"
+ dhall-lang/tests/normalization/success/unit/TextReplaceMultipleB.dhall view
@@ -0,0 +1,1 @@+"barbazbar"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNFCUnicodeA.dhall view
@@ -0,0 +1,1 @@+Text/replace "👨" "👩" "👨‍👩‍👧‍👦"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNFCUnicodeB.dhall view
@@ -0,0 +1,1 @@+"👩‍👩‍👧‍👦"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNormalizationA.dhall view
@@ -0,0 +1,3 @@+-- This test verifies that implementations do not perform Unicode normalization+-- before substitution.+Text/replace "a\u{0301}" "b" "\u{00e1}c"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNormalizationB.dhall view
@@ -0,0 +1,1 @@+"ác"
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingA.dhall view
@@ -0,0 +1,1 @@+Text/replace "aa" "b" "aaaaa"
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingB.dhall view
@@ -0,0 +1,1 @@+"bba"
+ dhall-lang/tests/normalization/success/unit/TextReplaceSimpleA.dhall view
@@ -0,0 +1,1 @@+Text/replace "foo" "bar" "foo"
+ dhall-lang/tests/normalization/success/unit/TextReplaceSimpleB.dhall view
@@ -0,0 +1,1 @@+"bar"
+ dhall-lang/tests/normalization/success/unit/TextReplaceUnicodeA.dhall view
@@ -0,0 +1,1 @@+Text/replace "💣" "💥" "💣💣💣"
+ dhall-lang/tests/normalization/success/unit/TextReplaceUnicodeB.dhall view
@@ -0,0 +1,1 @@+"💥💥💥"
+ dhall-lang/tests/normalization/success/unit/TextReplaceVarA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation works with a variable as "replacement".+-}+λ(x : Text) → Text/replace "a" x "aaa"
+ dhall-lang/tests/normalization/success/unit/TextReplaceVarB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "${x}${x}${x}"
+ dhall-lang/tests/normalization/success/unit/TextShowA.dhall view
@@ -0,0 +1,1 @@+Text/show
+ dhall-lang/tests/normalization/success/unit/TextShowAllEscapesA.dhall view
@@ -0,0 +1,1 @@+Text/show "\"\$\\\b\f\n\r\tツa\u0007b\u0010c"
+ dhall-lang/tests/normalization/success/unit/TextShowAllEscapesB.dhall view
@@ -0,0 +1,1 @@+"\"\\\"\\u0024\\\\\\b\\f\\n\\r\\tツa\\u0007b\\u0010c\""
+ dhall-lang/tests/normalization/success/unit/TextShowB.dhall view
@@ -0,0 +1,1 @@+Text/show
+ dhall-lang/tests/normalization/success/unit/TextShowEmptyA.dhall view
@@ -0,0 +1,1 @@+Text/show ""
+ dhall-lang/tests/normalization/success/unit/TextShowEmptyB.dhall view
@@ -0,0 +1,1 @@+"\"\""
+ dhall-lang/tests/normalization/success/unit/TextShowInterpolatedA.dhall view
@@ -0,0 +1,1 @@+λ(containing : Text) → Text/show "text ${containing} interpolation"
+ dhall-lang/tests/normalization/success/unit/TextShowInterpolatedB.dhall view
@@ -0,0 +1,1 @@+λ(containing: Text) → Text/show "text ${containing} interpolation"
+ dhall-lang/tests/normalization/success/unit/TimeAsRecordA.dhall view
@@ -0,0 +1,2 @@+-- Timestamps are records, and this is a no-op+2000-01-01T12:00:00+08:00.{ time, date, timeZone }
+ dhall-lang/tests/normalization/success/unit/TimeAsRecordB.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
+ dhall-lang/tests/normalization/success/unit/ToMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/normalization/success/unit/ToMapB.dhall view
@@ -0,0 +1,4 @@+[ { mapKey = "bar", mapValue = 4 }+, { mapKey = "baz", mapValue = 9 }+, { mapKey = "foo", mapValue = 1 }+]
+ dhall-lang/tests/normalization/success/unit/ToMapWithTypeA.dhall view
@@ -0,0 +1,16 @@+{- This test verifies that the normalized result does not contain a type+   annotation if the input record is non-empty.++   The reason for this test is that implementations might need to store+   optional type annotations for both `toMap` invocations and empty list+   literals.  If an implementation does so, a common mistake is to take+   the optional type annotation and always pass it through as the optional+   type annotation for the list literal that `toMap` generates.++   However, the standard specifies that `toMap` should only generate a+   type annotation if the input record is empty.  If the input record is+   non-empty then the resulting normalized list is non-empty and therefore+   should not have a type annotation (since a non-empty list with a type+   annotation is not in normal form).+-}+toMap { foo= 1, bar= 4, baz= 9 } : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/normalization/success/unit/ToMapWithTypeB.dhall view
@@ -0,0 +1,4 @@+[ { mapKey = "bar", mapValue = 4 }+, { mapKey = "baz", mapValue = 9 }+, { mapKey = "foo", mapValue = 1 }+]
+ dhall-lang/tests/normalization/success/unit/TrueA.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/TrueB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/normalization/success/unit/TypeA.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/normalization/success/unit/TypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x : Bool
+ dhall-lang/tests/normalization/success/unit/TypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/TypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/normalization/success/unit/UnionProjectConstructorA.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.x
+ dhall-lang/tests/normalization/success/unit/UnionProjectConstructorB.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.x
+ dhall-lang/tests/normalization/success/unit/UnionTypeA.dhall view
@@ -0,0 +1,1 @@+< x : Bool | z >
+ dhall-lang/tests/normalization/success/unit/UnionTypeB.dhall view
@@ -0,0 +1,1 @@+< x : Bool | z >
+ dhall-lang/tests/normalization/success/unit/UnionTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+<>
+ dhall-lang/tests/normalization/success/unit/UnionTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+<>
+ dhall-lang/tests/normalization/success/unit/UnionTypeNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+let id = λ(X : Type) → X in < x : id Bool | z >
+ dhall-lang/tests/normalization/success/unit/UnionTypeNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+< x : Bool | z >
+ dhall-lang/tests/normalization/success/unit/VariableA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/VariableB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/WithA.dhall view
@@ -0,0 +1,1 @@+{ a = 1 } with b = 2
+ dhall-lang/tests/normalization/success/unit/WithB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }
+ dhall-lang/tests/normalization/success/unit/WithChainedA.dhall view
@@ -0,0 +1,4 @@+{-  This test verifies that an implementation correctly handles chained+    `with` expressions+-}+{ a = 1 } with b = 2 with c = 3
+ dhall-lang/tests/normalization/success/unit/WithChainedB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2, c = 3 }
+ dhall-lang/tests/normalization/success/unit/WithCreateIntermediateRecordsA.dhall view
@@ -0,0 +1,3 @@+{- This test illustrates that if an intermediate record does+   not exist, the `with` operator can create one -}+{ a = 5 } with b.c = 10
+ dhall-lang/tests/normalization/success/unit/WithCreateIntermediateRecordsB.dhall view
@@ -0,0 +1,1 @@+{ a = 5, b.c = 10 }
+ dhall-lang/tests/normalization/success/unit/WithDesugarA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation no longer implements the old desugaring (pre-v19.0.0)+-}+\(x: { a : { b : { c : {} } }}) -> x with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithDesugarB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : { b : { c : {} } } }) → x with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithNestedA.dhall view
@@ -0,0 +1,12 @@+{-  This test verifies that an implementation handles `with` expressions that+    update nested labels correctly++    A common mistake an implementation might make is to produce the following+    result:++        { a.c = 2 }++    ... due to the nested update clobbering the inner record.  A compliant+    implementation extends inner records.+-}+{ a.b = 1 } with a.c = 2
+ dhall-lang/tests/normalization/success/unit/WithNestedB.dhall view
@@ -0,0 +1,1 @@+{ a = { b = 1, c = 2 } }
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneA.dhall view
@@ -0,0 +1,1 @@+(None Natural) with ? = 1
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneB.dhall view
@@ -0,0 +1,1 @@+None Natural
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeA.dhall view
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeB.dhall view
@@ -0,0 +1,1 @@+Some 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedA.dhall view
@@ -0,0 +1,1 @@+(Some { x = Some { y = Some { z = Some 0 } } }) with ?.x.?.y.?.z.? = 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedB.dhall view
@@ -0,0 +1,1 @@+Some { x = Some { y = Some { z = Some 1 } } }
+ dhall-lang/tests/normalization/success/unit/WithOptionalNestedA.dhall view
@@ -0,0 +1,1 @@+{ x = Some 0 } with x.? = 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalNestedB.dhall view
@@ -0,0 +1,1 @@+{ x = Some 1 }
+ dhall-lang/tests/normalization/success/unit/WithPartiallyAbstractA.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation will evaluate a+partially abstract `with` expression correctly+-}+λ(x : { b : { c : {} } }) → { a = x } with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithPartiallyAbstractB.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : { c : {} } }) → { a = x with b.c = 42 }
+ dhall-lang/tests/normalization/success/unit/WithPriorityA.dhall view
@@ -0,0 +1,6 @@+{-  This test ensures that updates are ordered and latter updates take priority+    when the same field is updated more than one time++    In this example, the `a` field is updated twice, and the latter update wins+-}+{ a = 1 } with a = 2 with a = 3
+ dhall-lang/tests/normalization/success/unit/WithPriorityB.dhall view
@@ -0,0 +1,1 @@+{ a = 3 }
+ dhall-lang/tests/parser/failure/ImportHeadersExteriorHash.dhall view
@@ -0,0 +1,1 @@+(https://example.com/foo using ./headers) sha256:0000000000000000000000000000000000000000000000000000000000000000
+ dhall-lang/tests/parser/failure/ProjectionByTypeNeedsParens.dhall view
@@ -0,0 +1,1 @@+r.{ x: T }
+ dhall-lang/tests/parser/failure/annotation.dhall view
@@ -0,0 +1,1 @@+let a:Natural = 1 in a
+ dhall-lang/tests/parser/failure/assertBinding.dhall view
@@ -0,0 +1,1 @@+let assert = 2 in 1
+ dhall-lang/tests/parser/failure/boundBuiltins.dhall view
@@ -0,0 +1,6 @@+{-+    Builtin names are disallowed in bound variables.+    The grammar doesn't explicitly disallow this, but the implementation should+    refuse it. See the comments above the `nonreserved-label` rule.+-}+let Bool : Natural = 1 in Bool
+ dhall-lang/tests/parser/failure/builtinWithIndex.dhall view
@@ -0,0 +1,1 @@+Bool@2
+ dhall-lang/tests/parser/failure/bytesInvalid.dhall view
@@ -0,0 +1,1 @@+0x"invalid"
+ dhall-lang/tests/parser/failure/bytesOddLength.dhall view
@@ -0,0 +1,1 @@+0x"0"
+ dhall-lang/tests/parser/failure/doubleBoundsNeg.dhall view
@@ -0,0 +1,1 @@+-179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0
+ dhall-lang/tests/parser/failure/doubleBoundsPos.dhall view
@@ -0,0 +1,1 @@+179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0
+ dhall-lang/tests/parser/failure/fSomeX.dhall view
@@ -0,0 +1,1 @@+f Some x
+ dhall-lang/tests/parser/failure/importAccess.dhall view
@@ -0,0 +1,1 @@+./testImport .hello
+ dhall-lang/tests/parser/failure/incompleteIf.dhall view
@@ -0,0 +1,10 @@+-- This test verifies that an implementation rejects the following expression at+-- parse time (i.e. due to an incomplete `if` expression) rather than at+-- type-checking time (i.e. due to an unbound variable named `if` or `else`)+--+-- This ensures that implementations are not treating keywords as potential+-- identifier names.  In other words, if they fail to parse an incomplete+-- `if` expression they don't try to alternatively parse the expression as+-- function application instead.++if a then b else
+ dhall-lang/tests/parser/failure/mandatoryNewline.dhall view
@@ -0,0 +1,2 @@+-- Multi-line literals require a mandatory newline after the opening quotes+''ABC''
+ dhall-lang/tests/parser/failure/nonBase16Hash.dhall view
@@ -0,0 +1,1 @@+./foo sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe1g
+ dhall-lang/tests/parser/failure/nonCharacter.dhall view
@@ -0,0 +1,1 @@+"\u{10FFFF}"
+ dhall-lang/tests/parser/failure/nonCharacterUnbraced.dhall view
@@ -0,0 +1,6 @@+{-+The parser should reject unicode escape sequences for non-characters+(0xNFFFE-0xNFFFF for each `N` in `{ 0 .. F }), regardless of whether they are+braced or not.+-}+"\uFFFE"
+ dhall-lang/tests/parser/failure/nonUtf8.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation correctly rejects non-UTF8+   characters, such as this one: "í €"+-}+1
+ dhall-lang/tests/parser/failure/spacing/AnnotationNoSpace.dhall view
@@ -0,0 +1,1 @@+x :T
+ dhall-lang/tests/parser/failure/spacing/ApplicationNoSpace1.dhall view
@@ -0,0 +1,1 @@+f(x)
+ dhall-lang/tests/parser/failure/spacing/ApplicationNoSpace2.dhall view
@@ -0,0 +1,2 @@+-- There needs to be a space between a function and its argument+./example.dhall[1]
+ dhall-lang/tests/parser/failure/spacing/AssertNoSpace.dhall view
@@ -0,0 +1,1 @@+assert :T
+ dhall-lang/tests/parser/failure/spacing/ForallNoSpace.dhall view
@@ -0,0 +1,1 @@+forall(x :T) -> x
+ dhall-lang/tests/parser/failure/spacing/HeadersNoSpace.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using(x)
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace1.dhall view
@@ -0,0 +1,1 @@+if(b) then x else y
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace2.dhall view
@@ -0,0 +1,1 @@+if b then(x) else y
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace3.dhall view
@@ -0,0 +1,1 @@+if b then x else(y)
+ dhall-lang/tests/parser/failure/spacing/ImportAltNoSpace.dhall view
@@ -0,0 +1,1 @@+x ?y
+ dhall-lang/tests/parser/failure/spacing/ImportHashedNoSpace.dhall view
@@ -0,0 +1,1 @@+missingsha256:0000000000000000000000000000000000000000000000000000000000000000
+ dhall-lang/tests/parser/failure/spacing/LambdaNoSpace.dhall view
@@ -0,0 +1,1 @@+\(x :T) -> x
+ dhall-lang/tests/parser/failure/spacing/LetAnnotNoSpace.dhall view
@@ -0,0 +1,1 @@+let x :T = y in e
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace1.dhall view
@@ -0,0 +1,1 @@+letx = y in e
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace2.dhall view
@@ -0,0 +1,1 @@+let x = y in(e)
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace3.dhall view
@@ -0,0 +1,1 @@+let x = NaNin x
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace4.dhall view
@@ -0,0 +1,1 @@+let x = 3let y = x in y
+ dhall-lang/tests/parser/failure/spacing/ListLitEmptyNoSpace.dhall view
@@ -0,0 +1,1 @@+[] :T
+ dhall-lang/tests/parser/failure/spacing/MergeAnnotationNoSpace3.dhall view
@@ -0,0 +1,1 @@+merge x y :T
+ dhall-lang/tests/parser/failure/spacing/MergeNoSpace1.dhall view
@@ -0,0 +1,1 @@+merge(x) y
+ dhall-lang/tests/parser/failure/spacing/MergeNoSpace2.dhall view
@@ -0,0 +1,1 @@+merge x(y)
+ dhall-lang/tests/parser/failure/spacing/NaturalPlusNoSpace.dhall view
@@ -0,0 +1,1 @@+x +y
+ dhall-lang/tests/parser/failure/spacing/RecordTypeNoSpace.dhall view
@@ -0,0 +1,1 @@+{ x :T }
+ dhall-lang/tests/parser/failure/spacing/SomeNoSpace.dhall view
@@ -0,0 +1,1 @@+Some(x)
+ dhall-lang/tests/parser/failure/spacing/ToMapAnnotNoSpace.dhall view
@@ -0,0 +1,1 @@+toMap x :T
+ dhall-lang/tests/parser/failure/spacing/ToMapNoSpace.dhall view
@@ -0,0 +1,1 @@+toMap(x)
+ dhall-lang/tests/parser/failure/spacing/UnionTypeNoSpace.dhall view
@@ -0,0 +1,1 @@+< x :T >
+ dhall-lang/tests/parser/failure/surrogatePairUnbraced.dhall view
@@ -0,0 +1,5 @@+{-+The parser should reject unicode escape sequences for surrogate pairs+(0xD800-DFFF), regardless of whether they are braced or not.+-}+"\uD800"
+ dhall-lang/tests/parser/failure/time/DateTimeZone.dhall view
@@ -0,0 +1,2 @@+-- A date and time zone is not valid (because the time is missing)+2011-04-01+02:00
+ dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall view
@@ -0,0 +1,2 @@+-- April only has 30 days+2000-04-31
+ dhall-lang/tests/parser/failure/time/InvalidHour.dhall view
@@ -0,0 +1,2 @@+-- Hours must range between 0-23+24:00:00
+ dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall view
@@ -0,0 +1,3 @@+-- Leap seconds are not permitted by the Dhall standard, even though RFC 3339+-- supports them+2016-12-31T23:59:60
+ dhall-lang/tests/parser/failure/time/InvalidMinute.dhall view
@@ -0,0 +1,2 @@+-- Minutes must range between 0-59+00:60:00
+ dhall-lang/tests/parser/failure/time/InvalidMonth.dhall view
@@ -0,0 +1,2 @@+-- Months must be between 1-12+2000-13-01
+ dhall-lang/tests/parser/failure/time/InvalidSecond.dhall view
@@ -0,0 +1,2 @@+-- Seconds must range between 0-59 (and leap seconds are not supported)+00:00:60
+ dhall-lang/tests/parser/failure/time/NegativeYear.dhall view
@@ -0,0 +1,2 @@+-- Negative years are not permitted+-0001-01-01
+ dhall-lang/tests/parser/failure/time/YearTooLarge.dhall view
@@ -0,0 +1,2 @@+-- Only 4-digit years are permitted+10000-01-01
+ dhall-lang/tests/parser/failure/unit/AssertNoAnnotation.dhall view
@@ -0,0 +1,1 @@+assert
+ dhall-lang/tests/parser/failure/unit/BoolLitTrueWithIndex.dhall view
@@ -0,0 +1,1 @@+True@0
+ dhall-lang/tests/parser/failure/unit/BuiltinBoolWithIndex.dhall view
@@ -0,0 +1,1 @@+Bool@1
+ dhall-lang/tests/parser/failure/unit/BuiltinTypeWithIndex.dhall view
@@ -0,0 +1,1 @@+Type@0
+ dhall-lang/tests/parser/failure/unit/ImportEnvWrongEscape.dhall view
@@ -0,0 +1,1 @@+env:"\$"
+ dhall-lang/tests/parser/failure/unit/ListLitEmptyAnnotation.dhall view
@@ -0,0 +1,1 @@+([]) : List T
+ dhall-lang/tests/parser/failure/unit/ListLitEmptyMissingAnnotation.dhall view
@@ -0,0 +1,1 @@+[]
+ dhall-lang/tests/parser/failure/unit/ListLitTwoCommas.dhall view
@@ -0,0 +1,1 @@+[ ,, ]
+ dhall-lang/tests/parser/failure/unit/MergeAlone.dhall view
@@ -0,0 +1,1 @@+merge
+ dhall-lang/tests/parser/failure/unit/MergeOneArgument.dhall view
@@ -0,0 +1,1 @@+merge x
+ dhall-lang/tests/parser/failure/unit/NaturalLitLeadingZero.dhall view
@@ -0,0 +1,1 @@+042
+ dhall-lang/tests/parser/failure/unit/OldUnionLitSyntax.dhall view
@@ -0,0 +1,1 @@+< x = 3 | y : Bool >
+ dhall-lang/tests/parser/failure/unit/ProjectionTwoCommas.dhall view
@@ -0,0 +1,1 @@+foo.{ ,, }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword00.dhall view
@@ -0,0 +1,1 @@+{ if: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword01.dhall view
@@ -0,0 +1,1 @@+{ then: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword02.dhall view
@@ -0,0 +1,1 @@+{ else: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword03.dhall view
@@ -0,0 +1,1 @@+{ let: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword04.dhall view
@@ -0,0 +1,1 @@+{ in: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword05.dhall view
@@ -0,0 +1,1 @@+{ using: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword06.dhall view
@@ -0,0 +1,1 @@+{ missing: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword07.dhall view
@@ -0,0 +1,1 @@+{ assert: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword08.dhall view
@@ -0,0 +1,1 @@+{ as: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword09.dhall view
@@ -0,0 +1,1 @@+{ Infinity: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword10.dhall view
@@ -0,0 +1,1 @@+{ NaN: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword11.dhall view
@@ -0,0 +1,1 @@+{ merge: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword12.dhall view
@@ -0,0 +1,1 @@+{ toMap: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword13.dhall view
@@ -0,0 +1,1 @@+{ with: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword14.dhall view
@@ -0,0 +1,1 @@+{ forall: Text }
+ dhall-lang/tests/parser/failure/unit/RecordLitPunDotted.dhall view
@@ -0,0 +1,1 @@+{ x.y.z }
+ dhall-lang/tests/parser/failure/unit/RecordTwoCommas.dhall view
@@ -0,0 +1,1 @@+{ ,, }
+ dhall-lang/tests/parser/failure/unit/SomeAlone.dhall view
@@ -0,0 +1,1 @@+Some
+ dhall-lang/tests/parser/failure/unit/UnionTypeTwoDelims.dhall view
@@ -0,0 +1,1 @@+< || >
+ dhall-lang/tests/parser/failure/unit/UrlWithQuotedPath.dhall view
@@ -0,0 +1,1 @@+https://example.com/"a%20b"/c
+ dhall-lang/tests/parser/failure/unit/UsingToMap.dhall view
@@ -0,0 +1,8 @@+{-  At one point the Haskell implementation permitted this idiom, which was not+    standards-compliant++    The problem with the following expression is that the argument to `using`+    is parsed as a `completionExpression`, which means that any use of `toMap`+    within a `using` clause must be parenthesized+-}+https://example.com using toMap { Foo = "Bar" }
+ dhall-lang/tests/parser/failure/unit/WithPrecedence1.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } // { y = 1 } with x = 1
+ dhall-lang/tests/parser/failure/unit/WithPrecedence2.dhall view
@@ -0,0 +1,1 @@+foo { x = 0 } with x = 1
+ dhall-lang/tests/parser/failure/unit/WithPrecedence3.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } with x = 1 : T
+ dhall-lang/tests/parser/failure/unit/WithWhitespace.dhall view
@@ -0,0 +1,2 @@+-- For https://github.com/dhall-lang/dhall-haskell/issues/2212+{=}with foo = 0with bar = 1
+ dhall-lang/tests/parser/failure/unit/showConstructorAlone.dhall view
@@ -0,0 +1,1 @@+showConstructor
+ dhall-lang/tests/parser/success/annotationsA.dhall view
@@ -0,0 +1,1 @@+([] : List Natural) # [ 1, 2, 3 ] # ([ 1, 2, 3 ] : List Natural) : List Natural
+ dhall-lang/tests/parser/success/annotationsB.dhallb view

binary file changed (absent → 76 bytes)

+ dhall-lang/tests/parser/success/binaryA.dhall view
@@ -0,0 +1,8 @@+  λ(x : Bool)+→ λ(x : Bool)+→ { example0 = 0b0+  , example1 = 0b10+  , example2 = -0b11001+  , example3 = +0b100+  , example4 = x@0b01+  }
+ dhall-lang/tests/parser/success/binaryB.dhallb view

binary file changed (absent → 83 bytes)

+ dhall-lang/tests/parser/success/blockCommentA.dhall view
@@ -0,0 +1,3 @@+{- foo -}++1
+ dhall-lang/tests/parser/success/blockCommentB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/builtinNameAsFieldA.dhall view
@@ -0,0 +1,3 @@+let Prelude = https://prelude.dhall-lang.org/package.dhall++in  Prelude.List.map
+ dhall-lang/tests/parser/success/builtinNameAsFieldB.dhallb view

binary file changed (absent → 80 bytes)

+ dhall-lang/tests/parser/success/builtinsA.dhall view
@@ -0,0 +1,40 @@+[ Date/show+, Double/show+, Integer/clamp+, Integer/negate+, Integer/show+, Integer/toDouble+, List/build+, List/fold+, List/head+, List/indexed+, List/last+, List/length+, List/reverse+, Natural/build+, Natural/even+, Natural/fold+, Natural/isZero+, Natural/odd+, Natural/show+, Natural/subtract+, Natural/toInteger+, Text/replace+, Text/show+, Time/show+, TimeZone/show+, Bool+, Bytes+, Date+, Double+, False+, Integer+, List+, Natural+, None+, Optional+, Text+, Time+, TimeZone+, True+]
+ dhall-lang/tests/parser/success/builtinsB.dhallb view
@@ -0,0 +1,1 @@+˜)öiDate/showkDouble/showmInteger/clampnInteger/negatelInteger/showpInteger/toDoublejList/buildiList/foldiList/headlList/indexediList/lastkList/lengthlList/reversemNatural/buildlNatural/evenlNatural/foldnNatural/isZerokNatural/oddlNatural/showpNatural/subtractqNatural/toIntegerlText/replaceiText/showiTime/showmTimeZone/showdBooleBytesdDatefDoubleôgIntegerdListgNaturaldNonehOptionaldTextdTimehTimeZoneõ
+ dhall-lang/tests/parser/success/bytesA.dhall view
@@ -0,0 +1,25 @@+[ 0x""+, 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+, 0x"000102030405060708090a0b0c0d0e0f0A0B0C0D0E0F"+]
+ dhall-lang/tests/parser/success/bytesB.dhallb view

binary file changed (absent → 144 bytes)

+ dhall-lang/tests/parser/success/collectionImportTypeA.dhall view
@@ -0,0 +1,3 @@+{ example0 = None ./type.dhall+, example1 = [] : List ./type.dhall+}
+ dhall-lang/tests/parser/success/collectionImportTypeB.dhallb view

binary file changed (absent → 64 bytes)

+ dhall-lang/tests/parser/success/fieldsA.dhall view
@@ -0,0 +1,1 @@+({ foo = { bar = { baz = 1 } } }).foo. bar .baz
+ dhall-lang/tests/parser/success/fieldsB.dhallb view
@@ -0,0 +1,1 @@+ƒ	ƒ	ƒ	‚¡cfoo‚¡cbar‚¡cbaz‚cfoocbarcbaz
+ dhall-lang/tests/parser/success/forallA.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → forall (b : Type) -> a
+ dhall-lang/tests/parser/success/forallB.dhallb view

binary file changed (absent → 22 bytes)

+ dhall-lang/tests/parser/success/functionTypeA.dhall view
@@ -0,0 +1,1 @@+Bool → Bool -> Bool
+ dhall-lang/tests/parser/success/functionTypeB.dhallb view
@@ -0,0 +1,1 @@+ƒdBoolƒdBooldBool
+ dhall-lang/tests/parser/success/hexadecimalA.dhall view
@@ -0,0 +1,6 @@+  λ(x : Bool)+→ λ(x : Bool)+→ { example0 = 0xFF+  , example1 = -0x1A10+  , example2 = x@0x01+  }
+ dhall-lang/tests/parser/success/hexadecimalB.dhallb view
@@ -0,0 +1,1 @@+„axdBool„axdBool‚£hexample0‚ÿhexample1‚9hexample2‚ax
+ dhall-lang/tests/parser/success/identifierA.dhall view
@@ -0,0 +1,1 @@+λ(a : Type) → λ(a : Type) → a@1
+ dhall-lang/tests/parser/success/identifierB.dhallb view
@@ -0,0 +1,1 @@+„aadType„aadType‚aa
+ dhall-lang/tests/parser/success/labelA.dhall view
@@ -0,0 +1,2 @@+let _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/ = 1+in  _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/
+ dhall-lang/tests/parser/success/labelB.dhallb view

binary file changed (absent → 143 bytes)

+ dhall-lang/tests/parser/success/lambdaA.dhall view
@@ -0,0 +1,1 @@+λ(a : Type) → \(b : Type) -> a
+ dhall-lang/tests/parser/success/lambdaB.dhallb view

binary file changed (absent → 22 bytes)

+ dhall-lang/tests/parser/success/largeExpressionA.dhall view
@@ -0,0 +1,272 @@+  λ ( xs+    : List+      { cores :+          Natural+      , host :+          Text+      , key :+          Text+      , mandatoryFeatures :+          List Text+      , platforms :+          List+          < AArch64_Linux+          | ARMv5tel_Linux+          | ARMv7l_Linux+          | I686_Cygwin+          | I686_Linux+          | MIPS64el_Linux+          | PowerPC_Linux+          | X86_64_Cygwin+          | X86_64_Darwin+          | X86_64_FreeBSD+          | X86_64_Linux+          | X86_64_Solaris+          >+      , speedFactor :+          Natural+      , supportedFeatures :+          List Text+      , user :+          Optional Text+      }+    )+→ List/fold+  { cores :+      Natural+  , host :+      Text+  , key :+      Text+  , mandatoryFeatures :+      List Text+  , platforms :+      List+      < AArch64_Linux+      | ARMv5tel_Linux+      | ARMv7l_Linux+      | I686_Cygwin+      | I686_Linux+      | MIPS64el_Linux+      | PowerPC_Linux+      | X86_64_Cygwin+      | X86_64_Darwin+      | X86_64_FreeBSD+      | X86_64_Linux+      | X86_64_Solaris+      >+  , speedFactor :+      Natural+  , supportedFeatures :+      List Text+  , user :+      Optional Text+  }+  xs+  Text+  (   λ ( x+        : { cores :+              Natural+          , host :+              Text+          , key :+              Text+          , mandatoryFeatures :+              List Text+          , platforms :+              List+              < AArch64_Linux+              | ARMv5tel_Linux+              | ARMv7l_Linux+              | I686_Cygwin+              | I686_Linux+              | MIPS64el_Linux+              | PowerPC_Linux+              | X86_64_Cygwin+              | X86_64_Darwin+              | X86_64_FreeBSD+              | X86_64_Linux+              | X86_64_Solaris+              >+          , speedFactor :+              Natural+          , supportedFeatures :+              List Text+          , user :+              Optional Text+          }+        )+    → λ(y : Text)+    →     merge+            { None = x.host+            , Some = λ(user : Text) → user ++ "@" ++ x.host ++ ""+            }+            x.user+      ++  " "+      ++  ( merge+            { Empty = "", NonEmpty = λ(result : Text) → result }+            ( List/fold+              < AArch64_Linux+              | ARMv5tel_Linux+              | ARMv7l_Linux+              | I686_Cygwin+              | I686_Linux+              | MIPS64el_Linux+              | PowerPC_Linux+              | X86_64_Cygwin+              | X86_64_Darwin+              | X86_64_FreeBSD+              | X86_64_Linux+              | X86_64_Solaris+              >+              x.platforms+              < Empty | NonEmpty : Text >+              (   λ ( element+                    : < AArch64_Linux+                      | ARMv5tel_Linux+                      | ARMv7l_Linux+                      | I686_Cygwin+                      | I686_Linux+                      | MIPS64el_Linux+                      | PowerPC_Linux+                      | X86_64_Cygwin+                      | X86_64_Darwin+                      | X86_64_FreeBSD+                      | X86_64_Linux+                      | X86_64_Solaris+                      >+                    )+                → λ(status : < Empty | NonEmpty : Text >)+                → merge+                  { Empty =+                      < Empty | NonEmpty : Text >.NonEmpty+                      ( merge+                        { AArch64_Linux =+                            "aarch64-linux"+                        , ARMv5tel_Linux =+                            "armv5tel-linux"+                        , ARMv7l_Linux =+                            "armv7l-linux"+                        , I686_Cygwin =+                            "i686-cygwin"+                        , I686_Linux =+                            "i686-linux"+                        , MIPS64el_Linux =+                            "mips64el-linux"+                        , PowerPC_Linux =+                            "powerpc-linux"+                        , X86_64_Cygwin =+                            "x86_64-cygwin"+                        , X86_64_Darwin =+                            "x86_64-darwin"+                        , X86_64_FreeBSD =+                            "x86_64-freebsd"+                        , X86_64_Linux =+                            "x86_64-linux"+                        , X86_64_Solaris =+                            "x86_64-solaris"+                        }+                        element+                      )+                  , NonEmpty =+                        λ(result : Text)+                      → < Empty | NonEmpty : Text >.NonEmpty+                        (     ( merge+                                { AArch64_Linux =+                                    "aarch64-linux"+                                , ARMv5tel_Linux =+                                    "armv5tel-linux"+                                , ARMv7l_Linux =+                                    "armv7l-linux"+                                , I686_Cygwin =+                                    "i686-cygwin"+                                , I686_Linux =+                                    "i686-linux"+                                , MIPS64el_Linux =+                                    "mips64el-linux"+                                , PowerPC_Linux =+                                    "powerpc-linux"+                                , X86_64_Cygwin =+                                    "x86_64-cygwin"+                                , X86_64_Darwin =+                                    "x86_64-darwin"+                                , X86_64_FreeBSD =+                                    "x86_64-freebsd"+                                , X86_64_Linux =+                                    "x86_64-linux"+                                , X86_64_Solaris =+                                    "x86_64-solaris"+                                }+                                element+                              )+                          ++  ","+                          ++  result+                        )+                  }+                  status+                  : < Empty | NonEmpty : Text >+              )+              < Empty | NonEmpty : Text >.Empty+            )+            : Text+          )+      ++  " "+      ++  x.key+      ++  " "+      ++  Integer/show (Natural/toInteger x.cores)+      ++  " "+      ++  Integer/show (Natural/toInteger x.speedFactor)+      ++  " "+      ++  ( merge+            { Empty = "", NonEmpty = λ(result : Text) → result }+            ( List/fold+              Text+              x.supportedFeatures+              < Empty | NonEmpty : Text >+              (   λ(element : Text)+                → λ(status : < Empty | NonEmpty : Text >)+                → merge+                  { Empty =+                      < Empty | NonEmpty : Text >.NonEmpty element+                  , NonEmpty =+                        λ(result : Text)+                      → < Empty | NonEmpty : Text >.NonEmpty+                        (element ++ "," ++ result)+                  }+                  status+                  : < Empty | NonEmpty : Text >+              )+              < Empty | NonEmpty : Text >.Empty+            )+            : Text+          )+      ++  " "+      ++  ( merge+            { Empty = "", NonEmpty = λ(result : Text) → result }+            ( List/fold+              Text+              x.mandatoryFeatures+              < Empty | NonEmpty : Text >+              (   λ(element : Text)+                → λ(status : < Empty | NonEmpty : Text >)+                → merge+                  { Empty =+                      < Empty | NonEmpty : Text >.NonEmpty element+                  , NonEmpty =+                        λ(result : Text)+                      → < Empty | NonEmpty : Text >.NonEmpty+                        (element ++ "," ++ result)+                  }+                  status+                  : < Empty | NonEmpty : Text >+              )+              < Empty | NonEmpty : Text >.Empty+            )+            : Text+          )+      ++  ''+          +          ''+      ++  y+  )+  ""
+ dhall-lang/tests/parser/success/largeExpressionB.dhallb view

binary file changed (absent → 3507 bytes)

+ dhall-lang/tests/parser/success/leadingSeparatorsA.dhall view
@@ -0,0 +1,10 @@+{ emptyRecordLiteral = { , = }+, emptyRecordType = { , }+, emptyList = [,] : List Natural+, emptyUnionType = < | >++, recordLiteral = { , x = 1, y = True }+, recordType = { , x : Natural, y : Bool }+, list = [ , 1, 2 ]+, unionType = < | x : Natural | y : Bool >+}
+ dhall-lang/tests/parser/success/leadingSeparatorsB.dhallb view
@@ -0,0 +1,1 @@+‚¨iemptyList‚gNaturalremptyRecordLiteral‚ oemptyRecordType‚ nemptyUnionType‚ dlist„ö‚‚mrecordLiteral‚¢ax‚ayõjrecordType‚¢axgNaturalaydBooliunionType‚¢axgNaturalaydBool
+ dhall-lang/tests/parser/success/leadingTabsA.dhall view
@@ -0,0 +1,21 @@+{- This test verifies that leading tabs are correctly stripped++   Since one line is blank and the other line only has tabs, they are all+   stripped since they all count as leading whitespace for dedenting purposes.++   The end result is that the dedented string is equivalent to:++```+''++''+```++   ... which desugars to a single "\n".++   Carefully note that the two spaces before the starting quotes are not+   counted for dedenting purposes.+-}+  ''++		''
+ dhall-lang/tests/parser/success/leadingTabsB.dhallb view
@@ -0,0 +1,1 @@+‚a
+ dhall-lang/tests/parser/success/lineCommentA.dhall view
@@ -0,0 +1,3 @@+-- foo++1
+ dhall-lang/tests/parser/success/lineCommentB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/lineCommentCRLFA.dhall view
@@ -0,0 +1,3 @@+-- foo
+
+1
+ dhall-lang/tests/parser/success/lineCommentCRLFB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/listA.dhall view
@@ -0,0 +1,4 @@+[ [+1, +2, +3]+, [+1, +2, +3] : List Integer+, [] : List Integer+]
+ dhall-lang/tests/parser/success/listB.dhallb view

binary file changed (absent → 55 bytes)

+ dhall-lang/tests/parser/success/listWithCommentA.dhall view
@@ -0,0 +1,3 @@+[+  1, -- item one+{- foo -} 2, 3 ]
+ dhall-lang/tests/parser/success/listWithCommentB.dhallb view
@@ -0,0 +1,1 @@+…ö‚‚‚
+ dhall-lang/tests/parser/success/mergeA.dhall view
@@ -0,0 +1,7 @@+  λ(x : <>)+→ { bar = merge {=} x : Integer+  , foo =+	  merge+	  { Left = λ(b : Bool) → b, Right = Natural/even }+	  (< Left : Bool | Right : Natural >.Left True)+  }
+ dhall-lang/tests/parser/success/mergeB.dhallb view

binary file changed (absent → 114 bytes)

+ dhall-lang/tests/parser/success/missingFooA.dhall view
@@ -0,0 +1,1 @@+missingFoo
+ dhall-lang/tests/parser/success/missingFooB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/missingInParenthesesA.dhall view
@@ -0,0 +1,1 @@+(missing)
+ dhall-lang/tests/parser/success/missingInParenthesesB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/missingSlashA.dhall view
@@ -0,0 +1,1 @@+missing/
+ dhall-lang/tests/parser/success/missingSlashB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/mixedBlockLineCommentA.dhall view
@@ -0,0 +1,6 @@+{- foo -}+-- bar+{- --baz -}+-- {- qux -}++1
+ dhall-lang/tests/parser/success/mixedBlockLineCommentB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/naturalA.dhall view
@@ -0,0 +1,1 @@+[ 0, 1, 10 ]
+ dhall-lang/tests/parser/success/naturalB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/nestedBlockCommentA.dhall view
@@ -0,0 +1,3 @@+{- foo {- bar -} baz -}++1
+ dhall-lang/tests/parser/success/nestedBlockCommentB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/operatorsA.dhall view
@@ -0,0 +1,3 @@+  { foo = False && Natural/even (1 + 2 * 3) || True == False != True }+∧ { bar = [ "ABC" ++ "DEF" ] # [ "GHI" ] } ⫽ { baz = True }+: { foo : Bool, baz: Bool } ⩓ { bar : List Text }
+ dhall-lang/tests/parser/success/operatorsB.dhallb view

binary file changed (absent → 150 bytes)

+ dhall-lang/tests/parser/success/preferMissingNoSpacesA.dhall view
@@ -0,0 +1,1 @@+missing//foo
+ dhall-lang/tests/parser/success/preferMissingNoSpacesB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/quotedBoundVariableA.dhall view
@@ -0,0 +1,1 @@+(\(`Natural/even`: Natural -> Bool) -> `Natural/even`) Natural/odd 0
+ dhall-lang/tests/parser/success/quotedBoundVariableB.dhallb view

binary file changed (absent → 62 bytes)

+ dhall-lang/tests/parser/success/quotedLabelA.dhall view
@@ -0,0 +1,5 @@+{ example1 = let `let` = 1 in `let`+, example2 = let `:.` = 1 in `:.`+, example3 = let `$ref` = 1 in `$ref`+, example4 = let `` = 1 in ``+}
+ dhall-lang/tests/parser/success/quotedLabelB.dhallb view

binary file changed (absent → 101 bytes)

+ dhall-lang/tests/parser/success/quotedRecordLabelA.dhall view
@@ -0,0 +1,1 @@+{foo = 1, `` = 2, ` ` = 3}
+ dhall-lang/tests/parser/success/quotedRecordLabelB.dhallb view
@@ -0,0 +1,1 @@+‚£`‚a ‚cfoo‚
+ dhall-lang/tests/parser/success/quotedUnionLabelA.dhall view
@@ -0,0 +1,1 @@+<foo: Natural|``: Natural|` `: Natural>
+ dhall-lang/tests/parser/success/quotedUnionLabelB.dhallb view
@@ -0,0 +1,1 @@+‚£`gNaturala gNaturalcfoogNatural
+ dhall-lang/tests/parser/success/recordA.dhall view
@@ -0,0 +1,4 @@+{ foo = +1+, bar = 2+, baz = True+} : { foo : Integer, bar : Natural, baz : Bool }
+ dhall-lang/tests/parser/success/recordB.dhallb view
@@ -0,0 +1,1 @@+ƒ‚£cbar‚cbazõcfoo‚‚£cbargNaturalcbazdBoolcfoogInteger
+ dhall-lang/tests/parser/success/recordProjectionByExpressionA.dhall view
@@ -0,0 +1,15 @@+let example1 = λ(A : Type) → λ(B : Type) → λ(C : { x : A, y : B }) → C.({ x : A }) : { x : A }++let example2 =+	  λ(A : Type)+	→ λ(B : Type)+	→ λ(C : { p : A, q : B })+	→ C.(let r = { p : A } in r) : { p : A }++let A = Natural++let B = Text++in++(example1 A B { x = 10, y = "Text" }) ∧ (example2 A B { p = 10, q = "Text" }) : { x : A, p : A }
+ dhall-lang/tests/parser/success/recordProjectionByExpressionB.dhallb view

binary file changed (absent → 279 bytes)

+ dhall-lang/tests/parser/success/reservedPrefixA.dhall view
@@ -0,0 +1,1 @@+let TypeSynonym = Integer in +1 : TypeSynonym
+ dhall-lang/tests/parser/success/reservedPrefixB.dhallb view

binary file changed (absent → 44 bytes)

+ dhall-lang/tests/parser/success/text/dollarSignA.dhall view
@@ -0,0 +1,1 @@+"$"
+ dhall-lang/tests/parser/success/text/dollarSignB.dhallb view
@@ -0,0 +1,1 @@+‚a$
+ dhall-lang/tests/parser/success/text/doubleQuotedStringA.dhall view
@@ -0,0 +1,1 @@+"ABC"
+ dhall-lang/tests/parser/success/text/doubleQuotedStringB.dhallb view
@@ -0,0 +1,1 @@+‚cABC
+ dhall-lang/tests/parser/success/text/escapeA.dhall view
@@ -0,0 +1,9 @@+-- Verify that an implementation is processing escape sequences correctly++''+''${+'''+$+"+\+''
+ dhall-lang/tests/parser/success/text/escapeB.dhallb view
@@ -0,0 +1,5 @@+‚l${+''+$+"+\
+ dhall-lang/tests/parser/success/text/escapedDoubleQuotedStringA.dhall view
@@ -0,0 +1,1 @@+"\\\"\$\\\/\b\f\n\r\t\u{1D11E} \u2200(a : Type) \u2192 a"
+ dhall-lang/tests/parser/success/text/escapedDoubleQuotedStringB.dhallb view
@@ -0,0 +1,2 @@+‚x"\"$\/+
	𝄞 ∀(a : Type) → a
+ dhall-lang/tests/parser/success/text/escapedSingleQuotedStringA.dhall view
@@ -0,0 +1,4 @@+''+''${+'''+''
+ dhall-lang/tests/parser/success/text/escapedSingleQuotedStringB.dhallb view
@@ -0,0 +1,2 @@+‚f${+''
+ dhall-lang/tests/parser/success/text/interestingA.dhall view
@@ -0,0 +1,7 @@+-- Non-trivial example that combines several multi-line literal features++λ(x : Text) → ''+  ${x}    baz+      bar+    foo+    ''
+ dhall-lang/tests/parser/success/text/interestingB.dhallb view

binary file changed (absent → 42 bytes)

+ dhall-lang/tests/parser/success/text/interiorIndentA.dhall view
@@ -0,0 +1,16 @@+{- The indent is computed as the minimum number of leading spaces over all lines+   in a multi-line literal, including the line right before the closing quotes.+   In this case, there are three lines:++   * The first line containing "  foo" with two leading spaces+   * The second line containing "  bar" with two leading spaces+   * The third line containing "" with zero leading spaces++   Since the last line has zero leading spaces, the minimum number of leading+   spaces over all three lines is zero, so we don't strip any spaces.+-}++''+  foo+  bar+''
+ dhall-lang/tests/parser/success/text/interiorIndentB.dhallb view
@@ -0,0 +1,2 @@+‚l  foo+  bar
+ dhall-lang/tests/parser/success/text/interpolatedDoubleQuotedStringA.dhall view
@@ -0,0 +1,1 @@+"ABC${Natural/show 123}"
+ dhall-lang/tests/parser/success/text/interpolatedDoubleQuotedStringB.dhallb view

binary file changed (absent → 26 bytes)

+ dhall-lang/tests/parser/success/text/interpolatedSingleQuotedStringA.dhall view
@@ -0,0 +1,4 @@+''+ABC+${Natural/show 123}+''
+ dhall-lang/tests/parser/success/text/interpolatedSingleQuotedStringB.dhallb view

binary file changed (absent → 28 bytes)

+ dhall-lang/tests/parser/success/text/interpolationA.dhall view
@@ -0,0 +1,9 @@+{- This example verifies that an implementation is correctly breaking leading+   spaces at interpolated expressions.  The first line has the fewest number of+   leading spaces (2) due to the interruption by the interpolated expression.+-}++''+${Natural/show 1}      foo+  bar+''
+ dhall-lang/tests/parser/success/text/interpolationB.dhallb view

binary file changed (absent → 38 bytes)

+ dhall-lang/tests/parser/success/text/multilineBlankLineA.dhall view
@@ -0,0 +1,5 @@+    ''+    hello++    there+    ''
+ dhall-lang/tests/parser/success/text/multilineBlankLineB.dhallb view
@@ -0,0 +1,3 @@+‚mhello++there
+ dhall-lang/tests/parser/success/text/multilineBlankLineCrlfA.dhall view
@@ -0,0 +1,5 @@+    ''+    hello+
+    there+    ''
+ dhall-lang/tests/parser/success/text/multilineBlankLineCrlfB.dhallb view
@@ -0,0 +1,3 @@+‚mhello++there
+ dhall-lang/tests/parser/success/text/multilineCorruptedLeadingWhitespaceA.dhall view
@@ -0,0 +1,5 @@+	  	''+	  	hai+	  	there+	   ok+	  	''
+ dhall-lang/tests/parser/success/text/multilineCorruptedLeadingWhitespaceB.dhallb view
@@ -0,0 +1,4 @@+‚q	hai+	there+ ok+	
+ dhall-lang/tests/parser/success/text/multilineIndentedAndAlignedA.dhall view
@@ -0,0 +1,4 @@+	 ''+	 hai+	 there+	 ''
+ dhall-lang/tests/parser/success/text/multilineIndentedAndAlignedB.dhallb view
@@ -0,0 +1,2 @@+‚jhai+there
+ dhall-lang/tests/parser/success/text/multilineMismatchedLeadingWhitespaceA.dhall view
@@ -0,0 +1,4 @@+''+	a+ b+''
+ dhall-lang/tests/parser/success/text/multilineMismatchedLeadingWhitespaceB.dhallb view
@@ -0,0 +1,2 @@+‚f	a+ b
+ dhall-lang/tests/parser/success/text/multilinePreserveCommentA.dhall view
@@ -0,0 +1,8 @@+{- A comment within the interior of a multi-line literal counts as part of the+   literal+-}++''+-- Hello+{- world -}+''
+ dhall-lang/tests/parser/success/text/multilinePreserveCommentB.dhallb view
@@ -0,0 +1,2 @@+‚u-- Hello+{- world -}
+ dhall-lang/tests/parser/success/text/multilineTabsA.dhall view
@@ -0,0 +1,5 @@+	''+	hai+		there+	   lol+	''
+ dhall-lang/tests/parser/success/text/multilineTabsB.dhallb view
@@ -0,0 +1,3 @@+‚rhai+	there+   lol
+ dhall-lang/tests/parser/success/text/nonAssignedUnicodeA.dhall view
@@ -0,0 +1,1 @@+"\u{1FFF0}"
+ dhall-lang/tests/parser/success/text/nonAssignedUnicodeB.dhallb view
@@ -0,0 +1,1 @@+‚d🿰
+ dhall-lang/tests/parser/success/text/preserveCommentA.dhall view
@@ -0,0 +1,1 @@+"-- $--$--{--}$"
+ dhall-lang/tests/parser/success/text/preserveCommentB.dhallb view
@@ -0,0 +1,1 @@+‚n-- $--$--{--}$
+ dhall-lang/tests/parser/success/text/singleLineA.dhall view
@@ -0,0 +1,6 @@+{- This is how you encode a multi-line literal that contains no newlines++   The leading newline is stripped+-}+''+foo''
+ dhall-lang/tests/parser/success/text/singleLineB.dhallb view
@@ -0,0 +1,1 @@+‚cfoo
+ dhall-lang/tests/parser/success/text/singleQuoteConcatA.dhall view
@@ -0,0 +1,5 @@+''+a''++++''+b''
+ dhall-lang/tests/parser/success/text/singleQuoteConcatB.dhallb view
@@ -0,0 +1,1 @@+„‚aa‚ab
+ dhall-lang/tests/parser/success/text/singleQuotedStringA.dhall view
@@ -0,0 +1,4 @@+''+ABC+DEF+''
+ dhall-lang/tests/parser/success/text/singleQuotedStringB.dhallb view
@@ -0,0 +1,2 @@+‚hABC+DEF
+ dhall-lang/tests/parser/success/text/templateA.dhall view
@@ -0,0 +1,13 @@+    \(record : { name        : Text+               , value       : Double+               , taxed_value : Double+               , in_ca       : Bool+               }+     ) ->  ''+Hello ${record.name}+You have just won ${Double/show record.value} dollars!+${ if record.in_ca+   then "Well, ${Double/show record.taxed_value} dollars, after taxes"+   else ""+ }+''
+ dhall-lang/tests/parser/success/text/templateB.dhallb view

binary file changed (absent → 244 bytes)

+ dhall-lang/tests/parser/success/text/twoLinesA.dhall view
@@ -0,0 +1,7 @@+{- Verify that an implementation is correctly preserving newlines in the+   corresponding double-quoted literal+-}++''+foo+bar''
+ dhall-lang/tests/parser/success/text/twoLinesB.dhallb view
@@ -0,0 +1,2 @@+‚gfoo+bar
+ dhall-lang/tests/parser/success/text/unicodeBracedA.dhall view
@@ -0,0 +1,1 @@+"\u{1}\u{10}\u{100}\u{1000}\u{10000}\u{100000}"
+ dhall-lang/tests/parser/success/text/unicodeBracedB.dhallb view
@@ -0,0 +1,1 @@+‚oĀက𐀀ô€€€
+ dhall-lang/tests/parser/success/text/unicodeDoubleQuotedStringA.dhall view
@@ -0,0 +1,1 @@+"∀(a : Type) → a"
+ dhall-lang/tests/parser/success/text/unicodeDoubleQuotedStringB.dhallb view
@@ -0,0 +1,1 @@+‚s∀(a : Type) → a
+ dhall-lang/tests/parser/success/text/unicodeEscapedA.dhall view
@@ -0,0 +1,1 @@+"A\u2115B\u{1FA00}C\u{43}D\u{00000001F574}E\u0022F"
+ dhall-lang/tests/parser/success/text/unicodeEscapedB.dhallb view
@@ -0,0 +1,1 @@+‚sAℕB🨀CCD🕴E"F
+ dhall-lang/tests/parser/success/text/unicodePlane16A.dhall view
@@ -0,0 +1,1 @@+"\u{10fffd}\u{1fffd}"
+ dhall-lang/tests/parser/success/text/unicodePlane16B.dhallb view
@@ -0,0 +1,1 @@+‚hô¿½ðŸ¿½
+ dhall-lang/tests/parser/success/time/DateTimeA.dhall view
@@ -0,0 +1,1 @@+1960-12-25T04:23:34
+ dhall-lang/tests/parser/success/time/DateTimeB.dhallb view

binary file changed (absent → 32 bytes)

+ dhall-lang/tests/parser/success/time/DateTimeTimeZoneA.dhall view
@@ -0,0 +1,1 @@+2020-01-01T12:00:00-08:00
+ dhall-lang/tests/parser/success/time/DateTimeTimeZoneB.dhallb view

binary file changed (absent → 45 bytes)

+ dhall-lang/tests/parser/success/time/LowercaseTA.dhall view
@@ -0,0 +1,2 @@+-- Check that lowercase `t` is supported+2000-01-01t12:00:00
+ dhall-lang/tests/parser/success/time/LowercaseTB.dhallb view

binary file changed (absent → 30 bytes)

+ dhall-lang/tests/parser/success/time/TimeTimeZoneA.dhall view
@@ -0,0 +1,1 @@+00:00:00+00:00
+ dhall-lang/tests/parser/success/time/TimeTimeZoneB.dhallb view

binary file changed (absent → 32 bytes)

+ dhall-lang/tests/parser/success/time/TimeTimeZoneZA.dhall view
@@ -0,0 +1,5 @@+-- Same as `./TimeTimeZoneA.dhall`, but with `Z` as the `TimeZone`+--+-- This ensures that implementation still parse `Z` in conjunction with a time,+-- even if `Z` by itself is not permitted+00:00:00Z
+ dhall-lang/tests/parser/success/time/TimeTimeZoneZB.dhallb view

binary file changed (absent → 32 bytes)

+ dhall-lang/tests/parser/success/toMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/parser/success/toMapB.dhallb view
@@ -0,0 +1,1 @@+‚‚£cbar‚cbaz‚	cfoo‚
+ dhall-lang/tests/parser/success/unicodeCommentA.dhall view
@@ -0,0 +1,3 @@+{- ∀(a : Type) → a -}++1
+ dhall-lang/tests/parser/success/unicodeCommentB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/unit/AnnotationA.dhall view
@@ -0,0 +1,1 @@+x : T
+ dhall-lang/tests/parser/success/unit/AnnotationB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/AssertA.dhall view
@@ -0,0 +1,1 @@+assert : T
+ dhall-lang/tests/parser/success/unit/AssertB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/AssertEquivalenceA.dhall view
@@ -0,0 +1,1 @@+assert : x === y
+ dhall-lang/tests/parser/success/unit/AssertEquivalenceB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/AssertEquivalenceUnicodeA.dhall view
@@ -0,0 +1,1 @@+assert : x ≡ y
+ dhall-lang/tests/parser/success/unit/AssertEquivalenceUnicodeB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/AssertPrecedenceA.dhall view
@@ -0,0 +1,1 @@+assert : T U
+ dhall-lang/tests/parser/success/unit/AssertPrecedenceB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/BoolA.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/parser/success/unit/BoolB.dhallb view
@@ -0,0 +1,1 @@+dBool
+ dhall-lang/tests/parser/success/unit/BoolLitTrueA.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/parser/success/unit/BoolLitTrueB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/unit/BuiltinListBuildA.dhall view
@@ -0,0 +1,1 @@+List/Build
+ dhall-lang/tests/parser/success/unit/BuiltinListBuildB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/CompletionA.dhall view
@@ -0,0 +1,1 @@+T :: r
+ dhall-lang/tests/parser/success/unit/CompletionB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/DateA.dhall view
@@ -0,0 +1,1 @@+Date
+ dhall-lang/tests/parser/success/unit/DateB.dhallb view
@@ -0,0 +1,1 @@+dDate
+ dhall-lang/tests/parser/success/unit/DateLiteralA.dhall view
@@ -0,0 +1,1 @@+2020-01-01
+ dhall-lang/tests/parser/success/unit/DateLiteralB.dhallb view
@@ -0,0 +1,1 @@+„ä
+ dhall-lang/tests/parser/success/unit/DeBruijnIndexA.dhall view
@@ -0,0 +1,1 @@+x == x@0
+ dhall-lang/tests/parser/success/unit/DeBruijnIndexB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLit16bitA.dhall view
@@ -0,0 +1,1 @@+5.5
+ dhall-lang/tests/parser/success/unit/DoubleLit16bitB.dhallb view
@@ -0,0 +1,1 @@+ùE€
+ dhall-lang/tests/parser/success/unit/DoubleLit32bitA.dhall view
@@ -0,0 +1,1 @@+5555.5
+ dhall-lang/tests/parser/success/unit/DoubleLit32bitB.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLit64bitA.dhall view
@@ -0,0 +1,1 @@+55555555555.5
+ dhall-lang/tests/parser/success/unit/DoubleLit64bitB.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitExponentA.dhall view
@@ -0,0 +1,1 @@+1.23e4
+ dhall-lang/tests/parser/success/unit/DoubleLitExponentB.dhallb view

binary file changed (absent → 5 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitExponentNegativeA.dhall view
@@ -0,0 +1,1 @@+1.23e-4
+ dhall-lang/tests/parser/success/unit/DoubleLitExponentNegativeB.dhallb view
@@ -0,0 +1,1 @@+û? 1ônÒF
+ dhall-lang/tests/parser/success/unit/DoubleLitExponentNoDotA.dhall view
@@ -0,0 +1,1 @@+1e4
+ dhall-lang/tests/parser/success/unit/DoubleLitExponentNoDotB.dhallb view
@@ -0,0 +1,1 @@+ùpâ
+ dhall-lang/tests/parser/success/unit/DoubleLitInfinityA.dhall view
@@ -0,0 +1,1 @@+Infinity
+ dhall-lang/tests/parser/success/unit/DoubleLitInfinityB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitNaNA.dhall view
@@ -0,0 +1,1 @@+NaN
+ dhall-lang/tests/parser/success/unit/DoubleLitNaNB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitNegInfinityA.dhall view
@@ -0,0 +1,1 @@+-Infinity
+ dhall-lang/tests/parser/success/unit/DoubleLitNegInfinityB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitNegZeroA.dhall view
@@ -0,0 +1,1 @@+-0.0
+ dhall-lang/tests/parser/success/unit/DoubleLitNegZeroB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitNegativeA.dhall view
@@ -0,0 +1,1 @@+-1.23
+ dhall-lang/tests/parser/success/unit/DoubleLitNegativeB.dhallb view
@@ -0,0 +1,1 @@+û¿ó®záG®
+ dhall-lang/tests/parser/success/unit/DoubleLitPositiveA.dhall view
@@ -0,0 +1,1 @@+1.23
+ dhall-lang/tests/parser/success/unit/DoubleLitPositiveB.dhallb view
@@ -0,0 +1,1 @@+û?ó®záG®
+ dhall-lang/tests/parser/success/unit/DoubleLitSecretlyIntA.dhall view
@@ -0,0 +1,5 @@+{-+    Some languages do not make principled distinctions between number types, so+    this checks that this Double is not silently considered as a Natural+-}+1.0
+ dhall-lang/tests/parser/success/unit/DoubleLitSecretlyIntB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/DoubleLitZeroA.dhall view
@@ -0,0 +1,1 @@+0.0
+ dhall-lang/tests/parser/success/unit/DoubleLitZeroB.dhallb view

binary file changed (absent → 3 bytes)

+ dhall-lang/tests/parser/success/unit/EmptyRecordLiteralA.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/parser/success/unit/EmptyRecordLiteralB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/FieldA.dhall view
@@ -0,0 +1,1 @@+r.x
+ dhall-lang/tests/parser/success/unit/FieldB.dhallb view

binary file changed (absent → 8 bytes)

+ dhall-lang/tests/parser/success/unit/FieldBuiltinNameA.dhall view
@@ -0,0 +1,1 @@+r.List
+ dhall-lang/tests/parser/success/unit/FieldBuiltinNameB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/FieldQuotedA.dhall view
@@ -0,0 +1,1 @@+r.`x`
+ dhall-lang/tests/parser/success/unit/FieldQuotedB.dhallb view

binary file changed (absent → 8 bytes)

+ dhall-lang/tests/parser/success/unit/ForallA.dhall view
@@ -0,0 +1,1 @@+forall(x: T) -> x
+ dhall-lang/tests/parser/success/unit/ForallB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/ForallNestedA.dhall view
@@ -0,0 +1,1 @@+forall(x: T) -> forall(y: U) -> x
+ dhall-lang/tests/parser/success/unit/ForallNestedB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/ForallUnderscoreA.dhall view
@@ -0,0 +1,1 @@+forall(_: T) -> x
+ dhall-lang/tests/parser/success/unit/ForallUnderscoreB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/ForallUnicodeA.dhall view
@@ -0,0 +1,1 @@+∀(x : T) -> y
+ dhall-lang/tests/parser/success/unit/ForallUnicodeB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionApplicationMultipleArgsA.dhall view
@@ -0,0 +1,1 @@+f x y z
+ dhall-lang/tests/parser/success/unit/FunctionApplicationMultipleArgsB.dhallb view

binary file changed (absent → 18 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionApplicationOneArgA.dhall view
@@ -0,0 +1,1 @@+f x
+ dhall-lang/tests/parser/success/unit/FunctionApplicationOneArgB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionTypeArrowA.dhall view
@@ -0,0 +1,1 @@+T -> U
+ dhall-lang/tests/parser/success/unit/FunctionTypeArrowB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionTypePiA.dhall view
@@ -0,0 +1,1 @@+forall(x: T) -> U
+ dhall-lang/tests/parser/success/unit/FunctionTypePiB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionTypePiNestedA.dhall view
@@ -0,0 +1,1 @@+forall(x: T) -> ∀(y: U) -> V
+ dhall-lang/tests/parser/success/unit/FunctionTypePiNestedB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionTypePiUnderscoreA.dhall view
@@ -0,0 +1,1 @@+forall(_: T) -> U
+ dhall-lang/tests/parser/success/unit/FunctionTypePiUnderscoreB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/FunctionTypePiUnicodeA.dhall view
@@ -0,0 +1,1 @@+∀(x: T) -> U
+ dhall-lang/tests/parser/success/unit/FunctionTypePiUnicodeB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/IntegerLitNegativeA.dhall view
@@ -0,0 +1,1 @@+-10
+ dhall-lang/tests/parser/success/unit/IntegerLitNegativeB.dhallb view
@@ -0,0 +1,1 @@+‚)
+ dhall-lang/tests/parser/success/unit/IntegerLitPositiveA.dhall view
@@ -0,0 +1,1 @@++10
+ dhall-lang/tests/parser/success/unit/IntegerLitPositiveB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/unit/KindA.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/parser/success/unit/KindB.dhallb view
@@ -0,0 +1,1 @@+dKind
+ dhall-lang/tests/parser/success/unit/LambdaA.dhall view
@@ -0,0 +1,1 @@+\(x: T) -> x
+ dhall-lang/tests/parser/success/unit/LambdaB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/LambdaNestedA.dhall view
@@ -0,0 +1,1 @@+\(x: T) -> \(y: U) -> x
+ dhall-lang/tests/parser/success/unit/LambdaNestedB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/LambdaUnderscoreA.dhall view
@@ -0,0 +1,1 @@+\(_: T) -> x
+ dhall-lang/tests/parser/success/unit/LambdaUnderscoreB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/LambdaUnicodeA.dhall view
@@ -0,0 +1,1 @@+λ(x : T) -> y
+ dhall-lang/tests/parser/success/unit/LambdaUnicodeB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/LetA.dhall view
@@ -0,0 +1,1 @@+let x: T = v in e
+ dhall-lang/tests/parser/success/unit/LetAnnotA.dhall view
@@ -0,0 +1,1 @@+let x: T = y in e
+ dhall-lang/tests/parser/success/unit/LetAnnotB.dhallb view

binary file changed (absent → 17 bytes)

+ dhall-lang/tests/parser/success/unit/LetB.dhallb view

binary file changed (absent → 17 bytes)

+ dhall-lang/tests/parser/success/unit/LetMultiA.dhall view
@@ -0,0 +1,1 @@+let x: T = v let y: U = w in e
+ dhall-lang/tests/parser/success/unit/LetMultiB.dhallb view

binary file changed (absent → 27 bytes)

+ dhall-lang/tests/parser/success/unit/LetNestedA.dhall view
@@ -0,0 +1,1 @@+let x: T = v in let y: U = w in e
+ dhall-lang/tests/parser/success/unit/LetNestedB.dhallb view

binary file changed (absent → 27 bytes)

+ dhall-lang/tests/parser/success/unit/LetNoAnnotA.dhall view
@@ -0,0 +1,1 @@+let x = y in e
+ dhall-lang/tests/parser/success/unit/LetNoAnnotB.dhallb view

binary file changed (absent → 14 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitEmpty1A.dhall view
@@ -0,0 +1,1 @@+[] : List T
+ dhall-lang/tests/parser/success/unit/ListLitEmpty1B.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitEmpty2A.dhall view
@@ -0,0 +1,1 @@+[] : T
+ dhall-lang/tests/parser/success/unit/ListLitEmpty2B.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitEmptyCommaA.dhall view
@@ -0,0 +1,1 @@+[ , ] : List Bool
+ dhall-lang/tests/parser/success/unit/ListLitEmptyCommaB.dhallb view
@@ -0,0 +1,1 @@+‚dBool
+ dhall-lang/tests/parser/success/unit/ListLitEmptyPrecedenceA.dhall view
@@ -0,0 +1,1 @@+[] : List T U
+ dhall-lang/tests/parser/success/unit/ListLitEmptyPrecedenceB.dhallb view

binary file changed (absent → 18 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitLeadingCommaA.dhall view
@@ -0,0 +1,1 @@+[ , x, y ]
+ dhall-lang/tests/parser/success/unit/ListLitLeadingCommaB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitNonEmptyA.dhall view
@@ -0,0 +1,1 @@+[x, y]
+ dhall-lang/tests/parser/success/unit/ListLitNonEmptyAnnotatedA.dhall view
@@ -0,0 +1,1 @@+[x, y] : List T
+ dhall-lang/tests/parser/success/unit/ListLitNonEmptyAnnotatedB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitNonEmptyB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitTrailingAndLeadingCommasA.dhall view
@@ -0,0 +1,1 @@+[ , x, y, ]
+ dhall-lang/tests/parser/success/unit/ListLitTrailingAndLeadingCommasB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ListLitTrailingCommaA.dhall view
@@ -0,0 +1,1 @@+[ x, y, ]
+ dhall-lang/tests/parser/success/unit/ListLitTrailingCommaB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ListWithNewlineA.dhall view
@@ -0,0 +1,11 @@+[ [+    1,+    2,+    3,+  ]+, [+  , 1+  , 2+  , 3+  ]+]
+ dhall-lang/tests/parser/success/unit/ListWithNewlineB.dhallb view
@@ -0,0 +1,1 @@+„ö…ö‚‚‚…ö‚‚‚
+ dhall-lang/tests/parser/success/unit/MergeA.dhall view
@@ -0,0 +1,1 @@+merge x y
+ dhall-lang/tests/parser/success/unit/MergeAnnotationA.dhall view
@@ -0,0 +1,1 @@+merge x y : t
+ dhall-lang/tests/parser/success/unit/MergeAnnotationB.dhallb view

binary file changed (absent → 14 bytes)

+ dhall-lang/tests/parser/success/unit/MergeAnnotationPrecedenceA.dhall view
@@ -0,0 +1,1 @@+merge x y : t a
+ dhall-lang/tests/parser/success/unit/MergeAnnotationPrecedenceB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/MergeB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/MergeParenAnnotationA.dhall view
@@ -0,0 +1,1 @@+(merge x y) : t
+ dhall-lang/tests/parser/success/unit/MergeParenAnnotationB.dhallb view

binary file changed (absent → 17 bytes)

+ dhall-lang/tests/parser/success/unit/MergeXYZA.dhall view
@@ -0,0 +1,1 @@+merge x y z
+ dhall-lang/tests/parser/success/unit/MergeXYZB.dhallb view

binary file changed (absent → 16 bytes)

+ dhall-lang/tests/parser/success/unit/NaturalLitA.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/parser/success/unit/NaturalLitB.dhallb view
@@ -0,0 +1,1 @@+‚*
+ dhall-lang/tests/parser/success/unit/ProjectionA.dhall view
@@ -0,0 +1,1 @@+r.{x, y, z}
+ dhall-lang/tests/parser/success/unit/ProjectionB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/ProjectionLeadingCommaA.dhall view
@@ -0,0 +1,1 @@+foo.{ , x, y }
+ dhall-lang/tests/parser/success/unit/ProjectionLeadingCommaB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/ProjectionTrailingAndLeadingCommasA.dhall view
@@ -0,0 +1,1 @@+foo.{ , x, y, }
+ dhall-lang/tests/parser/success/unit/ProjectionTrailingAndLeadingCommasB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/ProjectionTrailingCommaA.dhall view
@@ -0,0 +1,1 @@+foo.{ x, y, }
+ dhall-lang/tests/parser/success/unit/ProjectionTrailingCommaB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/QuotedBoolA.dhall view
@@ -0,0 +1,1 @@+`Bool`
+ dhall-lang/tests/parser/success/unit/QuotedBoolB.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/QuotedTrueA.dhall view
@@ -0,0 +1,1 @@+`True`
+ dhall-lang/tests/parser/success/unit/QuotedTrueB.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/QuotedTypeA.dhall view
@@ -0,0 +1,1 @@+`Type`
+ dhall-lang/tests/parser/success/unit/QuotedTypeB.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/QuotedVariableA.dhall view
@@ -0,0 +1,1 @@+`x+y`
+ dhall-lang/tests/parser/success/unit/QuotedVariableB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitA.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = 2 }
+ dhall-lang/tests/parser/success/unit/RecordLitB.dhallb view
@@ -0,0 +1,1 @@+‚¢ax‚ay‚
+ dhall-lang/tests/parser/success/unit/RecordLitDottedA.dhall view
@@ -0,0 +1,7 @@+{-  The purpose of this test is to illustrate that dotted fields are syntactic+    sugar that does not survive the parsing stage.  The underlying expression is+    actually represented and encoded as:++    { x = { y = { z = 1 } } }+-}+{ x.y.z = 1 }
+ dhall-lang/tests/parser/success/unit/RecordLitDottedB.dhallb view
@@ -0,0 +1,1 @@+‚¡ax‚¡ay‚¡az‚
+ dhall-lang/tests/parser/success/unit/RecordLitDottedEscapeA.dhall view
@@ -0,0 +1,1 @@+{ `x.y`.z = 1 }
+ dhall-lang/tests/parser/success/unit/RecordLitDottedEscapeB.dhallb view
@@ -0,0 +1,1 @@+‚¡cx.y‚¡az‚
+ dhall-lang/tests/parser/success/unit/RecordLitDuplicatesA.dhall view
@@ -0,0 +1,7 @@+{-  The purpose of this test is to illustrate that duplicate fields are+    syntactic sugar that does not survive the parsing stage.  The underlying+    expression is actually represented and encoded as:++    { x = { y = 1 } ∧ { z = 1 } }+-}+{ x = { y = 1 }, x = { z = 1 } }
+ dhall-lang/tests/parser/success/unit/RecordLitDuplicatesB.dhallb view
@@ -0,0 +1,1 @@+‚¡ax„‚¡ay‚‚¡az‚
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyBothCommasA.dhall view
@@ -0,0 +1,1 @@+{ , =, }
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyBothCommasB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyLeadingCommaA.dhall view
@@ -0,0 +1,1 @@+{ , = }
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyLeadingCommaB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyTrailingCommaA.dhall view
@@ -0,0 +1,1 @@+{ =, }
+ dhall-lang/tests/parser/success/unit/RecordLitEmptyTrailingCommaB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/RecordLitLeadingCommaA.dhall view
@@ -0,0 +1,1 @@+{ , x = 0, y = 1 }
+ dhall-lang/tests/parser/success/unit/RecordLitLeadingCommaB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitNixLikeA.dhall view
@@ -0,0 +1,5 @@+{- The purpose of this test is to verify that the combination of the dotted+   field notation and the duplicate record fields desugar to the desired syntax+   tree+-}+{ x.y = 1, x.z = True }
+ dhall-lang/tests/parser/success/unit/RecordLitNixLikeB.dhallb view
@@ -0,0 +1,1 @@+‚¡ax„‚¡ay‚‚¡azõ
+ dhall-lang/tests/parser/success/unit/RecordLitPunA.dhall view
@@ -0,0 +1,1 @@+{ x, y, z }
+ dhall-lang/tests/parser/success/unit/RecordLitPunB.dhallb view

binary file changed (absent → 21 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitPunDuplicateA.dhall view
@@ -0,0 +1,1 @@+{ x, y, x }
+ dhall-lang/tests/parser/success/unit/RecordLitPunDuplicateB.dhallb view

binary file changed (absent → 22 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitPunMixedA.dhall view
@@ -0,0 +1,1 @@+{ x, y = 1, z, w.a.b = 2 }
+ dhall-lang/tests/parser/success/unit/RecordLitPunMixedB.dhallb view

binary file changed (absent → 35 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitPunSomeA.dhall view
@@ -0,0 +1,1 @@+{ Some }
+ dhall-lang/tests/parser/success/unit/RecordLitPunSomeB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitSomeA.dhall view
@@ -0,0 +1,1 @@+{ Some = 0 }
+ dhall-lang/tests/parser/success/unit/RecordLitSomeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitTrailingAndLeadingCommasA.dhall view
@@ -0,0 +1,1 @@+{ , x = 0, y = 1, }
+ dhall-lang/tests/parser/success/unit/RecordLitTrailingAndLeadingCommasB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/RecordLitTrailingCommaA.dhall view
@@ -0,0 +1,1 @@+{ x = 0, y = 1, }
+ dhall-lang/tests/parser/success/unit/RecordLitTrailingCommaB.dhallb view

binary file changed (absent → 13 bytes)

+ dhall-lang/tests/parser/success/unit/RecordProjectionByTypeA.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }.({ a : Natural })
+ dhall-lang/tests/parser/success/unit/RecordProjectionByTypeB.dhallb view
@@ -0,0 +1,2 @@+‚¢aa‚ab‚‚¡aagNatural
+ dhall-lang/tests/parser/success/unit/RecordProjectionByTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }.({})
+ dhall-lang/tests/parser/success/unit/RecordProjectionByTypeEmptyB.dhallb view
@@ -0,0 +1,2 @@+‚¢aa‚ab‚‚ 
+ dhall-lang/tests/parser/success/unit/RecordTypeA.dhall view
@@ -0,0 +1,1 @@+{ x: T, y: U }
+ dhall-lang/tests/parser/success/unit/RecordTypeB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/RecordTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/parser/success/unit/RecordTypeEmptyB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/RecordTypeEmptyCommaA.dhall view
@@ -0,0 +1,1 @@+{ , }
+ dhall-lang/tests/parser/success/unit/RecordTypeEmptyCommaB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/RecordTypeLeadingCommaA.dhall view
@@ -0,0 +1,1 @@+{ , x : T, y : U }
+ dhall-lang/tests/parser/success/unit/RecordTypeLeadingCommaB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/RecordTypeTrailingAndLeadingCommasA.dhall view
@@ -0,0 +1,1 @@+{ , x : T, y : U, }
+ dhall-lang/tests/parser/success/unit/RecordTypeTrailingAndLeadingCommasB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/RecordTypeTrailingCommaA.dhall view
@@ -0,0 +1,1 @@+{ x : T, y : U, }
+ dhall-lang/tests/parser/success/unit/RecordTypeTrailingCommaB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/SelectionSomeA.dhall view
@@ -0,0 +1,1 @@+record.{ Some }
+ dhall-lang/tests/parser/success/unit/SelectionSomeB.dhallb view

binary file changed (absent → 16 bytes)

+ dhall-lang/tests/parser/success/unit/ShebangA.dhall view
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"A"
+ dhall-lang/tests/parser/success/unit/ShebangB.dhallb view
@@ -0,0 +1,1 @@+‚aA
+ dhall-lang/tests/parser/success/unit/ShebangNixA.dhall view
@@ -0,0 +1,3 @@+#! /usr/bin/env nix-shell+#! nix-shell -i "dhall --file" -p dhall+42
+ dhall-lang/tests/parser/success/unit/ShebangNixB.dhallb view
@@ -0,0 +1,1 @@+‚*
+ dhall-lang/tests/parser/success/unit/ShowConstructorA.dhall view
@@ -0,0 +1,1 @@+showConstructor <A>.A
+ dhall-lang/tests/parser/success/unit/ShowConstructorB.dhallb view
@@ -0,0 +1,1 @@+‚"ƒ	‚¡aAöaA
+ dhall-lang/tests/parser/success/unit/ShowConstructorWithValueA.dhall view
@@ -0,0 +1,1 @@+showConstructor (<A : Bool>.A False)
+ dhall-lang/tests/parser/success/unit/ShowConstructorWithValueB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/SomeXA.dhall view
@@ -0,0 +1,1 @@+Some x
+ dhall-lang/tests/parser/success/unit/SomeXB.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/SomeXYZA.dhall view
@@ -0,0 +1,6 @@+{-+This is always a type error, but if this+was a parse error it would be quite confusing+because Some looks like a builtin.+-}+Some x y z
+ dhall-lang/tests/parser/success/unit/SomeXYZB.dhallb view

binary file changed (absent → 17 bytes)

+ dhall-lang/tests/parser/success/unit/SortA.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/parser/success/unit/SortB.dhallb view
@@ -0,0 +1,1 @@+dSort
+ dhall-lang/tests/parser/success/unit/TimeA.dhall view
@@ -0,0 +1,1 @@+Time
+ dhall-lang/tests/parser/success/unit/TimeB.dhallb view
@@ -0,0 +1,1 @@+dTime
+ dhall-lang/tests/parser/success/unit/TimeLiteralA.dhall view
@@ -0,0 +1,1 @@+12:00:00
+ dhall-lang/tests/parser/success/unit/TimeLiteralB.dhallb view

binary file changed (absent → 9 bytes)

+ dhall-lang/tests/parser/success/unit/TimeZoneA.dhall view
@@ -0,0 +1,1 @@+TimeZone
+ dhall-lang/tests/parser/success/unit/TimeZoneB.dhallb view
@@ -0,0 +1,1 @@+hTimeZone
+ dhall-lang/tests/parser/success/unit/TimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@++08:00
+ dhall-lang/tests/parser/success/unit/TimeZoneLiteralB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/ToMapA.dhall view
@@ -0,0 +1,1 @@+toMap x
+ dhall-lang/tests/parser/success/unit/ToMapAnnotA.dhall view
@@ -0,0 +1,1 @@+toMap x : T
+ dhall-lang/tests/parser/success/unit/ToMapAnnotB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ToMapB.dhallb view

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineA.dhall view
@@ -0,0 +1,2 @@+-- This test verifies that a trailing line comment does not require a newline+1--
+ dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/unit/TypeA.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/parser/success/unit/TypeB.dhallb view
@@ -0,0 +1,1 @@+dType
+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+< >
+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyDelimA.dhall view
@@ -0,0 +1,1 @@+< | >
+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyDelimB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/UnionTypeLeadingDelimA.dhall view
@@ -0,0 +1,1 @@+< | x: T | y: U >
+ dhall-lang/tests/parser/success/unit/UnionTypeLeadingDelimB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeSomeA.dhall view
@@ -0,0 +1,1 @@+< Some: Natural >
+ dhall-lang/tests/parser/success/unit/UnionTypeSomeB.dhallb view
@@ -0,0 +1,1 @@+‚¡dSomegNatural
+ dhall-lang/tests/parser/success/unit/UnionTypeTrailingAndLeadingDelimsA.dhall view
@@ -0,0 +1,1 @@+< | x: T | y: U | >
+ dhall-lang/tests/parser/success/unit/UnionTypeTrailingAndLeadingDelimsB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeTrailingDelimA.dhall view
@@ -0,0 +1,1 @@+< x: T | y: U | >
+ dhall-lang/tests/parser/success/unit/UnionTypeTrailingDelimB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeXA.dhall view
@@ -0,0 +1,1 @@+< x >
+ dhall-lang/tests/parser/success/unit/UnionTypeXB.dhallb view
@@ -0,0 +1,1 @@+‚¡axö
+ dhall-lang/tests/parser/success/unit/UnionTypeXTYA.dhall view
@@ -0,0 +1,1 @@+< x: T | y >
+ dhall-lang/tests/parser/success/unit/UnionTypeXTYB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeXTYUA.dhall view
@@ -0,0 +1,1 @@+< x: T | y: U >
+ dhall-lang/tests/parser/success/unit/UnionTypeXTYUB.dhallb view

binary file changed (absent → 15 bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeXYA.dhall view
@@ -0,0 +1,1 @@+< x | y >
+ dhall-lang/tests/parser/success/unit/UnionTypeXYB.dhallb view
@@ -0,0 +1,1 @@+‚¢axöayö
+ dhall-lang/tests/parser/success/unit/UnionTypeXYTA.dhall view
@@ -0,0 +1,1 @@+< x | y: T >
+ dhall-lang/tests/parser/success/unit/UnionTypeXYTB.dhallb view

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/VariableA.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/parser/success/unit/VariableB.dhallb view

binary file changed (absent → 4 bytes)

+ dhall-lang/tests/parser/success/unit/VariableQuotedWithSpaceA.dhall view
@@ -0,0 +1,1 @@+` x `
+ dhall-lang/tests/parser/success/unit/VariableQuotedWithSpaceB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/VariableUnderscoreA.dhall view
@@ -0,0 +1,1 @@+_
+ dhall-lang/tests/parser/success/unit/VariableUnderscoreB.dhallb view

binary file changed (absent → 1 bytes)

+ dhall-lang/tests/parser/success/unit/WithA.dhall view
@@ -0,0 +1,1 @@+{ a = 1 } with a = 2
+ dhall-lang/tests/parser/success/unit/WithB.dhallb view
@@ -0,0 +1,1 @@+„‚¡aa‚aa‚
+ dhall-lang/tests/parser/success/unit/WithMultipleA.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation correctly encodes chained+   `with` expressions in a left-associative way.+-}+{ a.b = 1, c.d = 2 } with a.b = 3 with c.e = 4
+ dhall-lang/tests/parser/success/unit/WithMultipleB.dhallb view
@@ -0,0 +1,1 @@+„„‚¢aa‚¡ab‚ac‚¡ad‚‚aaab‚‚acae‚
+ dhall-lang/tests/parser/success/unit/WithPrecedence1A.dhall view
@@ -0,0 +1,13 @@+{-  The purpose of this test is to illustrate that function application has+    higher precedence than `with` so that chained with expressions parse+    correctly++    The following expression should parse as:++        ({ a = Some 1 } with a = Some 2) with a = Some 3++    ... and not parse as:++        { a = Some 1 } with a = (Some 2 with a = Some 3)+-}+{ a = Some 1 } with a = Some 2 with a = Some 3
+ dhall-lang/tests/parser/success/unit/WithPrecedence1B.dhallb view
@@ -0,0 +1,1 @@+„„‚¡aaƒö‚aaƒö‚aaƒö‚
+ dhall-lang/tests/parser/success/unit/WithPrecedence2A.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } with x = 1 + 1
+ dhall-lang/tests/parser/success/unit/WithPrecedence2B.dhallb view

binary file changed (absent → 23 bytes)

+ dhall-lang/tests/parser/success/unit/WithPrecedence3A.dhall view
@@ -0,0 +1,1 @@+foo::{ x = 0 } with x = 1
+ dhall-lang/tests/parser/success/unit/WithPrecedence3B.dhallb view

binary file changed (absent → 26 bytes)

+ dhall-lang/tests/parser/success/unit/WithSomeA.dhall view
@@ -0,0 +1,1 @@+{ Some = 0 } with Some = 1
+ dhall-lang/tests/parser/success/unit/WithSomeB.dhallb view

binary file changed (absent → 23 bytes)

+ dhall-lang/tests/parser/success/unit/ifThenElseA.dhall view
@@ -0,0 +1,1 @@+if True then 1 else 2
+ dhall-lang/tests/parser/success/unit/ifThenElseB.dhallb view
@@ -0,0 +1,1 @@+„õ‚‚
+ dhall-lang/tests/parser/success/unit/import/AsLocationAbsoluteA.dhall view
@@ -0,0 +1,1 @@+/absolute/import as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationAbsoluteB.dhallb view
@@ -0,0 +1,1 @@+†öhabsolutefimport
+ dhall-lang/tests/parser/success/unit/import/AsLocationEnvA.dhall view
@@ -0,0 +1,1 @@+env:HOME as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationEnvB.dhallb view
@@ -0,0 +1,1 @@+…ödHOME
+ dhall-lang/tests/parser/success/unit/import/AsLocationHashA.dhall view
@@ -0,0 +1,1 @@+./some/import sha256:0000000000000000000000000000000000000000000000000000000000000000 as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationHashB.dhallb view

binary file changed (absent → 53 bytes)

+ dhall-lang/tests/parser/success/unit/import/AsLocationLocalA.dhall view
@@ -0,0 +1,1 @@+./local/import as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationLocalB.dhallb view
@@ -0,0 +1,1 @@+†öelocalfimport
+ dhall-lang/tests/parser/success/unit/import/AsLocationMissingA.dhall view
@@ -0,0 +1,1 @@+missing as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationMissingB.dhallb view
@@ -0,0 +1,1 @@+„ö
+ dhall-lang/tests/parser/success/unit/import/AsLocationRemoteA.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/package.dhall as Location
+ dhall-lang/tests/parser/success/unit/import/AsLocationRemoteB.dhallb view
@@ -0,0 +1,1 @@+ˆöövprelude.dhall-lang.orgmpackage.dhallö
+ dhall-lang/tests/parser/success/unit/import/HeadersA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using x
+ dhall-lang/tests/parser/success/unit/import/HeadersB.dhallb view

binary file changed (absent → 27 bytes)

+ dhall-lang/tests/parser/success/unit/import/HeadersDoubleHashA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using (./headers sha256:0000000000000000000000000000000000000000000000000000000000000000) sha256:1111111111111111111111111111111111111111111111111111111111111111
+ dhall-lang/tests/parser/success/unit/import/HeadersDoubleHashB.dhallb view

binary file changed (absent → 107 bytes)

+ dhall-lang/tests/parser/success/unit/import/HeadersDoubleHashPrecedenceA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using ./headers sha256:0000000000000000000000000000000000000000000000000000000000000000 sha256:1111111111111111111111111111111111111111111111111111111111111111
+ dhall-lang/tests/parser/success/unit/import/HeadersDoubleHashPrecedenceB.dhallb view

binary file changed (absent → 107 bytes)

+ dhall-lang/tests/parser/success/unit/import/HeadersHashPrecedenceA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using ./headers sha256:0000000000000000000000000000000000000000000000000000000000000000
+ dhall-lang/tests/parser/success/unit/import/HeadersHashPrecedenceB.dhallb view

binary file changed (absent → 72 bytes)

+ dhall-lang/tests/parser/success/unit/import/HeadersInteriorHashA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using (./headers sha256:0000000000000000000000000000000000000000000000000000000000000000)
+ dhall-lang/tests/parser/success/unit/import/HeadersInteriorHashB.dhallb view

binary file changed (absent → 72 bytes)

+ dhall-lang/tests/parser/success/unit/import/ImportAsNoSpaceA.dhall view
@@ -0,0 +1,1 @@+./import asText
+ dhall-lang/tests/parser/success/unit/import/ImportAsNoSpaceB.dhallb view

binary file changed (absent → 24 bytes)

+ dhall-lang/tests/parser/success/unit/import/MissingA.dhall view
@@ -0,0 +1,1 @@+missing
+ dhall-lang/tests/parser/success/unit/import/MissingB.dhallb view

binary file changed (absent → 6 bytes)

+ dhall-lang/tests/parser/success/unit/import/asTextA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo as Text
+ dhall-lang/tests/parser/success/unit/import/asTextB.dhallb view
@@ -0,0 +1,1 @@+ˆöökexample.comcfooö
+ dhall-lang/tests/parser/success/unit/import/environmentVariableBashA.dhall view
@@ -0,0 +1,1 @@+env:FOO
+ dhall-lang/tests/parser/success/unit/import/environmentVariableBashB.dhallb view

binary file changed (absent → 10 bytes)

+ dhall-lang/tests/parser/success/unit/import/environmentVariablePosixA.dhall view
@@ -0,0 +1,2 @@+-- Yes, this is legal+env:"\"\\\a\b\f\n\r\t\v!<[~"
+ dhall-lang/tests/parser/success/unit/import/environmentVariablePosixB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/import/hashA.dhall view
@@ -0,0 +1,1 @@+./a.dhall sha256:16173e984d35ee3ffd8b6b79167df89480e67d1cd03ea5d0fc93689e4d928e61
+ dhall-lang/tests/parser/success/unit/import/hashB.dhallb view

binary file changed (absent → 49 bytes)

+ dhall-lang/tests/parser/success/unit/import/importAltA.dhall view
@@ -0,0 +1,1 @@+env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3 ? 2
+ dhall-lang/tests/parser/success/unit/import/importAltB.dhallb view

binary file changed (absent → 60 bytes)

+ dhall-lang/tests/parser/success/unit/import/inlineUsingA.dhall view
@@ -0,0 +1,14 @@+{- The language standard used to require that custom headers were provided via+   an external import, but was later amended to support inline headers as part+   of:++   https://github.com/dhall-lang/dhall-lang/pull/560++   This test verifies that an implementation supports such inline custom headers+-}++https://example.com/foo using+    [ { mapKey   = "Authorization"+      , mapValue = "token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4"+      }+    ]
+ dhall-lang/tests/parser/success/unit/import/inlineUsingB.dhallb view

binary file changed (absent → 111 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathAbsoluteA.dhall view
@@ -0,0 +1,1 @@+/absolute/path
+ dhall-lang/tests/parser/success/unit/import/pathAbsoluteB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathHereA.dhall view
@@ -0,0 +1,1 @@+./relative/path
+ dhall-lang/tests/parser/success/unit/import/pathHereB.dhallb view

binary file changed (absent → 20 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathHomeA.dhall view
@@ -0,0 +1,1 @@+~/home/anchored/path
+ dhall-lang/tests/parser/success/unit/import/pathHomeB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathParentA.dhall view
@@ -0,0 +1,1 @@+../parent/path
+ dhall-lang/tests/parser/success/unit/import/pathParentB.dhallb view

binary file changed (absent → 18 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathTerminationLambdaA.dhall view
@@ -0,0 +1,2 @@+-- Verify that certain punctuation marks terminate paths correctly+λ(x : ./example) -> x
+ dhall-lang/tests/parser/success/unit/import/pathTerminationLambdaB.dhallb view

binary file changed (absent → 22 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathTerminationListA.dhall view
@@ -0,0 +1,2 @@+-- Verify that certain punctuation marks terminate paths correctly+[./example,./example, ./example]
+ dhall-lang/tests/parser/success/unit/import/pathTerminationListB.dhallb view

binary file changed (absent → 45 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathTerminationRecordA.dhall view
@@ -0,0 +1,2 @@+-- Verify that certain punctuation marks terminate paths correctly+{foo = ./example, bar = ./example}
+ dhall-lang/tests/parser/success/unit/import/pathTerminationRecordB.dhallb view

binary file changed (absent → 39 bytes)

+ dhall-lang/tests/parser/success/unit/import/pathTerminationUnionA.dhall view
@@ -0,0 +1,2 @@+-- Verify that certain punctuation marks terminate paths correctly+<foo: ./example| bar: ./example>
+ dhall-lang/tests/parser/success/unit/import/pathTerminationUnionB.dhallb view

binary file changed (absent → 47 bytes)

+ dhall-lang/tests/parser/success/unit/import/quotedPathsA.dhall view
@@ -0,0 +1,1 @@+/"foo"/bar/"baz qux"
+ dhall-lang/tests/parser/success/unit/import/quotedPathsB.dhallb view

binary file changed (absent → 22 bytes)

+ dhall-lang/tests/parser/success/unit/import/unicodePathsA.dhall view
@@ -0,0 +1,1 @@+./families/"禺.dhall"
+ dhall-lang/tests/parser/success/unit/import/unicodePathsB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/basicHttpA.dhall view
@@ -0,0 +1,1 @@+http://example.com/someFile.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/basicHttpB.dhallb view

binary file changed (absent → 35 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/basicHttpsA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True
+ dhall-lang/tests/parser/success/unit/import/urls/basicHttpsB.dhallb view

binary file changed (absent → 116 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/emptyPath0A.dhall view
@@ -0,0 +1,3 @@+-- the normal form for an empty path is a path of `/`+-- see RFC7230 section 2.7.3+https://example.com
+ dhall-lang/tests/parser/success/unit/import/urls/emptyPath0B.dhallb view

binary file changed (absent → 21 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/emptyPath1A.dhall view
@@ -0,0 +1,1 @@+https://example.com/
+ dhall-lang/tests/parser/success/unit/import/urls/emptyPath1B.dhallb view

binary file changed (absent → 21 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/emptyPathSegmentA.dhall view
@@ -0,0 +1,2 @@+-- empty path segments are not equivalent to missing path segments+https://example.com/foo//bar
+ dhall-lang/tests/parser/success/unit/import/urls/emptyPathSegmentB.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/emptyQueryA.dhall view
@@ -0,0 +1,3 @@+-- an empty query string is not the same as a missing one+-- see RFC 3986 section 6.2.3+https://example.com/foo?
+ dhall-lang/tests/parser/success/unit/import/urls/emptyQueryB.dhallb view

binary file changed (absent → 24 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/escapedPathA.dhall view
@@ -0,0 +1,1 @@+https://example.com/a%20b/c%2fd/e+f/g%2dh
+ dhall-lang/tests/parser/success/unit/import/urls/escapedPathB.dhallb view

binary file changed (absent → 42 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/escapedQueryA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo?a%20b=c%2fd&e+f/?
+ dhall-lang/tests/parser/success/unit/import/urls/escapedQueryB.dhallb view

binary file changed (absent → 41 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/fragmentParsesAsListAppendA.dhall view
@@ -0,0 +1,11 @@+{- Fragment identifiers are not allowed in URLs because they serve no purpose+   for Dhall and they could lead to ambiguity if a parser interprets them as+   the list append operator (`#`)++   The following expression therefore only has one valid parse, which is to+   interpret the `#` as a list append.  In other words, the following expression+   is parsed as:++   (https://example.com/foo) # bar+-}+https://example.com/foo#bar
+ dhall-lang/tests/parser/success/unit/import/urls/fragmentParsesAsListAppendB.dhallb view

binary file changed (absent → 33 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv4A.dhall view
@@ -0,0 +1,1 @@+https://127.0.0.1/index.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv4B.dhallb view

binary file changed (absent → 30 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv4upperoctetsA.dhall view
@@ -0,0 +1,1 @@+https://200.249.250.255/index.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv4upperoctetsB.dhallb view

binary file changed (absent → 36 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv6longA.dhall view
@@ -0,0 +1,1 @@+https://[2001:db8:85a3:0:0:8a2e:370:7334]/tutorial.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv6longB.dhallb view

binary file changed (absent → 58 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv6mediumA.dhall view
@@ -0,0 +1,1 @@+https://[2001:db8:85a3::8a2e:370:7334]/tutorial.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv6mediumB.dhallb view

binary file changed (absent → 55 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv6shortA.dhall view
@@ -0,0 +1,1 @@+https://[::]/index.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv6shortB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv6verylongA.dhall view
@@ -0,0 +1,1 @@+http://[AAAA:BBBB:CCCC:DDDD:EEEE:FFFF:0000::]/tutorial.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv6verylongB.dhallb view

binary file changed (absent → 63 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/ipv6withipv4A.dhall view
@@ -0,0 +1,1 @@+https://[2001:db8:85a3::8a2e:3.112.115.52]/tutorial.dhall
+ dhall-lang/tests/parser/success/unit/import/urls/ipv6withipv4B.dhallb view

binary file changed (absent → 59 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/portA.dhall view
@@ -0,0 +1,1 @@+https://example.com:1234/foo
+ dhall-lang/tests/parser/success/unit/import/urls/portB.dhallb view

binary file changed (absent → 29 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/potPourriA.dhall view
@@ -0,0 +1,1 @@+https://-._~%2C!$&'*+;=:@0abc1--12a------a-a--a-0/foo?/-._~%2C!$&'*+;=:@/?
+ dhall-lang/tests/parser/success/unit/import/urls/potPourriB.dhallb view

binary file changed (absent → 75 bytes)

+ dhall-lang/tests/parser/success/unit/import/urls/userinfoA.dhall view
@@ -0,0 +1,1 @@+https://john:doe@example.com/foo
+ dhall-lang/tests/parser/success/unit/import/urls/userinfoB.dhallb view

binary file changed (absent → 33 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolAndA.dhall view
@@ -0,0 +1,1 @@+x && y
+ dhall-lang/tests/parser/success/unit/operators/BoolAndAssocA.dhall view
@@ -0,0 +1,1 @@+w && x && y && z
+ dhall-lang/tests/parser/success/unit/operators/BoolAndAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolAndB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolEQA.dhall view
@@ -0,0 +1,1 @@+x == y
+ dhall-lang/tests/parser/success/unit/operators/BoolEQAssocA.dhall view
@@ -0,0 +1,1 @@+w == x == y == z
+ dhall-lang/tests/parser/success/unit/operators/BoolEQAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolEQB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolNEA.dhall view
@@ -0,0 +1,1 @@+x != y
+ dhall-lang/tests/parser/success/unit/operators/BoolNEAssocA.dhall view
@@ -0,0 +1,1 @@+w != x != y != z
+ dhall-lang/tests/parser/success/unit/operators/BoolNEAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolNEB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolOrA.dhall view
@@ -0,0 +1,1 @@+x || y
+ dhall-lang/tests/parser/success/unit/operators/BoolOrAssocA.dhall view
@@ -0,0 +1,1 @@+w || x || y || z
+ dhall-lang/tests/parser/success/unit/operators/BoolOrAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/BoolOrB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/EquivalenceA.dhall view
@@ -0,0 +1,1 @@+x === y
+ dhall-lang/tests/parser/success/unit/operators/EquivalenceAssocA.dhall view
@@ -0,0 +1,1 @@+w === x === y === z
+ dhall-lang/tests/parser/success/unit/operators/EquivalenceAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/EquivalenceB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/ImportAltA.dhall view
@@ -0,0 +1,1 @@+x ? y
+ dhall-lang/tests/parser/success/unit/operators/ImportAltAssocA.dhall view
@@ -0,0 +1,1 @@+w ? x ? y ? z
+ dhall-lang/tests/parser/success/unit/operators/ImportAltAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/ImportAltB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/ListAppendA.dhall view
@@ -0,0 +1,1 @@+x # y
+ dhall-lang/tests/parser/success/unit/operators/ListAppendAssocA.dhall view
@@ -0,0 +1,1 @@+w # x # y # z
+ dhall-lang/tests/parser/success/unit/operators/ListAppendAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/ListAppendB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/NaturalPlusA.dhall view
@@ -0,0 +1,1 @@+x + y
+ dhall-lang/tests/parser/success/unit/operators/NaturalPlusAssocA.dhall view
@@ -0,0 +1,1 @@+w + x + y + z
+ dhall-lang/tests/parser/success/unit/operators/NaturalPlusAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/NaturalPlusB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/NaturalTimesA.dhall view
@@ -0,0 +1,1 @@+x * y
+ dhall-lang/tests/parser/success/unit/operators/NaturalTimesAssocA.dhall view
@@ -0,0 +1,1 @@+w * x * y * z
+ dhall-lang/tests/parser/success/unit/operators/NaturalTimesAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/NaturalTimesB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/PrecedenceBoolA.dhall view
@@ -0,0 +1,1 @@+a && b || c d == e || f != g && h || i
+ dhall-lang/tests/parser/success/unit/operators/PrecedenceBoolB.dhallb view

binary file changed (absent → 59 bytes)

+ dhall-lang/tests/parser/success/unit/operators/PrecedenceEquivalenceA.dhall view
@@ -0,0 +1,1 @@+2 + 3 * 4 === 4 * 3 + 2
+ dhall-lang/tests/parser/success/unit/operators/PrecedenceEquivalenceB.dhallb view
@@ -0,0 +1,1 @@+„„‚„‚‚„„‚‚‚
+ dhall-lang/tests/parser/success/unit/operators/PrecedenceNatA.dhall view
@@ -0,0 +1,1 @@+a + b * d + e f * (g + h)
+ dhall-lang/tests/parser/success/unit/operators/PrecedenceNatB.dhallb view

binary file changed (absent → 45 bytes)

+ dhall-lang/tests/parser/success/unit/operators/PrecedenceRecordA.dhall view
@@ -0,0 +1,1 @@+a // b c /\ d ⫽ e.{x} ∧ f
+ dhall-lang/tests/parser/success/unit/operators/PrecedenceRecordB.dhallb view

binary file changed (absent → 42 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeA.dhall view
@@ -0,0 +1,1 @@+x /\ y
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocA.dhall view
@@ -0,0 +1,1 @@+w /\ x /\ y /\ z
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeUnicodeA.dhall view
@@ -0,0 +1,1 @@+x ∧ y
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeUnicodeAssocA.dhall view
@@ -0,0 +1,1 @@+w ∧ x /\ y ∧ z
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeUnicodeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeUnicodeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeA.dhall view
@@ -0,0 +1,1 @@+x //\\ y
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeAssocA.dhall view
@@ -0,0 +1,1 @@+w //\\ x //\\ y //\\ z
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeUnicodeA.dhall view
@@ -0,0 +1,1 @@+x ⩓ y
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeUnicodeAssocA.dhall view
@@ -0,0 +1,1 @@+w ⩓ x //\\ y ⩓ z
+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeUnicodeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeUnicodeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeA.dhall view
@@ -0,0 +1,1 @@+x // y
+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeAssocA.dhall view
@@ -0,0 +1,1 @@+w // x // y // z
+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeUnicodeA.dhall view
@@ -0,0 +1,1 @@+x ⫽ y
+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeUnicodeAssocA.dhall view
@@ -0,0 +1,1 @@+w ⫽ x // y ⫽ z
+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeUnicodeAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/RightBiasedRecordMergeUnicodeB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/operators/TextAppendA.dhall view
@@ -0,0 +1,1 @@+x ++ y
+ dhall-lang/tests/parser/success/unit/operators/TextAppendAssocA.dhall view
@@ -0,0 +1,1 @@+w ++ x ++ y ++ z
+ dhall-lang/tests/parser/success/unit/operators/TextAppendAssocB.dhallb view

binary file changed (absent → 25 bytes)

+ dhall-lang/tests/parser/success/unit/operators/TextAppendB.dhallb view

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/usingToMapA.dhall view
@@ -0,0 +1,1 @@+https://example.com using (toMap { Foo = "Bar" })
+ dhall-lang/tests/parser/success/usingToMapB.dhallb view

binary file changed (absent → 36 bytes)

+ dhall-lang/tests/parser/success/whitespaceA.dhall view
@@ -0,0 +1,3 @@++1+
+ dhall-lang/tests/parser/success/whitespaceB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/whitespaceBuffetA.dhall view
@@ -0,0 +1,9 @@+    -- This+
+     Natural/even {-+
+{- file+-}
+  has+
+ -}  2 -- mixed {- line endings -}
+ dhall-lang/tests/parser/success/whitespaceBuffetB.dhallb view

binary file changed (absent → 18 bytes)

+ dhall-lang/tests/parser/success/withQuestionMarkA.dhall view
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
+ dhall-lang/tests/parser/success/withQuestionMarkB.dhallb view

binary file changed (absent → 14 bytes)

+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/0A.dhall view
@@ -0,0 +1,1 @@+{ x = "foo" }.x
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/0B.hash view
@@ -0,0 +1,1 @@+sha256:fd881e3d48cbc85b4044697bdce8167a77f3fb4665ff0b647a1210a17528818a
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/1A.dhall view
@@ -0,0 +1,1 @@+< Foo : Text | Bar : Natural >.Foo
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/1B.hash view
@@ -0,0 +1,1 @@+sha256:35ba8bddad36acfb29cc6f1700364544c145e96cf522f592f18f90c2f96e6e9c
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/0A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/0B.hash view
@@ -0,0 +1,1 @@+sha256:4495bbf3fea6c579c65ee51463b225747803b94668013528b9ca0384304cb350
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/1A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/1B.hash view
@@ -0,0 +1,1 @@+sha256:4495bbf3fea6c579c65ee51463b225747803b94668013528b9ca0384304cb350
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/0A.dhall view
@@ -0,0 +1,1 @@+{ foo = 1, bar = "ABC" } // { baz = True }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/0B.hash view
@@ -0,0 +1,1 @@+sha256:18fbad84131d28b6d412e6bc09d5ee8eaf432b639c6cc6f1bef1b4ef366642d7
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/0A.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = True, z = "ABC" }.{ x, y }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/0B.hash view
@@ -0,0 +1,1 @@+sha256:b7ae500723633be94b53b905384236fcd18cbce59314bb51044bb7d3f3939e6e
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall True
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall False
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall True
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:cdbb7fd982ba05e709fe67b23818fffb65ff9c0b8abde1abb5ac1a8245891a3f
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall False
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:2357bb42b56beb99180d967177c0490061bd3536a147dfe144d2630f983004e5
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall -3.1
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:d0b3cdb4f3cd5375495629450de676f445c0da6980a5ada251df199079d0ef89
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall 0.4
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:dd5e8756d06f12ef6e003dc769b6e1222e5aa0c8491579dc65b2dd6f4f0ec53d
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall -3
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:053de6c2b7f281dd82dd9b643cc848e64633b88c9c57082ec0ac41257c5592d7
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall +0
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:4ab1c5aa262f39cdbe1f4924accb69bb44e2a616b5a0ca39655eebd0cc863d33
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall -3
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0B.hash view
@@ -0,0 +1,1 @@+sha256:3c97d2d6c7d01c1c324e6e0a7fcf3b756ff56cf1bf398c4945f04898ae9325a7
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall +2
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1B.hash view
@@ -0,0 +1,1 @@+sha256:fe5c1f8c6cc72fc9aeb61e3b0c5217bf62d2427bcfa678aeefeaa9d04cb9627c
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ cons "ABC" (cons "DEF" nil)+)
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:8a08646db7447b14cf03a497635242b6fb76365017fc1699b2a8807272a2ec58
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ nil+)
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:6da0c98142d1168ac9d6080b7853d2b59b97d42079e1b2f121daf449b3b2e449
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/0A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [ 0, 1, 2 ]+, [ 3, 4 ]+, [ 5, 6, 7, 8 ]+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:ae3a399d05bafcee80c088ca6c740f0c61c2a4c6fce6d7e4f4fa26560eac083f
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/1A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [] : List Natural+, [] : List Natural+, [] : List Natural+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0B.hash view
@@ -0,0 +1,1 @@+sha256:ea1f5046bcba6efb41bde23738d9a3f3aa2cda3dc722999d9e4f477eb9d1b12d
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/0B.hash view
@@ -0,0 +1,1 @@+sha256:988afbf26d86e95a4e6b78b0c344c9f987dcd5f7d7a7c541601bb1e9a01c9102
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/1B.hash view
@@ -0,0 +1,1 @@+sha256:68248e1b69b249e6aeebcd36e7034f159b75d2931105fb4d41fc55d644b7ee8d
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/List/fold.dhall+Natural+[ 2, 3, 5 ]+Natural+(λ(x : Natural) → λ(y : Natural) → x + y)+0
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:d4428061b6fd69b6b45574603ac71060f9756a5c9a1642df322812e3a7ea858b
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/1A.dhall view
@@ -0,0 +1,7 @@+  λ(nil : Natural)+→ ../../../../../../Prelude/List/fold.dhall+  Natural+  [ 2, 3, 5 ]+  Natural+  (λ(x : Natural) → λ(y : Natural) → x + y)+  nil
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:3bd732ae873cb107c3dfef4ae953f6480af310b27fda6b678b43569841e1012b
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(list : Type)+→ λ(cons : Natural → list → list)+→ λ(nil : list)+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/2B.hash view
@@ -0,0 +1,1 @@+sha256:186c485f65cbbf97aba127a1205a16ee1125ec279e727ff05d8f8ada624257c7
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/0B.hash view
@@ -0,0 +1,1 @@+sha256:0860d18cdc28bc4e7b081bf8c9891ab07e303e4f72b3439bb3a92d7dedd7e8fa
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/1B.hash view
@@ -0,0 +1,1 @@+sha256:fb7841e1b3b3e3511196b38df96e73ac7785edef663ea450f97b3c1322742d69
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/0B.hash view
@@ -0,0 +1,1 @@+sha256:7ac81b06d39113c93f17cc3d2aa55867453f68f35f58a4d577f5bacbb969225f
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0B.hash view
@@ -0,0 +1,1 @@+sha256:7225a557384940f3f2f7f40e5e3e36384be7892c08a24e5467d0f75cd0dda9e1
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1B.hash view
@@ -0,0 +1,1 @@+sha256:ff10538dd6bf3bf736bf38f54575e1ddd251aa1d6aad7c6ff6f4159bfc87cc4a
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0B.hash view
@@ -0,0 +1,1 @@+sha256:577ea4905798b4fbd4803b3a7c82902594f0c3e5d84af46cec4514da9801760a
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/0B.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/0B.hash view
@@ -0,0 +1,1 @@+sha256:aaf20d96e69473f836397764ec61b64a65dc5084ee33692ecd8b85ca63962827
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/1B.hash view
@@ -0,0 +1,1 @@+sha256:fb7841e1b3b3e3511196b38df96e73ac7785edef663ea450f97b3c1322742d69
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0B.hash view
@@ -0,0 +1,1 @@+sha256:4241079fe7c8a46be37831a35dedb60645c3a86a2ab24778e03c27c820813cdc
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0B.hash view
@@ -0,0 +1,1 @@+sha256:ed586af4895ad8118e77976c6ee2fef5a39f69eb9378df32349c81fee2d61d4d
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0A.dhall view
@@ -0,0 +1,15 @@+../../../../../../Prelude/List/shifted.dhall+Bool+[ [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = False }+  ]+, [ { index = 0, value = False }+  , { index = 1, value = False }+  ]+, [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = True }+  , { index = 3, value = True }+  ]+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0B.hash view
@@ -0,0 +1,1 @@+sha256:e5c27411e9b0692ac96e6914420f17748eda33d3854067675c6a3b3780fb15a6
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1B.hash view
@@ -0,0 +1,1 @@+sha256:ff10538dd6bf3bf736bf38f54575e1ddd251aa1d6aad7c6ff6f4159bfc87cc4a
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/unzip.dhall+Text+Bool+[ { _1 = "ABC", _2 = True }+, { _1 = "DEF", _2 = False }+, { _1 = "GHI", _2 = True }+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0B.hash view
@@ -0,0 +1,1 @@+sha256:fffb0db166d08b99a1beb1650a3c9ee6e7bf6ce1054150bea4dae9b8ce5e4fbf
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1B.hash view
@@ -0,0 +1,1 @@+sha256:c598ac5f10c7d20fe201f94ed5d9d18a847e89c65db9478492c930e5c42af710
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ succ (succ (succ zero))+)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ zero+)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 10
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0B.hash view
@@ -0,0 +1,1 @@+sha256:a7af1902b53cc68a9613b659ebf58d06c840072625d14f9fde7eefa0e0f2add0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:39b0b6e0e0b616af4f20c7b06fefcd26dcdbd5be772d885fe73487574ec8b56b
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1A.dhall view
@@ -0,0 +1,1 @@+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:c6ddb630f2abfcd78aa874079323ba2a9f80f548c5687346a0fcedff78d14f52
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2B.hash view
@@ -0,0 +1,1 @@+sha256:08681d6fb9b1bb78be37f5a976186daa8fc39d0d1d3f7dbb716dc33937a6746d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0B.hash view
@@ -0,0 +1,1 @@+sha256:49036d5d861d35d4aff797975a3447ebae71a9057951a03fc810ab8e8e00a498
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:c8911e8084484ca0d468334986a19f0a11cc18b31f41f272e7d4ad2cd479ad39
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:e3062e0493964ebaef8880667ad8a6289c277618c0b31141610abf5d69e7c9ea
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0B.hash view
@@ -0,0 +1,1 @@+sha256:d4428061b6fd69b6b45574603ac71060f9756a5c9a1642df322812e3a7ea858b
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0B.hash view
@@ -0,0 +1,1 @@+sha256:45b03fd4a48720ca71d4d12967cdde317c918d7c0295845cf9628784a124108d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1B.hash view
@@ -0,0 +1,1 @@+sha256:3c213998cb56b97b31168d9dce02d084fb5f5103caef41fb6dc375f593749a7d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0B.hash view
@@ -0,0 +1,1 @@+sha256:aa773179ef61a5d65c774bcc510806531ce8fa97c550961526153e42959e6f76
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1B.hash view
@@ -0,0 +1,1 @@+sha256:5abe149a174ca99b6da92c97b0a7c8900a5f9acddb720bf7173eef877c6a187b
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ some 1+)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ none+)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:4caf97e8c445d4d4b5c5b992973e098ed4ae88a355915f5a59db640a589bc9cb
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0B.hash view
@@ -0,0 +1,1 @@+sha256:3af5b2f9dcc58e7950e2f0281f796de2ac5e87554ae758e38c36cd55cf53743e
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1B.hash view
@@ -0,0 +1,1 @@+sha256:2c9884f8336ed425b13068919b216c42be286636c657faa15b911382436b3f00
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0B.hash view
@@ -0,0 +1,1 @@+sha256:75be41333b1ef7a6f5c5cfbcd6097681f3968736dc393b9bf53b2e609564217f
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0B.hash view
@@ -0,0 +1,1 @@+sha256:5604f6ef6cf7385166101c61738c34a84983f1b7b4695858fa2068fc669eb2c1
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1B.hash view
@@ -0,0 +1,1 @@+sha256:6de82c54048538c97063c9ae31919b4ca21018ae7119bc123508c136ee653280
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:1f73cf8a6efa724376c3342f9e0104c499e16420732b8c25efc6ab1c18979772
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0B.hash view
@@ -0,0 +1,1 @@+sha256:fa7f18d0522f120dbf229ff0a55f96792ce76613ba17611c53f3f5efd81df510
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0B.hash view
@@ -0,0 +1,1 @@+sha256:952e63727a69b5f2db65645167c3a8f60dbc350608562a1c90423c819a1b5baf
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0B.hash view
@@ -0,0 +1,1 @@+sha256:151ad6d86cced932c9ed6fa5d69b88fb47e160a13762f4d92dcb1e847ccd30d6
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/show.dhall "ABC"
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:8dffa347e98424c7b1e91e3e3758fc203a4e52fd990dc4b050da18cdb39655d3
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/show.dhall "\u0000 \$ \\ \n \u263a"
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:92655b5ee59ddfb1decfd19cf8b37e8f2dd5dbd317f55bcbb780bf6ed2010b0a
+ dhall-lang/tests/semantic-hash/success/remoteSystemsA.dhall view
@@ -0,0 +1,51 @@+let Text/concatMap = ../../../Prelude/Text/concatMap++let Text/concatSep = ../../../Prelude/Text/concatSep++let Row =+      { cores :+          Natural+      , host :+          Text+      , key :+          Text+      , mandatoryFeatures :+          List Text+      , platforms :+          List Text+      , speedFactor :+          Natural+      , supportedFeatures :+          List Text+      , user :+          Optional Text+      }++let renderRow =+        λ ( row+          : Row+          )+      → let host =+              merge+                { None = row.host+                , Some = λ(user : Text) → "${user}@${row.host}"+                }+                row.user+        +        let platforms = Text/concatSep "," row.platforms+        +        let key = row.key+        +        let cores = Integer/show (Natural/toInteger row.cores)+        +        let speedFactor = Integer/show (Natural/toInteger row.speedFactor)+        +        let supportedFeatures = Text/concatSep "," row.supportedFeatures+        +        let mandatoryFeatures = Text/concatSep "," row.mandatoryFeatures+        +        in  ''+            ${host} ${platforms} ${key} ${cores} ${speedFactor} ${supportedFeatures} ${mandatoryFeatures}+            ''++in  Text/concatMap Row renderRow
+ dhall-lang/tests/semantic-hash/success/remoteSystemsB.hash view
@@ -0,0 +1,1 @@+sha256:573b0d8fbc28c09c155cf239963b6ba71941aace25e23806043017f7fe75098b
+ dhall-lang/tests/semantic-hash/success/simple/doubleShowA.dhall view
@@ -0,0 +1,6 @@+{ example0 = Double/show -0.42+, example1 = Double/show 13.37+, example2 = Double/show NaN+, example3 = Double/show Infinity+, example4 = Double/show -Infinity+}
+ dhall-lang/tests/semantic-hash/success/simple/doubleShowB.hash view
@@ -0,0 +1,1 @@+sha256:519ea07f25f759795d4326f06a97401fe0a5efe7823139976d1158c939ee6176
+ dhall-lang/tests/semantic-hash/success/simple/enumA.dhall view
@@ -0,0 +1,8 @@+let Role = < Wizard | Fighter | Rogue >++let show : Role → Text+         =+        λ(x : Role)+      → merge { Wizard = "Wizard", Fighter = "Fighter", Rogue = "Rogue" } x++in  show Role.Wizard
+ dhall-lang/tests/semantic-hash/success/simple/enumB.hash view
@@ -0,0 +1,1 @@+sha256:0e6e479638f87eca04805548d70b5de9d22c5359e7d84ccbcfe148577bc25a4e
+ dhall-lang/tests/semantic-hash/success/simple/integerShowA.dhall view
@@ -0,0 +1,4 @@+{ example0 = Integer/show +1337+, example1 = Integer/show -42+, example2 = Integer/show +0+}
+ dhall-lang/tests/semantic-hash/success/simple/integerShowB.hash view
@@ -0,0 +1,1 @@+sha256:7ff01ad1c68550be713834548385874f38fd7b989e3c4b8cad7125bc266e2bb3
+ dhall-lang/tests/semantic-hash/success/simple/integerToDoubleA.dhall view
@@ -0,0 +1,10 @@+[ Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944++, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944+]
+ dhall-lang/tests/semantic-hash/success/simple/integerToDoubleB.hash view
@@ -0,0 +1,1 @@+sha256:439d81a4aee03a27da069772c4ea51d64c025faac1a2e749734cc5e4cf0f2484
+ dhall-lang/tests/semantic-hash/success/simple/letletA.dhall view
@@ -0,0 +1,3 @@+let l = λ(n : Natural) → λ(m : Natural) → λ(x : Natural) → n + m * x+let f = l 2 3+in  f 445
+ dhall-lang/tests/semantic-hash/success/simple/letletB.hash view
@@ -0,0 +1,1 @@+sha256:97285916da4ee4a1e108af044b449edcdfb818c2f55aefd64f0af76b347da16d
+ dhall-lang/tests/semantic-hash/success/simple/listBuildA.dhall view
@@ -0,0 +1,22 @@+{ example0 =+    List/build+    Bool+    (   λ(list : Type)+      → λ(cons : Bool → list → list)+      → λ(nil : list)+      → cons True (cons False nil)+    )+, example1 =+    List/build+    Bool+    (λ(x : Type) → λ(x : Bool → x → x) → λ(x : x@1) → x@1 True (x@1 False x))+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → List/build+      Bool+      (   λ(list : Type)+        → λ(cons : Bool → list → list)+        → λ(nil : list)+        → id list (cons True (cons False nil))+      )+}
+ dhall-lang/tests/semantic-hash/success/simple/listBuildB.hash view
@@ -0,0 +1,1 @@+sha256:f8f03d5be6563b275253b4d995499e783112ff98ed231855e9152ba45970f8c7
+ dhall-lang/tests/semantic-hash/success/simple/multiLineA.dhall view
@@ -0,0 +1,4 @@+''+ foo+bar+''
+ dhall-lang/tests/semantic-hash/success/simple/multiLineB.hash view
@@ -0,0 +1,1 @@+sha256:2ab4fb081094ad6729186b7cd8a0ec67f7845bbea59ec5a484bff2de42390137
+ dhall-lang/tests/semantic-hash/success/simple/naturalBuildA.dhall view
@@ -0,0 +1,18 @@+{ example0 =+    Natural/build+    (   λ(natural : Type)+      → λ(succ : natural → natural)+      → λ(zero : natural)+      → succ zero+    )+, example1 =+    Natural/build (λ(x : Type) → λ(x : x → x) → λ(x : x@1) → x@1 x)+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → Natural/build+      (   λ(natural : Type)+        → λ(succ : natural → natural)+        → λ(zero : natural)+        → id natural (succ zero)+      )+}
+ dhall-lang/tests/semantic-hash/success/simple/naturalBuildB.hash view
@@ -0,0 +1,1 @@+sha256:3e14f3cbed2ddcc78cb9bf66bf2372c2059fd6c4b406ca309a05b89b7f62b011
+ dhall-lang/tests/semantic-hash/success/simple/naturalPlusA.dhall view
@@ -0,0 +1,1 @@+1 + 2
+ dhall-lang/tests/semantic-hash/success/simple/naturalPlusB.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/simple/naturalShowA.dhall view
@@ -0,0 +1,1 @@+Natural/show 42
+ dhall-lang/tests/semantic-hash/success/simple/naturalShowB.hash view
@@ -0,0 +1,1 @@+sha256:3d1abfe685ff9abcf5e1a6bcce9b1a8374fc8ac176c22ef3e0188bd29e7d8c6d
+ dhall-lang/tests/semantic-hash/success/simple/naturalToIntegerA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger 1
+ dhall-lang/tests/semantic-hash/success/simple/naturalToIntegerB.hash view
@@ -0,0 +1,1 @@+sha256:d2cbb0e226f332ea76d63b3ae4332780c4051d1388d3e190debd5441f4595a04
+ dhall-lang/tests/semantic-hash/success/simple/sortOperatorA.dhall view
@@ -0,0 +1,1 @@+{ b = 2 } // { a = 1 }
+ dhall-lang/tests/semantic-hash/success/simple/sortOperatorB.hash view
@@ -0,0 +1,1 @@+sha256:97090822fa42ff0245484a518e2457f85271f4c36fc9462b82498d85b2cc98fc
+ dhall-lang/tests/semantic-hash/success/simplifications/andA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x && True+, example1 = λ(x : Bool) → True && x+, example2 = λ(x : Bool) → x && False+, example3 = λ(x : Bool) → False && x+, example4 = λ(x : Bool) → x && x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/andB.hash view
@@ -0,0 +1,1 @@+sha256:ceac399e820b2a86c65077e07e77bb62f10253fda02a51e438457adf4368b580
+ dhall-lang/tests/semantic-hash/success/simplifications/eqA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x == True+, example1 = λ(x : Bool) → True == x+, example2 = λ(x : Bool) → x == x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/eqB.hash view
@@ -0,0 +1,1 @@+sha256:5524bd7e3ecdeaa98a25f51f40a1cb33896c2e3e0e21e14c939d17dac946fa4d
+ dhall-lang/tests/semantic-hash/success/simplifications/ifThenElseA.dhall view
@@ -0,0 +1,3 @@+{ example0 = λ(x : Bool) → if x then True else False+, example1 = λ(x : Bool) → λ(y : Text) → if x then y else y+}
+ dhall-lang/tests/semantic-hash/success/simplifications/ifThenElseB.hash view
@@ -0,0 +1,1 @@+sha256:40b3cdc4cc8f2ff9b733e5e8d8613ec8c3d17fc11f22cfd96d8109765c15add5
+ dhall-lang/tests/semantic-hash/success/simplifications/neA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x != False+, example1 = λ(x : Bool) → False != x+, example2 = λ(x : Bool) → x != x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/neB.hash view
@@ -0,0 +1,1 @@+sha256:69d11e754a064f8abe927e5df446896372a6367135e08c52b5c2274e3bd03bc7
+ dhall-lang/tests/semantic-hash/success/simplifications/orA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x || True+, example1 = λ(x : Bool) → True || x+, example2 = λ(x : Bool) → x || False+, example3 = λ(x : Bool) → False || x+, example4 = λ(x : Bool) → x || x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/orB.hash view
@@ -0,0 +1,1 @@+sha256:41437a8eb5753b2d340fc27cc192265459da57cd65d487447a261f2eede2f5ef
+ dhall-lang/tests/type-inference/failure/DateApplyTime.dhall view
@@ -0,0 +1,3 @@+-- This parses, but will fail to type-check, because in the absence of the `T`+-- it is interpreted as a `Date` applied to a `Time`+2020-01-01 12:00:00
+ dhall-lang/tests/type-inference/failure/SortInLet.dhall view
@@ -0,0 +1,1 @@+let x = Sort in 0
+ dhall-lang/tests/type-inference/failure/hurkensParadox.dhall view
@@ -0,0 +1,49 @@+    let bottom : Type = ∀(any : Type) → any++in  let not : Type → Type = λ(p : Type) → p → bottom++in  let pow = λ(X : Kind) → X → Type++in  let U = ∀(X : Kind) → (pow (pow X) → X) → pow (pow X)++in  let tau+        : pow (pow U) → U+        =   λ(t : pow (pow U))+          → λ(X : Kind)+          → λ(f : pow (pow X) → X)+          → λ(p : pow X)+          → t (λ(x : U) → p (f (x X f)))++in  let sigma : U → pow (pow U) = λ(s : U) → s U (λ(t : pow (pow U)) → tau t)++in  let Delta+        : pow U+        = λ(y : U) → not (∀(p : pow U) → sigma y p → p (tau (sigma y)))++in  let Omega : U = tau (λ(p : pow U) → ∀(x : U) → sigma x p → p x)++in  let Theta : Type = ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega++in  let D : Type = ∀(p : pow U) → sigma Omega p → p (tau (sigma Omega))++in  let lem1+        : ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega+        =   λ(p : pow U)+          → λ(t1 : ∀(x : U) → sigma x p → p x)+          → t1 Omega (λ(x : U) → t1 (tau (sigma x)))++in  let lem3 : D = λ(p : pow U) → lem1 (λ(y : U) → p (tau (sigma y)))++in  let lem2+        : not D+        = lem1+          Delta+          (   λ(x : U)+            → λ(H2 : sigma x Delta)+            → λ(H3 : ∀(p : pow U) → sigma x p → p (tau (sigma x)))+            → H3 Delta H2 (λ(pp : pow U) → H3 (λ(y : U) → pp (tau (sigma y))))+          )++in  let evidence : bottom = lem2 lem3++in  evidence
+ dhall-lang/tests/type-inference/failure/recordOfKind.dhall view
@@ -0,0 +1,1 @@+{ a = Kind }
+ dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall view
@@ -0,0 +1,1 @@+{ x = 1 } : { y : Natural }
+ dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall view
@@ -0,0 +1,1 @@+{ x = 1 } : { x : Text }
+ dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall view
@@ -0,0 +1,1 @@+assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
+ dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall view
@@ -0,0 +1,1 @@+\(_: Bool) -> assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
+ dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall view
@@ -0,0 +1,1 @@+assert : -0.0 ≡ +0.0
+ dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall view
@@ -0,0 +1,1 @@+assert : Bool
+ dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall view
@@ -0,0 +1,1 @@+assert : 1 === 2
+ dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { id = None Natural }+      }++in  Example::{=}
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = True, id = None Natural }+      }++in  Example::{=}
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  Example::{ nam = "John Doe" }
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  Example::{ name = True }
+ dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall view
@@ -0,0 +1,1 @@+toMap {=}
+ dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall view
@@ -0,0 +1,1 @@+1 === False
+ dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall view
@@ -0,0 +1,1 @@+Bool === Bool
+ dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall view
@@ -0,0 +1,1 @@+(λ(_ : Natural) → _) True
+ dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall view
@@ -0,0 +1,1 @@+True True
+ dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall view
@@ -0,0 +1,1 @@+λ(_ : 1) → _
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall view
@@ -0,0 +1,1 @@+2 → _
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall view
@@ -0,0 +1,1 @@+Kind → Sort
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall view
@@ -0,0 +1,1 @@+Bool -> 1
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall view
@@ -0,0 +1,1 @@+Type → Sort
+ dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= "Bar" }
+ dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall view
@@ -0,0 +1,1 @@+if True then 1 else ""
+ dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall view
@@ -0,0 +1,1 @@+if True then Kind else Kind
+ dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall view
@@ -0,0 +1,1 @@+if 1 then 1 else 1
+ dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall view
@@ -0,0 +1,1 @@+\(x: let x = 0 in Sort) -> 1
+ dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall view
@@ -0,0 +1,14 @@+-- When you check if an inferred type is equivalent to an annotation,+-- you must alpha-beta-normalize both sides first.  But it is not safe+-- to beta-normalise an expression which hasn't first been+-- typechecked.+--+-- This test contains an annotation which doesn't typecheck, and+-- which, when beta-normalized, doesn't terminate.  It exists to+-- verify that implementations typecheck the annotation before+-- checking equivalence.+let a+    : (λ(x : Natural) → x x) (λ(x : Natural) → x x)+    = 3++in  5
+ dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall view
@@ -0,0 +1,1 @@+let x : Natural = True in True
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall view
@@ -0,0 +1,1 @@+[] : List Type
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall view
@@ -0,0 +1,1 @@+[ Bool ]
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall view
@@ -0,0 +1,1 @@+[ True, 1 ]
+ dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall view
@@ -0,0 +1,1 @@+merge {=} (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall view
@@ -0,0 +1,1 @@+merge { x = 0 } < x >.x : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall view
@@ -0,0 +1,1 @@+merge {=} <> : Type
+ dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall view
@@ -0,0 +1,1 @@+\(x: { True: Natural, False: Natural }) -> merge x True
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall view
@@ -0,0 +1,1 @@+\(x: <>) -> (merge {=} x) : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall view
@@ -0,0 +1,1 @@+\(x: <>) -> let y: Bool = merge {=} x in 1
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall view
@@ -0,0 +1,1 @@+merge {=} <>
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall view
@@ -0,0 +1,1 @@+merge { x = None } (<x: Type>.x Bool)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall view
@@ -0,0 +1,1 @@+merge { x = True } (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } <> : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Natural >.x 1)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _, y = λ(_ : Natural) → _ } (< x : Bool | y : Natural >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+merge True < x >.x
+ dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall view
@@ -0,0 +1,1 @@+merge {=} <x>.x
+ dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall view
@@ -0,0 +1,1 @@+merge { x = 0 } <x | y>.x
+ dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall view
@@ -0,0 +1,1 @@+merge {=} True
+ dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall view
@@ -0,0 +1,1 @@+merge { x = 1, y = 2 } < x >.x
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : Natural
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List Natural
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Natural, mapValue : Natural }
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Text, mapValue : Text }
+ dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall view
@@ -0,0 +1,1 @@+Natural/subtract True True
+ dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall view
@@ -0,0 +1,1 @@+(0 : Bool) : Natural
+ dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall view
@@ -0,0 +1,1 @@+(0 : Natural) : Bool
+ dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall view
@@ -0,0 +1,1 @@+toMap "text"
+ dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall view
@@ -0,0 +1,1 @@+1 && 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall view
@@ -0,0 +1,1 @@+1 == 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall view
@@ -0,0 +1,1 @@+1 # [ True ]
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall view
@@ -0,0 +1,1 @@+[ True ] # [ 1 ]
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall view
@@ -0,0 +1,1 @@+1 # 2
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall view
@@ -0,0 +1,1 @@+[ True ] # 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall view
@@ -0,0 +1,1 @@+1 != 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall view
@@ -0,0 +1,1 @@+1 || 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall view
@@ -0,0 +1,1 @@+True + True
+ dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall view
@@ -0,0 +1,1 @@+1 ++ ""
+ dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall view
@@ -0,0 +1,1 @@+"" ++ 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall view
@@ -0,0 +1,1 @@+True * True
+ dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall view
@@ -0,0 +1,1 @@+[] : Optional Bool
+ dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall view
@@ -0,0 +1,1 @@+[ 1 ] : Optional Natural
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall view
@@ -0,0 +1,13 @@+{-  This test illustrates that duplicate fields need not be literals in order+    to be properly normalized.  One or both of the duplicate fields can be+    abstract because field duplication delegates its behavior to the `∧`+    operator++    This particular example fails because it desugars to:++        λ(r : { y : Natural }) → { x = { y = 1 } ∧ r }++    ... and the `∧` operator can infer that the two records collide on the+    field `y`+-}+λ(r : { y : Natural }) → { x = { y = 1 }, x = r }
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall view
@@ -0,0 +1,8 @@+{-  This fails because the expression desugars to:++        { x = { y = 0 } ∧ { y = 0 } }++    ... which is ill-typed due to `∧` forbidding collisions and the two `y`+    fields collide.+-}+{ x = { y = 0 }, x = { y = 0 } }
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall view
@@ -0,0 +1,7 @@+{-  This fails because the expression desugars to:++    { x = 0 ∧ 0 }++    ... which is ill-typed due to ∧ only working on records+-}+{ x = 0, x = 0 }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.( {y : Natural} )
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.( {x : Natural} )
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall view
@@ -0,0 +1,1 @@+{ x = 1 }.{ x, x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall view
@@ -0,0 +1,1 @@+{=}.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall view
@@ -0,0 +1,1 @@+True.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall view
@@ -0,0 +1,1 @@+{=}.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall view
@@ -0,0 +1,1 @@+True.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall view
@@ -0,0 +1,1 @@+Bool.x
+ dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall view
@@ -0,0 +1,1 @@+{ x: Natural, x: Natural }
+ dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall view
@@ -0,0 +1,1 @@+{ x : True }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+True ∧ {=}
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { x = False }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall view
@@ -0,0 +1,1 @@+{=} ∧ True
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall view
@@ -0,0 +1,1 @@+Bool ⩓ {}
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { x : Natural }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall view
@@ -0,0 +1,1 @@+{} ⩓ Bool
+ dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall view
@@ -0,0 +1,1 @@+Optional/build
+ dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall view
@@ -0,0 +1,1 @@+Optional/fold
+ dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+True ⫽ {=}
+ dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall view
@@ -0,0 +1,1 @@+{=} ⫽ True
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyApplied.dhall view
@@ -0,0 +1,1 @@+showConstructor < A : Bool >.A
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyAppliedOptional.dhall view
@@ -0,0 +1,1 @@+showConstructor None
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorWrongArgument.dhall view
@@ -0,0 +1,1 @@+showConstructor 0
+ dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall view
@@ -0,0 +1,1 @@+Some Bool
+ dhall-lang/tests/type-inference/failure/unit/Sort.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall view
@@ -0,0 +1,1 @@+"${1}"
+ dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall view
@@ -0,0 +1,2 @@+-- The mapKey must be Text+toMap {=} : List { mapKey : Bool, mapValue : Text }
+ dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall view
@@ -0,0 +1,1 @@+toMap { x = Bool }
+ dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall view
@@ -0,0 +1,1 @@+1 : Bool
+ dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.y
+ dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall view
@@ -0,0 +1,1 @@+constructors < Left : Natural | Right : Bool >
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall view
@@ -0,0 +1,1 @@+<x | x>
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall view
@@ -0,0 +1,1 @@+<x | x: Natural>
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall view
@@ -0,0 +1,1 @@+< x : True >
+ dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall view
@@ -0,0 +1,1 @@+Some ({=} with x = Bool)
+ dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall view
@@ -0,0 +1,6 @@+{-  The `with` keyword cannot "descend" past a field that is not a record++    In the following example, the `a` field is not a record, therefore there is+    no possibility of adding or overriding `a` with an inner `b` field+-}+{ a = 1 } with a.b = 2
+ dhall-lang/tests/type-inference/failure/unit/WithNotOptional.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } with ? = 1
+ dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall view
@@ -0,0 +1,1 @@+5 with a = 10
+ dhall-lang/tests/type-inference/failure/unit/WithOptionalRecordTypeChanged.dhall view
@@ -0,0 +1,1 @@+(None { x : Natural }) with ?.x = True
+ dhall-lang/tests/type-inference/failure/unit/WithOptionalTypeChanged.dhall view
@@ -0,0 +1,1 @@+(None Natural) with ? = "hello"
+ dhall-lang/tests/type-inference/failure/unit/Z.dhall view
@@ -0,0 +1,4 @@+-- The purpose of this test is to check that an implementation is not parsing a+-- standalone `Z` as a `TimeOffset`.  Instead, this should be treated as an+-- unbound variable named `Z`+Z
+ dhall-lang/tests/type-inference/success/CacheImportsA.dhall view
@@ -0,0 +1,11 @@+{-+	This URL returns (probably) a different result for each request. This test+	ensures that import results for a given URL are correctly cached within an+	execution of dhall.+-}+let _ =+		assert+	  :   https://test.dhall-lang.org/random-string as Text+		≡ https://test.dhall-lang.org/random-string as Text++in  0
+ dhall-lang/tests/type-inference/success/CacheImportsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/CacheImportsCanonicalizeA.dhall view
@@ -0,0 +1,10 @@+{-+	This URL returns (probably) a different result for each request. This test+	ensures that import locations are canonicalized before being cached.+-}+let _ =+		assert+	  :   https://test.dhall-lang.org/random-string as Text+		≡ https://test.dhall-lang.org/foo/../random-string as Text++in  0
+ dhall-lang/tests/type-inference/success/CacheImportsCanonicalizeB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/accessEncodedTypeA.dhall view
@@ -0,0 +1,4 @@+  λ ( record+    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k+    )+→ record Type (λ(x : Type) → λ(y : Type → Type) → x)
+ dhall-lang/tests/type-inference/success/accessEncodedTypeB.dhall view
@@ -0,0 +1,4 @@+  ∀ ( record+    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k+    )+→ Type
+ dhall-lang/tests/type-inference/success/accessTypeA.dhall view
@@ -0,0 +1,1 @@+λ(record : { x : Type, y : Type → Type }) → record.x
+ dhall-lang/tests/type-inference/success/accessTypeB.dhall view
@@ -0,0 +1,1 @@+∀(record : { x : Type, y : Type → Type }) → Type
+ dhall-lang/tests/type-inference/success/preferMixedRecordsA.dhall view
@@ -0,0 +1,1 @@+{ foo = 1 } ⫽ { bar = Text }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsB.dhall view
@@ -0,0 +1,1 @@+{ bar : Type, foo : Natural }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsSameFieldA.dhall view
@@ -0,0 +1,1 @@+{ a = 0 } ⫽ { a = Bool }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsSameFieldB.dhall view
@@ -0,0 +1,1 @@+{ a : Type }
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/0A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/1A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/2B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/3B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall True
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall False
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/2B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/3B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall True
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall False
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Double/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall -3.1
+ dhall-lang/tests/type-inference/success/prelude/Double/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Double/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall 0.4
+ dhall-lang/tests/type-inference/success/prelude/Double/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall -3
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall +0
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall -3
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall +2
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/List/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/all/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/all/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/any/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/any/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ cons "ABC" (cons "DEF" nil)+)
+ dhall-lang/tests/type-inference/success/prelude/List/build/0B.dhall view
@@ -0,0 +1,1 @@+List Text
+ dhall-lang/tests/type-inference/success/prelude/List/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ nil+)
+ dhall-lang/tests/type-inference/success/prelude/List/build/1B.dhall view
@@ -0,0 +1,1 @@+List Text
+ dhall-lang/tests/type-inference/success/prelude/List/concat/0A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [ 0, 1, 2 ]+, [ 3, 4 ]+, [ 5, 6, 7, 8 ]+]
+ dhall-lang/tests/type-inference/success/prelude/List/concat/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concat/1A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [] : List Natural+, [] : List Natural+, [] : List Natural+]
+ dhall-lang/tests/type-inference/success/prelude/List/concat/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/filter/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/filter/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/List/fold.dhall+Natural+[ 2, 3, 5 ]+Natural+(λ(x : Natural) → λ(y : Natural) → x + y)+0
+ dhall-lang/tests/type-inference/success/prelude/List/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/1A.dhall view
@@ -0,0 +1,7 @@+  λ(nil : Natural)+→ ../../../../../../Prelude/List/fold.dhall+  Natural+  [ 2, 3, 5 ]+  Natural+  (λ(x : Natural) → λ(y : Natural) → x + y)+  nil
+ dhall-lang/tests/type-inference/success/prelude/List/fold/1B.dhall view
@@ -0,0 +1,1 @@+∀(nil : Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(list : Type)+→ λ(cons : Natural → list → list)+→ λ(nil : list)+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
+ dhall-lang/tests/type-inference/success/prelude/List/fold/2B.dhall view
@@ -0,0 +1,1 @@+∀(list : Type) → ∀(cons : Natural → list → list) → ∀(nil : list) → list
+ dhall-lang/tests/type-inference/success/prelude/List/generate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
+ dhall-lang/tests/type-inference/success/prelude/List/generate/0B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/generate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
+ dhall-lang/tests/type-inference/success/prelude/List/generate/1B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/head/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/head/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/0B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/1B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/last/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/last/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/length/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/length/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/map/0B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/map/1B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/null/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/null/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/0A.dhall view
@@ -0,0 +1,15 @@+../../../../../../Prelude/List/shifted.dhall+Bool+[ [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = False }+  ]+, [ { index = 0, value = False }+  , { index = 1, value = False }+  ]+, [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = True }+  , { index = 3, value = True }+  ]+]
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/0B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/1B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/unzip.dhall+Text+Bool+[ { _1 = "ABC", _2 = True }+, { _1 = "DEF", _2 = False }+, { _1 = "GHI", _2 = True }+]
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/0B.dhall view
@@ -0,0 +1,1 @@+{ _1 : List Text, _2 : List Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/1B.dhall view
@@ -0,0 +1,1 @@+{ _1 : List Text, _2 : List Bool }
+ dhall-lang/tests/type-inference/success/prelude/Monoid/00A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/and
+ dhall-lang/tests/type-inference/success/prelude/Monoid/00B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/01A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/or
+ dhall-lang/tests/type-inference/success/prelude/Monoid/01B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/02A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/even
+ dhall-lang/tests/type-inference/success/prelude/Monoid/02B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/03A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/odd
+ dhall-lang/tests/type-inference/success/prelude/Monoid/03B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/04A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/List/concat
+ dhall-lang/tests/type-inference/success/prelude/Monoid/04B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xss : List (List a)) → List a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/05A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/List/shifted
+ dhall-lang/tests/type-inference/success/prelude/Monoid/05B.dhall view
@@ -0,0 +1,3 @@+  ∀(a : Type)+→ ∀(kvss : List (List { index : Natural, value : a }))+→ List { index : Natural, value : a }
+ dhall-lang/tests/type-inference/success/prelude/Monoid/06A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Natural/sum
+ dhall-lang/tests/type-inference/success/prelude/Monoid/06B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Monoid/07A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Natural/product
+ dhall-lang/tests/type-inference/success/prelude/Monoid/07B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Monoid/08A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Optional/head
+ dhall-lang/tests/type-inference/success/prelude/Monoid/08B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xs : List (Optional a)) → Optional a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/09A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Optional/last
+ dhall-lang/tests/type-inference/success/prelude/Monoid/09B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xs : List (Optional a)) → Optional a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/10A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Text/concat
+ dhall-lang/tests/type-inference/success/prelude/Monoid/10B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Text) → Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ succ (succ (succ zero))+)
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/1A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ zero+)
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 10
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/1A.dhall view
@@ -0,0 +1,1 @@+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/1B.dhall view
@@ -0,0 +1,1 @@+∀(zero : Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/2B.dhall view
@@ -0,0 +1,1 @@+∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 2
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0B.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1B.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ some 1+)
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ none+)
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/0B.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/1B.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0B.dhall view
@@ -0,0 +1,1 @@+{ _1 : Optional Text, _2 : Optional Bool }
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1B.dhall view
@@ -0,0 +1,1 @@+{ _1 : Optional Text, _2 : Optional Bool }
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/preludeA.dhall view
@@ -0,0 +1,1 @@+../../../Prelude/package.dhall
+ dhall-lang/tests/type-inference/success/preludeB.dhall view
@@ -0,0 +1,740 @@+{ Bool :+    { and : ∀(xs : List Bool) → Bool+    , build :+        ∀(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool+    , equal : ∀(x : Bool) → ∀(y : Bool) → Bool+    , even : ∀(xs : List Bool) → Bool+    , fold :+        ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool+    , not : ∀(b : Bool) → Bool+    , odd : ∀(xs : List Bool) → Bool+    , or : ∀(xs : List Bool) → Bool+    , show : ∀(b : Bool) → Text+    }+, Date : { show : Date → Text }+, Double : { show : Double → Text }+, Function :+    { compose :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(c : Type) →+        ∀(f : a → b) →+        ∀(g : b → c) →+        ∀(x : a) →+          c+    , composeList : ∀(a : Type) → ∀(functions : List (a → a)) → a → a+    , identity : ∀(a : Type) → ∀(x : a) → a+    }+, Integer :+    { abs : ∀(n : Integer) → Natural+    , add : ∀(m : Integer) → ∀(n : Integer) → Integer+    , clamp : Integer → Natural+    , equal : ∀(a : Integer) → ∀(b : Integer) → Bool+    , greaterThan : ∀(x : Integer) → ∀(y : Integer) → Bool+    , greaterThanEqual : ∀(x : Integer) → ∀(y : Integer) → Bool+    , lessThan : ∀(x : Integer) → ∀(y : Integer) → Bool+    , lessThanEqual : ∀(x : Integer) → ∀(y : Integer) → Bool+    , multiply : ∀(m : Integer) → ∀(n : Integer) → Integer+    , negate : Integer → Integer+    , negative : ∀(n : Integer) → Bool+    , nonNegative : ∀(n : Integer) → Bool+    , nonPositive : ∀(n : Integer) → Bool+    , positive : ∀(n : Integer) → Bool+    , show : Integer → Text+    , subtract : ∀(m : Integer) → ∀(n : Integer) → Integer+    , toDouble : Integer → Double+    , toNatural : ∀(n : Integer) → Optional Natural+    }+, JSON :+    { Nesting : Type+    , Tagged : ∀(a : Type) → Type+    , Type : Type+    , array :+        ∀ ( x+          : List+              ( ∀(JSON : Type) →+                ∀ ( json+                  : { array : List JSON → JSON+                    , bool : Bool → JSON+                    , double : Double → JSON+                    , integer : Integer → JSON+                    , null : JSON+                    , object : List { mapKey : Text, mapValue : JSON } → JSON+                    , string : Text → JSON+                    }+                  ) →+                  JSON+              )+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , bool :+        ∀(x : Bool) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , double :+        ∀(x : Double) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , integer :+        ∀(x : Integer) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , keyText :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , keyValue :+        ∀(v : Type) →+        ∀(key : Text) →+        ∀(value : v) →+          { mapKey : Text, mapValue : v }+    , natural :+        ∀(x : Natural) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , null :+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , number :+        ∀(x : Double) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , object :+        ∀ ( x+          : List+              { mapKey : Text+              , mapValue :+                  ∀(JSON : Type) →+                  ∀ ( json+                    : { array : List JSON → JSON+                      , bool : Bool → JSON+                      , double : Double → JSON+                      , integer : Integer → JSON+                      , null : JSON+                      , object : List { mapKey : Text, mapValue : JSON } → JSON+                      , string : Text → JSON+                      }+                    ) →+                    JSON+              }+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , omitNullFields :+        ∀ ( old+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , render :+        ∀ ( json+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , renderCompact :+        ∀ ( j+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , renderInteger : ∀(integer : Integer) → Text+    , renderYAML :+        ∀ ( json+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , string :+        ∀(x : Text) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , tagInline :+        ∀(tagFieldName : Text) →+        ∀(a : Type) →+        ∀(contents : a) →+          { contents : a, field : Text, nesting : < Inline | Nested : Text > }+    , tagNested :+        ∀(contentsFieldName : Text) →+        ∀(tagFieldName : Text) →+        ∀(a : Type) →+        ∀(contents : a) →+          { contents : a, field : Text, nesting : < Inline | Nested : Text > }+    }+, List :+    { all : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → Bool+    , any : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → Bool+    , build :+        ∀(a : Type) →+        (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list) →+          List a+    , concat : ∀(a : Type) → ∀(xss : List (List a)) → List a+    , concatMap :+        ∀(a : Type) → ∀(b : Type) → ∀(f : a → List b) → ∀(xs : List a) → List b+    , default : ∀(a : Type) → ∀(o : Optional (List a)) → List a+    , drop : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → List a+    , empty : ∀(a : Type) → List a+    , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → List a+    , filterMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(xs : List a) →+          List b+    , fold :+        ∀(a : Type) →+        List a →+        ∀(list : Type) →+        ∀(cons : a → list → list) →+        ∀(nil : list) →+          list+    , foldLeft :+        ∀(a : Type) →+        ∀(xs : List a) →+        ∀(list : Type) →+        ∀(cons : list → a → list) →+        ∀(nil : list) →+          list+    , generate : ∀(n : Natural) → ∀(a : Type) → ∀(f : Natural → a) → List a+    , head : ∀(a : Type) → List a → Optional a+    , index : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → Optional a+    , indexed : ∀(a : Type) → List a → List { index : Natural, value : a }+    , iterate : ∀(n : Natural) → ∀(a : Type) → ∀(f : a → a) → ∀(x : a) → List a+    , last : ∀(a : Type) → List a → Optional a+    , length : ∀(a : Type) → List a → Natural+    , map : ∀(a : Type) → ∀(b : Type) → ∀(f : a → b) → ∀(xs : List a) → List b+    , mapMaybe :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(xs : List a) →+          List b+    , mapWithIndex :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : Natural → a → b) →+        ∀(xs : List a) →+          List b+    , null : ∀(a : Type) → ∀(xs : List a) → Bool+    , partition :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : List a) →+          { false : List a, true : List a }+    , replicate : ∀(n : Natural) → ∀(a : Type) → ∀(x : a) → List a+    , reverse : ∀(a : Type) → List a → List a+    , shifted :+        ∀(a : Type) →+        ∀(kvss : List (List { index : Natural, value : a })) →+          List { index : Natural, value : a }+    , take : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → List a+    , unpackOptionals : ∀(a : Type) → ∀(xs : List (Optional a)) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : List { _1 : a, _2 : b }) →+          { _1 : List a, _2 : List b }+    , zip :+        ∀(a : Type) →+        ∀(xs : List a) →+        ∀(b : Type) →+        ∀(ys : List b) →+          List { _1 : a, _2 : b }+    }+, Location : { Type : Type }+, Map :+    { Entry : ∀(k : Type) → ∀(v : Type) → Type+    , Type : ∀(k : Type) → ∀(v : Type) → Type+    , empty : ∀(k : Type) → ∀(v : Type) → List { mapKey : k, mapValue : v }+    , keyText :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , keyValue :+        ∀(v : Type) →+        ∀(key : Text) →+        ∀(value : v) →+          { mapKey : Text, mapValue : v }+    , keys :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : v }) →+          List k+    , map :+        ∀(k : Type) →+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(m : List { mapKey : k, mapValue : a }) →+          List { mapKey : k, mapValue : b }+    , mapMaybe :+        ∀(k : Type) →+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(m : List { mapKey : k, mapValue : a }) →+          List { mapKey : k, mapValue : b }+    , unpackOptionals :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : Optional v }) →+          List { mapKey : k, mapValue : v }+    , values :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : v }) →+          List v+    }+, Monoid : ∀(m : Type) → Type+, Natural :+    { build :+        ( ∀(natural : Type) →+          ∀(succ : natural → natural) →+          ∀(zero : natural) →+            natural+        ) →+          Natural+    , enumerate : ∀(n : Natural) → List Natural+    , equal : ∀(a : Natural) → ∀(b : Natural) → Bool+    , even : Natural → Bool+    , fold :+        Natural →+        ∀(natural : Type) →+        ∀(succ : natural → natural) →+        ∀(zero : natural) →+          natural+    , greaterThan : ∀(x : Natural) → ∀(y : Natural) → Bool+    , greaterThanEqual : ∀(x : Natural) → ∀(y : Natural) → Bool+    , isZero : Natural → Bool+    , lessThan : ∀(x : Natural) → ∀(y : Natural) → Bool+    , lessThanEqual : ∀(x : Natural) → ∀(y : Natural) → Bool+    , listMax : ∀(xs : List Natural) → Optional Natural+    , listMin : ∀(xs : List Natural) → Optional Natural+    , max : ∀(a : Natural) → ∀(b : Natural) → Natural+    , min : ∀(a : Natural) → ∀(b : Natural) → Natural+    , odd : Natural → Bool+    , product : ∀(xs : List Natural) → Natural+    , show : Natural → Text+    , sort : ∀(xs : List Natural) → List Natural+    , subtract : Natural → Natural → Natural+    , sum : ∀(xs : List Natural) → Natural+    , toDouble : ∀(n : Natural) → Double+    , toInteger : Natural → Integer+    }+, NonEmpty :+    { Type : ∀(a : Type) → Type+    , all :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : { head : a, tail : List a }) →+          Bool+    , any :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : { head : a, tail : List a }) →+          Bool+    , concat :+        ∀(a : Type) →+        ∀ ( xss+          : { head : { head : a, tail : List a }+            , tail : List { head : a, tail : List a }+            }+          ) →+          { head : a, tail : List a }+    , concatMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → { head : b, tail : List b }) →+        ∀(xs : { head : a, tail : List a }) →+          { head : b, tail : List b }+    , head : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+    , index :+        ∀(n : Natural) →+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          Optional a+    , indexed :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          { head : { index : Natural, value : a }+          , tail : List { index : Natural, value : a }+          }+    , last : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+    , length : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → Natural+    , make :+        ∀(a : Type) →+        ∀(head : a) →+        ∀(tail : List a) →+          { head : a, tail : List a }+    , map :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(xs : { head : a, tail : List a }) →+          { head : b, tail : List b }+    , reverse :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          { head : a, tail : List a }+    , shifted :+        ∀(a : Type) →+        ∀ ( kvss+          : { head :+                { head : { index : Natural, value : a }+                , tail : List { index : Natural, value : a }+                }+            , tail :+                List+                  { head : { index : Natural, value : a }+                  , tail : List { index : Natural, value : a }+                  }+            }+          ) →+          { head : { index : Natural, value : a }+          , tail : List { index : Natural, value : a }+          }+    , singleton : ∀(a : Type) → ∀(x : a) → { head : a, tail : List a }+    , toList : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }) →+          { _1 : { head : a, tail : List a }, _2 : { head : b, tail : List b } }+    , zip :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+        ∀(b : Type) →+        ∀(ys : { head : b, tail : List b }) →+          { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }+    }+, Operator :+    { `!=` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `#` : ∀(type : Type) → ∀(m : List type) → ∀(n : List type) → List type+    , `&&` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `*` : ∀(m : Natural) → ∀(n : Natural) → Natural+    , `+` : ∀(m : Natural) → ∀(n : Natural) → Natural+    , `++` : ∀(m : Text) → ∀(n : Text) → Text+    , `==` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `||` : ∀(m : Bool) → ∀(n : Bool) → Bool+    }+, Optional :+    { all : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool+    , any : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool+    , build :+        ∀(a : Type) →+        ∀ ( build+          : ∀(optional : Type) →+            ∀(some : a → optional) →+            ∀(none : optional) →+              optional+          ) →+          Optional a+    , concat : ∀(a : Type) → ∀(x : Optional (Optional a)) → Optional a+    , concatMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(o : Optional a) →+          Optional b+    , default : ∀(a : Type) → ∀(default : a) → ∀(o : Optional a) → a+    , equal :+        ∀(a : Type) →+        ∀(compare : a → a → Bool) →+        ∀(ox : Optional a) →+        ∀(oy : Optional a) →+          Bool+    , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Optional a+    , fold :+        ∀(a : Type) →+        ∀(o : Optional a) →+        ∀(optional : Type) →+        ∀(some : a → optional) →+        ∀(none : optional) →+          optional+    , head : ∀(a : Type) → ∀(xs : List (Optional a)) → Optional a+    , last : ∀(a : Type) → ∀(xs : List (Optional a)) → Optional a+    , length : ∀(a : Type) → ∀(xs : Optional a) → Natural+    , map :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(o : Optional a) →+          Optional b+    , null : ∀(a : Type) → ∀(xs : Optional a) → Bool+    , toList : ∀(a : Type) → ∀(o : Optional a) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : Optional { _1 : a, _2 : b }) →+          { _1 : Optional a, _2 : Optional b }+    }+, Text :+    { concat : ∀(xs : List Text) → Text+    , concatMap : ∀(a : Type) → ∀(f : a → Text) → ∀(xs : List a) → Text+    , concatMapSep :+        ∀(separator : Text) →+        ∀(a : Type) →+        ∀(f : a → Text) →+        ∀(elements : List a) →+          Text+    , concatSep : ∀(separator : Text) → ∀(elements : List Text) → Text+    , default : ∀(o : Optional Text) → Text+    , defaultMap : ∀(a : Type) → ∀(f : a → Text) → ∀(o : Optional a) → Text+    , lowerASCII : ∀(nil : Text) → Text+    , replace :+        ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text+    , replicate : ∀(num : Natural) → ∀(text : Text) → Text+    , shell-escape : ∀(xs : Text) → Text+    , show : Text → Text+    , spaces : ∀(a : Natural) → Text+    , upperASCII : ∀(nil : Text) → Text+    }+, Time : { show : Time → Text }+, TimeZone : { show : TimeZone → Text }+, XML :+    { Type : Type+    , attribute :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , element :+        ∀ ( elem+          : { attributes : List { mapKey : Text, mapValue : Text }+            , content :+                List+                  ( ∀(XML : Type) →+                    ∀ ( xml+                      : { element :+                            { attributes :+                                List { mapKey : Text, mapValue : Text }+                            , content : List XML+                            , name : Text+                            } →+                              XML+                        , rawText : Text → XML+                        , text : Text → XML+                        }+                      ) →+                      XML+                  )+            , name : Text+            }+          ) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , emptyAttributes : List { mapKey : Text, mapValue : Text }+    , leaf :+        ∀ ( elem+          : { attributes : List { mapKey : Text, mapValue : Text }+            , name : Text+            }+          ) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , rawText :+        ∀(d : Text) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , render :+        ∀ ( x+          : ∀(XML : Type) →+            ∀ ( xml+              : { element :+                    { attributes : List { mapKey : Text, mapValue : Text }+                    , content : List XML+                    , name : Text+                    } →+                      XML+                , rawText : Text → XML+                , text : Text → XML+                }+              ) →+              XML+          ) →+          Text+    , text :+        ∀(d : Text) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    }+}
+ dhall-lang/tests/type-inference/success/recordOfRecordOfTypesA.dhall view
@@ -0,0 +1,5 @@+let types = { Scopes = < Public | Private > }++let prelude = { types = types }++in  prelude.types.Scopes.Public
+ dhall-lang/tests/type-inference/success/recordOfRecordOfTypesB.dhall view
@@ -0,0 +1,1 @@+< Private | Public >
+ dhall-lang/tests/type-inference/success/recordOfTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Text, y = List }
+ dhall-lang/tests/type-inference/success/recordOfTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type → Type }
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping1A.dhall view
@@ -0,0 +1,1 @@+let T = 0 in λ(T : Type) → λ(x : T) → 1
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping1B.dhall view
@@ -0,0 +1,1 @@+∀(T : Type) → ∀(x : T) → Natural
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping2A.dhall view
@@ -0,0 +1,1 @@+(λ(T : Type) → let x = 0 in λ(x : T) → x) : ∀(T : Type) → ∀(x : T) → T
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping2B.dhall view
@@ -0,0 +1,1 @@+∀(T : Type) → ∀(x : T) → T
+ dhall-lang/tests/type-inference/success/regression/RecursiveRecordTypeMergeTripleCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool } } ⩓ { x : { b : Bool } } ⩓ { x : { c : Bool } }
+ dhall-lang/tests/type-inference/success/regression/RecursiveRecordTypeMergeTripleCollisionB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/regression/TodoA.dhall view
@@ -0,0 +1,1 @@+λ(todo : ∀(a : Type) → a) → todo
+ dhall-lang/tests/type-inference/success/regression/TodoB.dhall view
@@ -0,0 +1,1 @@+∀(todo : ∀(a : Type) → a) → ∀(a : Type) → a
+ dhall-lang/tests/type-inference/success/simple/access/0A.dhall view
@@ -0,0 +1,1 @@+{ x = Text }.x
+ dhall-lang/tests/type-inference/success/simple/access/0B.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/simple/access/1A.dhall view
@@ -0,0 +1,1 @@+< Foo : Text | Bar : Natural >.Foo
+ dhall-lang/tests/type-inference/success/simple/access/1B.dhall view
@@ -0,0 +1,1 @@+∀(Foo : Text) → < Bar : Natural | Foo : Text >
+ dhall-lang/tests/type-inference/success/simple/anonymousFunctionsInTypesA.dhall view
@@ -0,0 +1,5 @@+    let anonymousFunction = λ(a : Type) → List a++in    λ(HigherOrderType : (Type → Type) → Type)+    → λ(x : HigherOrderType anonymousFunction)+    → (x : HigherOrderType anonymousFunction)
+ dhall-lang/tests/type-inference/success/simple/anonymousFunctionsInTypesB.dhall view
@@ -0,0 +1,3 @@+  ∀(HigherOrderType : (Type → Type) → Type)+→ ∀(x : HigherOrderType (λ(a : Type) → List a))+→ HigherOrderType (λ(a : Type) → List a)
+ dhall-lang/tests/type-inference/success/simple/combineMixedRecordsA.dhall view
@@ -0,0 +1,1 @@+{ foo = 1 } ∧ { bar = Text }
+ dhall-lang/tests/type-inference/success/simple/combineMixedRecordsB.dhall view
@@ -0,0 +1,1 @@+{ bar : Type, foo : Natural }
+ dhall-lang/tests/type-inference/success/simple/completionA.dhall view
@@ -0,0 +1,25 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++let ExtraFields = Example ∧ { extra = {=} }++let RequiredFields =+        { Type = { name : Text, id : Optional Natural }+        , default = { id = None Natural }+        }++let WrongDefaultType =+        { Type = { name : Text, id : Optional Natural }+        , default = { id = True }+        }++in  { example0 = Example::{=}+    , example1 = Example::{ name = "John Doe" }+    , example2 = Example::{ id = Some 0 }+    , example3 = Example::{ name = "Mary Jane", id = Some 0 }+    , example4 = ExtraFields::{=}+    , example5 = RequiredFields::{ name = "Jane Smith" }+    , example6 = WrongDefaultType::{ name = "Bob Roberts", id = Some 0 }+    }
+ dhall-lang/tests/type-inference/success/simple/completionB.dhall view
@@ -0,0 +1,8 @@+{ example0 : { id : Optional Natural, name : Text }+, example1 : { id : Optional Natural, name : Text }+, example2 : { id : Optional Natural, name : Text }+, example3 : { id : Optional Natural, name : Text }+, example4 : { id : Optional Natural, name : Text }+, example5 : { id : Optional Natural, name : Text }+, example6 : { id : Optional Natural, name : Text }+}
+ dhall-lang/tests/type-inference/success/simple/complexShadowingA.dhall view
@@ -0,0 +1,6 @@+let x = Bool+let x = Natural+in  \(x: x@1 {- Bool -})+ -> \(x: x@1 {- Natural -})+ -> let x = if x@1 then 0 else 1+    in  (x + x@1) : x@3
+ dhall-lang/tests/type-inference/success/simple/complexShadowingB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → ∀(x : Natural) → Natural
+ dhall-lang/tests/type-inference/success/simple/fieldsAreTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool, y = Text, z = List }
+ dhall-lang/tests/type-inference/success/simple/fieldsAreTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type, z : Type → Type }
+ dhall-lang/tests/type-inference/success/simple/kindParameterA.dhall view
@@ -0,0 +1,1 @@+λ(k : Kind) → λ(a : k → k → Type) → λ(x : k) → a x
+ dhall-lang/tests/type-inference/success/simple/kindParameterB.dhall view
@@ -0,0 +1,1 @@+∀(k : Kind) → ∀(a : k → k → Type) → ∀(x : k) → k → Type
+ dhall-lang/tests/type-inference/success/simple/mergeEquivalenceA.dhall view
@@ -0,0 +1,6 @@+let Foo = < Bar : Natural | Baz : Natural >++in    λ(a : Type)+	→ λ(f : Natural → a)+	→ λ(ts : Foo)+	→ merge { Bar = λ(a : Natural) → f a, Baz = f } ts
+ dhall-lang/tests/type-inference/success/simple/mergeEquivalenceB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(f : Natural → a) → ∀(ts : < Bar : Natural | Baz : Natural >) → a
+ dhall-lang/tests/type-inference/success/simple/mixedFieldAccessA.dhall view
@@ -0,0 +1,9 @@+-- Verify that users can use `.` to both access a record field and a union+-- constructor within the same expression.  This is a common idiom if a user+-- provides a types package.++let Scope = < Public | Private >++let types = { Scope = Scope }++in  types.Scope.Public
+ dhall-lang/tests/type-inference/success/simple/mixedFieldAccessB.dhall view
@@ -0,0 +1,1 @@+< Private | Public >
+ dhall-lang/tests/type-inference/success/simple/orderInsensitivityA.dhall view
@@ -0,0 +1,15 @@+{- This test caught a regression in the Haskell implementation's typechecker.++   The typechecker was not sorting the fields of a record type inferred from a+   projection, meaning that it inferred that the fully normalized type of+   the subexpression `{ bar = "", foo = "" }.{ foo, bar }` was+   `{ foo : Text, bar : Text }` when according to the standard the inferred type+   should have been `{ bar : Text, foo : Text }`.  On top of that the Haskell+   implementation was sensitive to field order, leading to a type mismatch+   when applying a function whose input type had the fields sorted.++   This test ensures that implementations correctly handle order-insensitivity+   when projecting fields and/or comparing types, just in case they are+   order-sensitive like the Haskell implementation.+-}+λ(f : { bar : Text, foo : Text } → Bool) → f { bar = "", foo = "" }.{ foo, bar }
+ dhall-lang/tests/type-inference/success/simple/orderInsensitivityB.dhall view
@@ -0,0 +1,1 @@+∀(f : { bar : Text, foo : Text } → Bool) → Bool
+ dhall-lang/tests/type-inference/success/simple/toMapEmptyNormalizeAnnotationA.dhall view
@@ -0,0 +1,3 @@+toMap+  { x = Bool }.{}+: List { mapKey : { t = Text }.t, mapValue : { t = Double }.t }
+ dhall-lang/tests/type-inference/success/simple/toMapEmptyNormalizeAnnotationB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Double }
+ dhall-lang/tests/type-inference/success/simple/unionsOfTypesA.dhall view
@@ -0,0 +1,1 @@+< Left : Type → Type | Right : Type >.Left List
+ dhall-lang/tests/type-inference/success/simple/unionsOfTypesB.dhall view
@@ -0,0 +1,1 @@+< Left : Type → Type | Right : Type >
+ dhall-lang/tests/type-inference/success/unit/AssertAlphaA.dhall view
@@ -0,0 +1,1 @@+assert : (\(x: Bool) -> x) === (\(y: Bool) -> y)
+ dhall-lang/tests/type-inference/success/unit/AssertAlphaB.dhall view
@@ -0,0 +1,1 @@+(λ(x : Bool) → x) ≡ (λ(y : Bool) → y)
+ dhall-lang/tests/type-inference/success/unit/AssertNaNA.dhall view
@@ -0,0 +1,6 @@+{-+    Equivalence must compare the result of the binary encoding, so in+    particular comparing Doubles should not use standard float equality (where+    NaN != NaN).+-}+assert : NaN === NaN
+ dhall-lang/tests/type-inference/success/unit/AssertNaNB.dhall view
@@ -0,0 +1,1 @@+NaN ≡ NaN
+ dhall-lang/tests/type-inference/success/unit/AssertSimpleA.dhall view
@@ -0,0 +1,1 @@+assert : 1 + 1 === 2
+ dhall-lang/tests/type-inference/success/unit/AssertSimpleB.dhall view
@@ -0,0 +1,1 @@+2 ≡ 2
+ dhall-lang/tests/type-inference/success/unit/AssertTrivialA.dhall view
@@ -0,0 +1,1 @@+assert : 1 === 1
+ dhall-lang/tests/type-inference/success/unit/AssertTrivialB.dhall view
@@ -0,0 +1,1 @@+1 ≡ 1
+ dhall-lang/tests/type-inference/success/unit/BoolA.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/BoolB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/BytesLiteralA.dhall view
@@ -0,0 +1,1 @@+0x"0123456789abcdefABCDEF"
+ dhall-lang/tests/type-inference/success/unit/BytesLiteralB.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/type-inference/success/unit/CompletionA.dhall view
@@ -0,0 +1,1 @@+{ default = {=}, Type = {} }::{=}
+ dhall-lang/tests/type-inference/success/unit/CompletionB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/ConstructorShiftA.dhall view
@@ -0,0 +1,1 @@+λ(t : Type) → < t : t >.t
+ dhall-lang/tests/type-inference/success/unit/ConstructorShiftB.dhall view
@@ -0,0 +1,1 @@+∀(t : Type) → ∀(t : t) → < t : t@1 >
+ dhall-lang/tests/type-inference/success/unit/DoubleA.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/unit/DoubleB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/DoubleLiteralA.dhall view
@@ -0,0 +1,1 @@+1.0
+ dhall-lang/tests/type-inference/success/unit/DoubleLiteralB.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/unit/DoubleShowA.dhall view
@@ -0,0 +1,1 @@+Double/show
+ dhall-lang/tests/type-inference/success/unit/DoubleShowB.dhall view
@@ -0,0 +1,1 @@+Double → Text
+ dhall-lang/tests/type-inference/success/unit/EquivalenceA.dhall view
@@ -0,0 +1,1 @@+1 === 2
+ dhall-lang/tests/type-inference/success/unit/EquivalenceB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FalseA.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/type-inference/success/unit/FalseB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionA.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → _
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationA.dhall view
@@ -0,0 +1,1 @@+(λ(_ : Bool) → _) True
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeArgumentA.dhall view
@@ -0,0 +1,1 @@+List/length (let x = 0 in Bool)
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeArgumentB.dhall view
@@ -0,0 +1,1 @@+List Bool → Natural
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeResultA.dhall view
@@ -0,0 +1,1 @@+(λ(g : Natural → Bool) → assert : g 0 ≡ g 0) Natural/even
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeResultB.dhall view
@@ -0,0 +1,1 @@+True ≡ True
+ dhall-lang/tests/type-inference/success/unit/FunctionB.dhall view
@@ -0,0 +1,1 @@+Bool → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType1A.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType1B.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType2A.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType2B.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionNamedArgA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/type-inference/success/unit/FunctionNamedArgB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionNormalizeTypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+λ(x : { t = Bool }.t) → x
+ dhall-lang/tests/type-inference/success/unit/FunctionNormalizeTypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindKindA.dhall view
@@ -0,0 +1,1 @@+Kind → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTermA.dhall view
@@ -0,0 +1,1 @@+Kind → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTypeA.dhall view
@@ -0,0 +1,1 @@+Kind → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTypeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTermTermA.dhall view
@@ -0,0 +1,1 @@+Bool → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTermTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeKindA.dhall view
@@ -0,0 +1,1 @@+Type → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTermA.dhall view
@@ -0,0 +1,1 @@+Type → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTypeA.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeUsingArgumentA.dhall view
@@ -0,0 +1,1 @@+Type → _
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeUsingArgumentB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IfA.dhall view
@@ -0,0 +1,1 @@+if True then False else True
+ dhall-lang/tests/type-inference/success/unit/IfB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/IfBranchesKindA.dhall view
@@ -0,0 +1,1 @@+if True then (Type -> Type) else Type
+ dhall-lang/tests/type-inference/success/unit/IfBranchesKindB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/IfBranchesTypeA.dhall view
@@ -0,0 +1,1 @@+if True then Bool else Natural
+ dhall-lang/tests/type-inference/success/unit/IfBranchesTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IfNormalizeArgumentsA.dhall view
@@ -0,0 +1,9 @@+      if if True then True else True++then  if True then False else True++else  if True++then  True++else  True
+ dhall-lang/tests/type-inference/success/unit/IfNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/IntegerA.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IntegerClampA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/type-inference/success/unit/IntegerClampB.dhall view
@@ -0,0 +1,1 @@+Integer → Natural
+ dhall-lang/tests/type-inference/success/unit/IntegerLiteralA.dhall view
@@ -0,0 +1,1 @@++1
+ dhall-lang/tests/type-inference/success/unit/IntegerLiteralB.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerNegateA.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/type-inference/success/unit/IntegerNegateB.dhall view
@@ -0,0 +1,1 @@+Integer → Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerShowA.dhall view
@@ -0,0 +1,1 @@+Integer/show
+ dhall-lang/tests/type-inference/success/unit/IntegerShowB.dhall view
@@ -0,0 +1,1 @@+Integer → Text
+ dhall-lang/tests/type-inference/success/unit/IntegerToDoubleA.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble
+ dhall-lang/tests/type-inference/success/unit/IntegerToDoubleB.dhall view
@@ -0,0 +1,1 @@+Integer → Double
+ dhall-lang/tests/type-inference/success/unit/KindA.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/KindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/LetA.dhall view
@@ -0,0 +1,1 @@+let x = True in x
+ dhall-lang/tests/type-inference/success/unit/LetB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetNestedTypeSynonymA.dhall view
@@ -0,0 +1,1 @@+let x = Bool let y : x = True in y
+ dhall-lang/tests/type-inference/success/unit/LetNestedTypeSynonymB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetTypeSynonymA.dhall view
@@ -0,0 +1,1 @@+let x = Bool in True : x
+ dhall-lang/tests/type-inference/success/unit/LetTypeSynonymB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetWithAnnotationA.dhall view
@@ -0,0 +1,1 @@+let x : Bool = True in x
+ dhall-lang/tests/type-inference/success/unit/LetWithAnnotationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/ListA.dhall view
@@ -0,0 +1,1 @@+List
+ dhall-lang/tests/type-inference/success/unit/ListB.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/ListBuildA.dhall view
@@ -0,0 +1,1 @@+List/build
+ dhall-lang/tests/type-inference/success/unit/ListBuildB.dhall view
@@ -0,0 +1,3 @@+  ∀(a : Type)+→ (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list)+→ List a
+ dhall-lang/tests/type-inference/success/unit/ListFoldA.dhall view
@@ -0,0 +1,1 @@+List/fold
+ dhall-lang/tests/type-inference/success/unit/ListFoldB.dhall view
@@ -0,0 +1,6 @@+  ∀(a : Type)+→ List a+→ ∀(list : Type)+→ ∀(cons : a → list → list)+→ ∀(nil : list)+→ list
+ dhall-lang/tests/type-inference/success/unit/ListHeadA.dhall view
@@ -0,0 +1,1 @@+List/head
+ dhall-lang/tests/type-inference/success/unit/ListHeadB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Optional a
+ dhall-lang/tests/type-inference/success/unit/ListIndexedA.dhall view
@@ -0,0 +1,1 @@+List/indexed
+ dhall-lang/tests/type-inference/success/unit/ListIndexedB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → List { index : Natural, value : a }
+ dhall-lang/tests/type-inference/success/unit/ListLastA.dhall view
@@ -0,0 +1,1 @@+List/last
+ dhall-lang/tests/type-inference/success/unit/ListLastB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Optional a
+ dhall-lang/tests/type-inference/success/unit/ListLengthA.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/type-inference/success/unit/ListLengthB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Natural
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyA.dhall view
@@ -0,0 +1,1 @@+[] : List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyNormalizeAnnotationA.dhall view
@@ -0,0 +1,1 @@+[] : { x = List Bool }.x
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyNormalizeAnnotationB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+[ if True then False else True ]
+ dhall-lang/tests/type-inference/success/unit/ListLiteralNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralOneA.dhall view
@@ -0,0 +1,1 @@+[ True ]
+ dhall-lang/tests/type-inference/success/unit/ListLiteralOneB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListReverseA.dhall view
@@ -0,0 +1,1 @@+List/reverse
+ dhall-lang/tests/type-inference/success/unit/ListReverseB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → List a
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyAlternativeA.dhall view
@@ -0,0 +1,1 @@+merge { x = 1 } < x >.x
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyAlternativeB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyUnionA.dhall view
@@ -0,0 +1,1 @@+λ(x : <>) → merge {=} x : Bool
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyUnionB.dhall view
@@ -0,0 +1,1 @@+∀(x : <>) → Bool
+ dhall-lang/tests/type-inference/success/unit/MergeNoneA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (None Bool)
+ dhall-lang/tests/type-inference/success/unit/MergeNoneB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneA.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/success/unit/MergeOneB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneEmptyA.dhall view
@@ -0,0 +1,1 @@+merge { x = 5 } < x >.x
+ dhall-lang/tests/type-inference/success/unit/MergeOneEmptyB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation0A.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Bool >.x True) : Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation1A.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(y : Bool) → y } < x >.x : (∀(y : Bool) → Bool)
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation1B.dhall view
@@ -0,0 +1,1 @@+∀(y : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOptionalA.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Bool) → merge { None = 0, Some = λ(_ : Bool) → 1 } x
+ dhall-lang/tests/type-inference/success/unit/MergeOptionalB.dhall view
@@ -0,0 +1,1 @@+∀(x : Optional Bool) → Natural
+ dhall-lang/tests/type-inference/success/unit/MergeSomeA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (Some True)
+ dhall-lang/tests/type-inference/success/unit/MergeSomeB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeTrickyShadowingA.dhall view
@@ -0,0 +1,1 @@+let _ = Bool in merge {_ = \(x: _) -> x} (<_: Bool>._ True)
+ dhall-lang/tests/type-inference/success/unit/MergeTrickyShadowingB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalA.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/NaturalBuildA.dhall view
@@ -0,0 +1,1 @@+Natural/build
+ dhall-lang/tests/type-inference/success/unit/NaturalBuildB.dhall view
@@ -0,0 +1,6 @@+  (   ∀(natural : Type)+    → ∀(succ : natural → natural)+    → ∀(zero : natural)+    → natural+  )+→ Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalEvenA.dhall view
@@ -0,0 +1,1 @@+Natural/even
+ dhall-lang/tests/type-inference/success/unit/NaturalEvenB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalFoldA.dhall view
@@ -0,0 +1,1 @@+Natural/fold
+ dhall-lang/tests/type-inference/success/unit/NaturalFoldB.dhall view
@@ -0,0 +1,5 @@+  Natural+→ ∀(natural : Type)+→ ∀(succ : natural → natural)+→ ∀(zero : natural)+→ natural
+ dhall-lang/tests/type-inference/success/unit/NaturalIsZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/isZero
+ dhall-lang/tests/type-inference/success/unit/NaturalIsZeroB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalLiteralA.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/type-inference/success/unit/NaturalLiteralB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalOddA.dhall view
@@ -0,0 +1,1 @@+Natural/odd
+ dhall-lang/tests/type-inference/success/unit/NaturalOddB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalShowA.dhall view
@@ -0,0 +1,1 @@+Natural/show
+ dhall-lang/tests/type-inference/success/unit/NaturalShowB.dhall view
@@ -0,0 +1,1 @@+Natural → Text
+ dhall-lang/tests/type-inference/success/unit/NaturalSubtractA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract
+ dhall-lang/tests/type-inference/success/unit/NaturalSubtractB.dhall view
@@ -0,0 +1,1 @@+Natural → Natural → Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalToIntegerA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger
+ dhall-lang/tests/type-inference/success/unit/NaturalToIntegerB.dhall view
@@ -0,0 +1,1 @@+Natural → Integer
+ dhall-lang/tests/type-inference/success/unit/NoneA.dhall view
@@ -0,0 +1,1 @@+None
+ dhall-lang/tests/type-inference/success/unit/NoneB.dhall view
@@ -0,0 +1,1 @@+∀(A : Type) → Optional A
+ dhall-lang/tests/type-inference/success/unit/OperatorAndA.dhall view
@@ -0,0 +1,1 @@+True && False
+ dhall-lang/tests/type-inference/success/unit/OperatorAndB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorAndNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True && False && False
+ dhall-lang/tests/type-inference/success/unit/OperatorAndNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualA.dhall view
@@ -0,0 +1,1 @@+True == False
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True == False == False
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateA.dhall view
@@ -0,0 +1,1 @@+[ True ] # [ True ]
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+(if True then [ True ] else [ False ]) # (if True then [ True ] else [ False ])
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualA.dhall view
@@ -0,0 +1,1 @@+True != False
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True != False != False
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorOrA.dhall view
@@ -0,0 +1,1 @@+True || False
+ dhall-lang/tests/type-inference/success/unit/OperatorOrB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorOrNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True || False || False
+ dhall-lang/tests/type-inference/success/unit/OperatorOrNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusA.dhall view
@@ -0,0 +1,1 @@+1 + 1
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+1 + 1 + (1 + 1)
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateA.dhall view
@@ -0,0 +1,1 @@+"a" ++ "b"
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+"x" ++ "a" ++ ("y" ++ "b")
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesA.dhall view
@@ -0,0 +1,1 @@+1 * 1
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+1 * 1 * (1 * 1)
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OptionalA.dhall view
@@ -0,0 +1,1 @@+Optional
+ dhall-lang/tests/type-inference/success/unit/OptionalB.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/RecordEmptyA.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/type-inference/success/unit/RecordEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x.y.z = 1 }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x : { y : { z : Natural } } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsMergeA.dhall view
@@ -0,0 +1,14 @@+{-  This example verifies that a Dhall interpreter correctly handles a corner+    case that other languages sometimes misbehave on++    The expression should desugar like this:++        λ(r : { z : Natural }) → { x.y = 1, x = r }++        λ(r : { z : Natural }) → { x = { y = 1 }, x = r }++        λ(r : { z : Natural }) → { x = { y = 1 } ∧ r }++    ... which type-checks since `{ y = 1 }` and `r` do not collide+-}+λ(r : { z : Natural }) → { x.y = 1, x = r }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsMergeB.dhall view
@@ -0,0 +1,1 @@+∀(r : { z : Natural }) → { x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsAbstractA.dhall view
@@ -0,0 +1,12 @@+{-  This test illustrates that duplicate fields need not be literals in order+    to be properly normalized.  One or both of the duplicate fields can be+    abstract because field duplication delegates its behavior to the ∧ operator++    This particular example succeeds because it desugars to:++        λ(r : { z : Natural }) → { x = { y = 1 } ∧ r }++    ... and the `∧` operator can infer the absence of conflicts due to knowing+    the type of `r`+-}+λ(r : { z : Natural }) → { x = { y = 1 }, x = r }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsAbstractB.dhall view
@@ -0,0 +1,1 @@+∀(r : { z : Natural }) → { x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsNoCollisionsA.dhall view
@@ -0,0 +1,12 @@+{-  This type-checks because the expression desugars to:++        { x = { y = 0 } ∧ { z = 0 } }++    ... which in turn type-checks due to the absence of a field collision.++    This expression is analogous to the following common Nix/TOML/Cue idiom,+    which we would like to support:++        { x.y = 0, x.z = 0 }+-}+{ x = { y = 0 }, x = { z = 0 } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsNoCollisionsB.dhall view
@@ -0,0 +1,1 @@+{ x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitNormalizeFieldTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = True : { t = Bool }.t }
+ dhall-lang/tests/type-inference/success/unit/RecordLitNormalizeFieldTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> { x }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → { x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunCaptureA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> \(x: Natural) -> { x }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunCaptureB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → ∀(x : Natural) → { x : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunSomeA.dhall view
@@ -0,0 +1,1 @@+let `None` = 0 let `Some` = \(_: Bool) -> 1 in { None, Some }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunSomeB.dhall view
@@ -0,0 +1,1 @@+{ None : Natural, Some : Bool → Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordLitSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b = 1, a = 2 }
+ dhall-lang/tests/type-inference/success/unit/RecordLitSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+{ x = Type, y = {} }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = {=}, y = Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : {}, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Type → Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindLikeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeLikeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Bool → Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeLikeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordOneKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }
+ dhall-lang/tests/type-inference/success/unit/RecordOneKindB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordOneTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = {} }
+ dhall-lang/tests/type-inference/success/unit/RecordOneTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordOneValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }
+ dhall-lang/tests/type-inference/success/unit/RecordOneValueB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeA.dhall view
@@ -0,0 +1,1 @@+let e = { a = 10, b = "Text" } let s = { a : Natural } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+let e = { a = 10, b = "Text" } let s = { } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeJudgmentalEqualityA.dhall view
@@ -0,0 +1,5 @@+-- This tests that we prefer the type from the selector over the inferred field+-- type from the record+-- ie the result should be `{ a : Natural → Natural }`+--                     not `{ a : ∀(x : Natural) → Natural }`+let e = { a = λ(x : Natural) → x } let s = { a : Natural → Natural } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeJudgmentalEqualityB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural → Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }.{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }.{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyKindB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type, y = Type }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionKindB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool, y = Natural }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=}, y = {=} }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionValueB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionKindB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = {} }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionValueB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindA.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a : Kind → Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindLikeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds3A.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds3B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind → Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindLikeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeBoolTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeBoolTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{=} ∧ { x = True }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { y = Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = True } } ∧ { x = { b = True } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool, b : Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = Type } } ∧ { x = { b = Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Kind, b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = Bool } } ∧ { x = { b = Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Type, b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ {=}
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { y = True }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = Type } ∧ { y = Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool } ∧ { y = Natural }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeDeepA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool } } } ⩓ { a : { b : { y : Bool } } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeDeepB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool } } ⩓ { y : { b : Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Kind } } ⩓ { y : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyKindsB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyTypesA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Type } } ⩓ { y : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyTypesB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ {}
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : Kind } ⩓ { y : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x : Type } ⩓ { y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = Bool }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ {=}
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = {=} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoDifferentA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = True }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoDifferentB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = Type } ⫽ { x = Type }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool } ⫽ { x = Natural }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor <A>.A
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalA.dhall view
@@ -0,0 +1,1 @@+showConstructor (Some 0)
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/SomeTrueA.dhall view
@@ -0,0 +1,1 @@+Some True
+ dhall-lang/tests/type-inference/success/unit/SomeTrueB.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/unit/TextA.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/TextLiteralA.dhall view
@@ -0,0 +1,1 @@+"a"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextLiteralNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+"a${if True then "a" else "b"}"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextLiteralWithInterpolationA.dhall view
@@ -0,0 +1,1 @@+"a${"b"}"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralWithInterpolationB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextReplaceA.dhall view
@@ -0,0 +1,1 @@+Text/replace
+ dhall-lang/tests/type-inference/success/unit/TextReplaceB.dhall view
@@ -0,0 +1,1 @@+∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text
+ dhall-lang/tests/type-inference/success/unit/TextShowA.dhall view
@@ -0,0 +1,1 @@+Text/show
+ dhall-lang/tests/type-inference/success/unit/TextShowB.dhall view
@@ -0,0 +1,1 @@+Text → Text
+ dhall-lang/tests/type-inference/success/unit/ToMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/type-inference/success/unit/ToMapAnnotatedA.dhall view
@@ -0,0 +1,1 @@+toMap { foo = 1, bar = 4, baz = 9 } : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapAnnotatedB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapInferTypeFromRecordA.dhall view
@@ -0,0 +1,1 @@+toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
+ dhall-lang/tests/type-inference/success/unit/ToMapInferTypeFromRecordB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
+ dhall-lang/tests/type-inference/success/unit/TrueA.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/type-inference/success/unit/TrueB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeA.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+True : Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionA.dhall view
@@ -0,0 +1,1 @@+(λ(x : Bool) → x) : ∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationNormalizeA.dhall view
@@ -0,0 +1,1 @@+True : { x = Bool }.x
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationNormalizeB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationSortA.dhall view
@@ -0,0 +1,1 @@+Kind : Sort
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationSortB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/TypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorEmptyFieldA.dhall view
@@ -0,0 +1,1 @@+< x | y : Bool >.x
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorEmptyFieldB.dhall view
@@ -0,0 +1,1 @@+< x | y : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorFieldA.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.x
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorFieldB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → < x : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+<>
+ dhall-lang/tests/type-inference/success/unit/UnionTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/UnionTypeKindA.dhall view
@@ -0,0 +1,1 @@+< x : Kind >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds1A.dhall view
@@ -0,0 +1,1 @@+< x : Kind | y : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds1B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+< x : Kind | y : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds3A.dhall view
@@ -0,0 +1,1 @@+< x : Bool | y : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds3B.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds4A.dhall view
@@ -0,0 +1,1 @@+< x : Bool | y | z : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds4B.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionTypeOneA.dhall view
@@ -0,0 +1,1 @@+< x : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeOneB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/UnionTypeTypeA.dhall view
@@ -0,0 +1,1 @@+< x : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/WithCreateIntermediateRecordsA.dhall view
@@ -0,0 +1,3 @@+{- This test illustrates that if an intermediate record does+   not exist, the `with` operator can create one -}+{ a = 5 } with b.c = 10
+ dhall-lang/tests/type-inference/success/unit/WithCreateIntermediateRecordsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : { c : Natural } }
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindA.dhall view
@@ -0,0 +1,1 @@+Some ({ x = Bool } with x = 0)
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindB.dhall view
@@ -0,0 +1,1 @@+Optional { x : Natural }
+ dhall-lang/tests/type-inference/success/unit/WithNestedA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates that the `with` keyword is permitted to override+   existing fields nested within a child record+-}+{ a = { p = 2, q = "hi" }, b = 5.6 } with a.p = True
+ dhall-lang/tests/type-inference/success/unit/WithNestedB.dhall view
@@ -0,0 +1,1 @@+{ a : { p : Bool, q : Text }, b : Double }
+ dhall-lang/tests/type-inference/success/unit/WithNewFieldA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates how the `with` keyword is permitted to extend a record+   with new fields+-}+{ a = 1 } with b = 2
+ dhall-lang/tests/type-inference/success/unit/WithNewFieldB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Natural }
+ dhall-lang/tests/type-inference/success/unit/WithNewTypeA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates that the `with` keyword is permitted to override+   existing fields with a value of a new type (just like the `//` operator)+-}+{ a = 1 } with a = True
+ dhall-lang/tests/type-inference/success/unit/WithNewTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : Bool }
+ dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedA.dhall view
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
+ dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedB.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/unit/time/DateA.dhall view
@@ -0,0 +1,1 @@+Date
+ dhall-lang/tests/type-inference/success/unit/time/DateB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01
+ dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall view
@@ -0,0 +1,1 @@+Date
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall view
@@ -0,0 +1,1 @@+{ date : Date, time : Time }
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+{ date : Date, time : Time, timeZone : TimeZone }
+ dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall view
@@ -0,0 +1,1 @@+Time
+ dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall view
@@ -0,0 +1,1 @@+12:00:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall view
@@ -0,0 +1,1 @@+Time
+ dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@+12:00:00+08:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+{ time : Time, timeZone : TimeZone }
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall view
@@ -0,0 +1,1 @@+TimeZone
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@++08:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+TimeZone
− dhall-repl/Main.hs
@@ -1,249 +0,0 @@-{-# language FlexibleContexts #-}-{-# language NamedFieldPuns #-}-{-# language OverloadedStrings #-}--module Main ( main ) where--import Control.Exception ( SomeException(SomeException), displayException, throwIO )-import Control.Monad.IO.Class ( MonadIO, liftIO )-import Control.Monad.State.Class ( MonadState, get, modify )-import Control.Monad.State.Strict ( evalStateT )-import Data.List ( foldl' )--import qualified Data.Text.Lazy as LazyText-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty ( renderIO )-import qualified Dhall.Context-import qualified Dhall.Core as Dhall ( Var(V), Expr, normalize )-import qualified Dhall.Pretty-import qualified Dhall.Core as Expr ( Expr(..) )-import qualified Dhall.Import as Dhall-import qualified Dhall.Parser as Dhall-import qualified Dhall.TypeCheck as Dhall-import qualified System.Console.ANSI-import qualified System.Console.Haskeline.MonadException as Haskeline-import qualified System.Console.Repline as Repline-import qualified System.IO-import qualified Text.Trifecta.Delta as Trifecta---main :: IO ()-main =-  evalStateT-    ( Repline.evalRepl-        "⊢ "-        ( dontCrash . eval )-        options-        ( Repline.Word completer )-        greeter-    )-    emptyEnv---data Env = Env-  { envBindings :: Dhall.Context.Context Binding-  , envIt :: Maybe Binding-  }---emptyEnv :: Env-emptyEnv =-  Env-    { envBindings = Dhall.Context.empty-    , envIt = Nothing-    }---data Binding = Binding-  { bindingExpr :: Dhall.Expr Dhall.Src Dhall.X-  , bindingType :: Dhall.Expr Dhall.Src Dhall.X-  }---envToContext :: Env -> Dhall.Context.Context Binding-envToContext Env{ envBindings, envIt } =-  case envIt of-    Nothing ->-      envBindings--    Just it ->-      Dhall.Context.insert "it" it envBindings---parseAndLoad-  :: ( MonadIO m, MonadState Env m )-  => String -> m ( Dhall.Expr Dhall.Src Dhall.X )-parseAndLoad src = do-  parsed <--    case Dhall.exprFromText ( Trifecta.Columns 0 0 ) ( LazyText.pack src ) of-      Left e ->-        liftIO ( throwIO e )--      Right a ->-        return a--  liftIO ( Dhall.load parsed )---eval :: ( MonadIO m, MonadState Env m ) => String -> m ()-eval src = do-  loaded <--    parseAndLoad src--  exprType <--    typeCheck loaded--  expr <--    normalize loaded--  modify ( \e -> e { envIt = Just ( Binding expr exprType ) } )--  output System.IO.stdout expr----typeOf :: ( MonadIO m, MonadState Env m ) => [String] -> m ()-typeOf [] =-  liftIO ( putStrLn ":type requires an argument to check the type of" )---typeOf srcs = do-  loaded <--    parseAndLoad ( unwords srcs )--  exprType <--    typeCheck loaded--  exprType' <--    normalize exprType--  output System.IO.stdout ( Expr.Annot loaded exprType' )----normalize-  :: MonadState Env m-  => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr t Dhall.X )-normalize e = do-  env <--    get--  return-    ( Dhall.normalize-        ( foldl'-            ( \a (k, Binding { bindingType, bindingExpr }) ->-                Expr.Let k ( Just bindingType ) bindingExpr a-            )-            e-            ( Dhall.Context.toList ( envToContext env ) )-        )-    )---typeCheck-  :: ( MonadIO m, MonadState Env m )-  => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr Dhall.Src Dhall.X )-typeCheck expr = do-  env <--    get--  case Dhall.typeWith ( bindingType <$> envToContext env ) expr of-    Left e ->-      liftIO ( throwIO e )--    Right a ->-      return a---addBinding :: ( MonadIO m, MonadState Env m ) => [String] -> m ()-addBinding (k : "=" : srcs) = do-  let-    varName =-      LazyText.pack k--  loaded <--    parseAndLoad ( unwords srcs )--  t <--    typeCheck loaded--  expr <--    normalize loaded--  modify-    ( \e ->-        e-          { envBindings =-              Dhall.Context.insert-                varName-                Binding { bindingType = t, bindingExpr = expr }-                ( envBindings e )-          }-    )--  output-    System.IO.stdout-    ( Expr.Annot ( Expr.Var ( Dhall.V varName 0 ) ) t )--addBinding _ =-  liftIO ( fail ":let should be of the form `:let x = y`" )--saveBinding :: ( MonadIO m, MonadState Env m ) => [String] -> m ()-saveBinding (file : "=" : tokens) = do-  loadedExpression <- parseAndLoad (unwords tokens)--  _ <- typeCheck loadedExpression--  normalizedExpression <- normalize loadedExpression--  let handler handle = output handle normalizedExpression--  liftIO (System.IO.withFile file System.IO.WriteMode handler)-saveBinding _ = fail ":save should be of the form `:save x = y`"---options-  :: ( Haskeline.MonadException m, MonadIO m, MonadState Env m )-  => Repline.Options m-options =-  [ ( "type", dontCrash . typeOf )-  , ( "let", dontCrash . addBinding )-  , ( "save", dontCrash . saveBinding )-  ]---completer :: Monad m => Repline.WordCompleter m-completer _ =-  return []---greeter :: MonadIO m => m ()-greeter =-  return ()---dontCrash :: ( MonadIO m, Haskeline.MonadException m ) => m () -> m ()-dontCrash m =-  Haskeline.catch-    m-    ( \ e@SomeException{} -> liftIO ( putStrLn ( displayException e ) ) )---output-    :: (Pretty.Pretty a, MonadIO m)-    => System.IO.Handle -> Dhall.Expr s a -> m ()-output handle expr = do-  let opts =-          Pretty.defaultLayoutOptions-              { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }--  let stream = Pretty.layoutSmart opts (Dhall.Pretty.prettyExpr expr)-  supportsANSI <- liftIO (System.Console.ANSI.hSupportsANSI handle)-  let ansiStream =-          if supportsANSI-          then fmap Dhall.Pretty.annToAnsiStyle stream-          else Pretty.unAnnotateS stream--  liftIO (Pretty.renderIO handle ansiStream)--  liftIO (putStrLn "") -- Pretty printing doesn't end with a new line
dhall.cabal view
@@ -1,13 +1,12 @@+Cabal-Version: 2.4 Name: dhall-Version: 1.11.1-Cabal-Version: >=1.8.0.2+Version: 1.42.3 Build-Type: Simple-Tested-With: GHC == 8.0.1-License: BSD3+License: BSD-3-Clause License-File: LICENSE-Copyright: 2017 Gabriel Gonzalez-Author: Gabriel Gonzalez-Maintainer: Gabriel439@gmail.com+Copyright: 2017 Gabriella Gonzalez+Author: Gabriella Gonzalez+Maintainer: GenuineGabriella@gmail.com Bug-Reports: https://github.com/dhall-lang/dhall-haskell/issues Synopsis: A configuration language guaranteed to terminate Description:@@ -22,256 +21,477 @@     .     Read "Dhall.Tutorial" to learn how to use this library Category: Compiler+Data-Files:+    man/dhall.1 Extra-Source-Files:     CHANGELOG.md-    Prelude/Bool/and-    Prelude/Bool/build-    Prelude/Bool/even-    Prelude/Bool/fold-    Prelude/Bool/not-    Prelude/Bool/odd-    Prelude/Bool/or-    Prelude/Bool/show-    Prelude/Double/show-    Prelude/Integer/show-    Prelude/List/all-    Prelude/List/any-    Prelude/List/build-    Prelude/List/concat-    Prelude/List/concatMap-    Prelude/List/filter-    Prelude/List/fold-    Prelude/List/generate-    Prelude/List/head-    Prelude/List/indexed-    Prelude/List/iterate-    Prelude/List/last-    Prelude/List/length-    Prelude/List/map-    Prelude/List/null-    Prelude/List/replicate-    Prelude/List/reverse-    Prelude/List/shifted-    Prelude/List/unzip-    Prelude/Monoid-    Prelude/Natural/build-    Prelude/Natural/enumerate-    Prelude/Natural/even-    Prelude/Natural/fold-    Prelude/Natural/isZero-    Prelude/Natural/odd-    Prelude/Natural/product-    Prelude/Natural/show-    Prelude/Natural/sum-    Prelude/Natural/toInteger-    Prelude/Optional/all-    Prelude/Optional/any-    Prelude/Optional/build-    Prelude/Optional/concat-    Prelude/Optional/filter-    Prelude/Optional/fold-    Prelude/Optional/head-    Prelude/Optional/last-    Prelude/Optional/length-    Prelude/Optional/map-    Prelude/Optional/null-    Prelude/Optional/toList-    Prelude/Optional/unzip-    Prelude/Text/concat-    Prelude/Text/concatMap-    Prelude/Text/concatMapSep-    Prelude/Text/concatSep-    tests/format/*.dhall-    tests/normalization/*.dhall-    tests/normalization/examples/Bool/and/*.dhall-    tests/normalization/examples/Bool/build/*.dhall-    tests/normalization/examples/Bool/even/*.dhall-    tests/normalization/examples/Bool/fold/*.dhall-    tests/normalization/examples/Bool/not/*.dhall-    tests/normalization/examples/Bool/odd/*.dhall-    tests/normalization/examples/Bool/or/*.dhall-    tests/normalization/examples/Bool/show/*.dhall-    tests/normalization/examples/Double/show/*.dhall-    tests/normalization/examples/Integer/show/*.dhall-    tests/normalization/examples/List/all/*.dhall-    tests/normalization/examples/List/any/*.dhall-    tests/normalization/examples/List/build/*.dhall-    tests/normalization/examples/List/concat/*.dhall-    tests/normalization/examples/List/concatMap/*.dhall-    tests/normalization/examples/List/filter/*.dhall-    tests/normalization/examples/List/fold/*.dhall-    tests/normalization/examples/List/generate/*.dhall-    tests/normalization/examples/List/head/*.dhall-    tests/normalization/examples/List/indexed/*.dhall-    tests/normalization/examples/List/iterate/*.dhall-    tests/normalization/examples/List/last/*.dhall-    tests/normalization/examples/List/length/*.dhall-    tests/normalization/examples/List/map/*.dhall-    tests/normalization/examples/List/null/*.dhall-    tests/normalization/examples/List/replicate/*.dhall-    tests/normalization/examples/List/reverse/*.dhall-    tests/normalization/examples/List/shifted/*.dhall-    tests/normalization/examples/List/unzip/*.dhall-    tests/normalization/examples/Natural/build/*.dhall-    tests/normalization/examples/Natural/enumerate/*.dhall-    tests/normalization/examples/Natural/even/*.dhall-    tests/normalization/examples/Natural/fold/*.dhall-    tests/normalization/examples/Natural/isZero/*.dhall-    tests/normalization/examples/Natural/odd/*.dhall-    tests/normalization/examples/Natural/product/*.dhall-    tests/normalization/examples/Natural/show/*.dhall-    tests/normalization/examples/Natural/sum/*.dhall-    tests/normalization/examples/Natural/toInteger/*.dhall-    tests/normalization/examples/Optional/all/*.dhall-    tests/normalization/examples/Optional/any/*.dhall-    tests/normalization/examples/Optional/build/*.dhall-    tests/normalization/examples/Optional/concat/*.dhall-    tests/normalization/examples/Optional/filter/*.dhall-    tests/normalization/examples/Optional/fold/*.dhall-    tests/normalization/examples/Optional/head/*.dhall-    tests/normalization/examples/Optional/last/*.dhall-    tests/normalization/examples/Optional/length/*.dhall-    tests/normalization/examples/Optional/map/*.dhall-    tests/normalization/examples/Optional/null/*.dhall-    tests/normalization/examples/Optional/toList/*.dhall-    tests/normalization/examples/Optional/unzip/*.dhall-    tests/normalization/examples/Text/concat/*.dhall-    tests/normalization/examples/Text/concatMap/*.dhall-    tests/normalization/examples/Text/concatMapSep/*.dhall-    tests/normalization/examples/Text/concatSep/*.dhall-    tests/normalization/simplifications/*.dhall-    tests/parser/*.dhall-    tests/regression/*.dhall-    tests/tutorial/*.dhall-    tests/typecheck/*.dhall-    tests/typecheck/examples/Monoid/*.dhall+    benchmark/**/*.dhall+    benchmark/**/*.dhallb+    dhall-lang/Prelude/**/*.dhall+    dhall-lang/Prelude/Bool/and+    dhall-lang/Prelude/Bool/build+    dhall-lang/Prelude/Bool/even+    dhall-lang/Prelude/Bool/fold+    dhall-lang/Prelude/Bool/not+    dhall-lang/Prelude/Bool/odd+    dhall-lang/Prelude/Bool/or+    dhall-lang/Prelude/Bool/show+    dhall-lang/Prelude/Double/show+    dhall-lang/Prelude/Function/compose+    dhall-lang/Prelude/Function/identity+    dhall-lang/Prelude/Integer/abs+    dhall-lang/Prelude/Integer/add+    dhall-lang/Prelude/Integer/clamp+    dhall-lang/Prelude/Integer/equal+    dhall-lang/Prelude/Integer/greaterThan+    dhall-lang/Prelude/Integer/greaterThanEqual+    dhall-lang/Prelude/Integer/lessThan+    dhall-lang/Prelude/Integer/lessThanEqual+    dhall-lang/Prelude/Integer/multiply+    dhall-lang/Prelude/Integer/negate+    dhall-lang/Prelude/Integer/negative+    dhall-lang/Prelude/Integer/nonNegative+    dhall-lang/Prelude/Integer/nonPositive+    dhall-lang/Prelude/Integer/positive+    dhall-lang/Prelude/Integer/show+    dhall-lang/Prelude/Integer/subtract+    dhall-lang/Prelude/Integer/toDouble+    dhall-lang/Prelude/Integer/toNatural+    dhall-lang/Prelude/JSON/Format+    dhall-lang/Prelude/JSON/Nesting+    dhall-lang/Prelude/JSON/Tagged+    dhall-lang/Prelude/JSON/Type+    dhall-lang/Prelude/JSON/array+    dhall-lang/Prelude/JSON/bool+    dhall-lang/Prelude/JSON/double+    dhall-lang/Prelude/JSON/integer+    dhall-lang/Prelude/JSON/keyText+    dhall-lang/Prelude/JSON/keyValue+    dhall-lang/Prelude/JSON/natural+    dhall-lang/Prelude/JSON/null+    dhall-lang/Prelude/JSON/number+    dhall-lang/Prelude/JSON/object+    dhall-lang/Prelude/JSON/omitNullFields+    dhall-lang/Prelude/JSON/render+    dhall-lang/Prelude/JSON/renderAs+    dhall-lang/Prelude/JSON/renderYAML+    dhall-lang/Prelude/JSON/string+    dhall-lang/Prelude/JSON/tagInline+    dhall-lang/Prelude/JSON/tagNested+    dhall-lang/Prelude/List/all+    dhall-lang/Prelude/List/any+    dhall-lang/Prelude/List/build+    dhall-lang/Prelude/List/concat+    dhall-lang/Prelude/List/concatMap+    dhall-lang/Prelude/List/default+    dhall-lang/Prelude/List/drop+    dhall-lang/Prelude/List/empty+    dhall-lang/Prelude/List/filter+    dhall-lang/Prelude/List/fold+    dhall-lang/Prelude/List/generate+    dhall-lang/Prelude/List/head+    dhall-lang/Prelude/List/index+    dhall-lang/Prelude/List/indexed+    dhall-lang/Prelude/List/iterate+    dhall-lang/Prelude/List/last+    dhall-lang/Prelude/List/length+    dhall-lang/Prelude/List/map+    dhall-lang/Prelude/List/null+    dhall-lang/Prelude/List/partition+    dhall-lang/Prelude/List/replicate+    dhall-lang/Prelude/List/reverse+    dhall-lang/Prelude/List/shifted+    dhall-lang/Prelude/List/take+    dhall-lang/Prelude/List/unpackOptionals+    dhall-lang/Prelude/List/unzip+    dhall-lang/Prelude/List/zip+    dhall-lang/Prelude/Location/Type+    dhall-lang/Prelude/Map/Entry+    dhall-lang/Prelude/Map/Type+    dhall-lang/Prelude/Map/empty+    dhall-lang/Prelude/Map/keyText+    dhall-lang/Prelude/Map/keyValue+    dhall-lang/Prelude/Map/keys+    dhall-lang/Prelude/Map/map+    dhall-lang/Prelude/Map/values+    dhall-lang/Prelude/Monoid+    dhall-lang/Prelude/Natural/build+    dhall-lang/Prelude/Natural/enumerate+    dhall-lang/Prelude/Natural/equal+    dhall-lang/Prelude/Natural/even+    dhall-lang/Prelude/Natural/fold+    dhall-lang/Prelude/Natural/greaterThan+    dhall-lang/Prelude/Natural/greaterThanEqual+    dhall-lang/Prelude/Natural/isZero+    dhall-lang/Prelude/Natural/lessThan+    dhall-lang/Prelude/Natural/lessThanEqual+    dhall-lang/Prelude/Natural/listMax+    dhall-lang/Prelude/Natural/listMin+    dhall-lang/Prelude/Natural/max+    dhall-lang/Prelude/Natural/min+    dhall-lang/Prelude/Natural/odd+    dhall-lang/Prelude/Natural/product+    dhall-lang/Prelude/Natural/show+    dhall-lang/Prelude/Natural/sort+    dhall-lang/Prelude/Natural/subtract+    dhall-lang/Prelude/Natural/sum+    dhall-lang/Prelude/Natural/toDouble+    dhall-lang/Prelude/Natural/toInteger+    dhall-lang/Prelude/Optional/all+    dhall-lang/Prelude/Optional/any+    dhall-lang/Prelude/Optional/build+    dhall-lang/Prelude/Optional/concat+    dhall-lang/Prelude/Optional/default+    dhall-lang/Prelude/Optional/filter+    dhall-lang/Prelude/Optional/fold+    dhall-lang/Prelude/Optional/head+    dhall-lang/Prelude/Optional/last+    dhall-lang/Prelude/Optional/length+    dhall-lang/Prelude/Optional/map+    dhall-lang/Prelude/Optional/null+    dhall-lang/Prelude/Optional/toList+    dhall-lang/Prelude/Optional/unzip+    dhall-lang/Prelude/Text/concat+    dhall-lang/Prelude/Text/concatMap+    dhall-lang/Prelude/Text/concatMapSep+    dhall-lang/Prelude/Text/concatSep+    dhall-lang/Prelude/Text/default+    dhall-lang/Prelude/Text/defaultMap+    dhall-lang/Prelude/Text/replicate+    dhall-lang/Prelude/Text/show+    dhall-lang/Prelude/Text/spaces+    dhall-lang/Prelude/XML/Type+    dhall-lang/Prelude/XML/attribute+    dhall-lang/Prelude/XML/element+    dhall-lang/Prelude/XML/emptyAttributes+    dhall-lang/Prelude/XML/leaf+    dhall-lang/Prelude/XML/render+    dhall-lang/Prelude/XML/text+    dhall-lang/tests/**/*.dhall+    dhall-lang/tests/**/*.dhallb+    dhall-lang/tests/**/*.hash+    dhall-lang/tests/**/*.txt+    dhall-lang/tests/**/*.bin+    dhall-lang/tests/import/cache/dhall/12203871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+    dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21+    tests/**/*.dhall+    tests/**/*.tags+    tests/**/*.txt  Source-Repository head     Type: git-    Location: https://github.com/dhall-lang/dhall-haskell+    Location: https://github.com/dhall-lang/dhall-haskell/tree/master/dhall -Library-    Hs-Source-Dirs: src+Flag with-http+  Description: Include support for importing dhall modules from HTTP URLs+  Default:     True+  Manual:      True++Flag use-http-client-tls+  Description: Use http-client-tls for resolving HTTP imports by default+               (requires with-http to be enabled)+  Default:     True+  Manual:      True++Flag cross+  Description: Disable TemplateHaskell to make cross-compiling easier+  Default:     False+  Manual:      True++Flag network-tests+  Description: Enable tests which depend on an internet connection+  Default:     True+  Manual:      True++Common common     Build-Depends:-        base                        >= 4.9.0.0  && < 5   ,-        ansi-wl-pprint                           < 0.7 ,-        base16-bytestring                        < 0.2 ,-        bytestring                               < 0.11,-        case-insensitive                         < 1.3 ,-        containers                  >= 0.5.0.0  && < 0.6 ,-        contravariant                            < 1.5 ,-        cryptonite                  >= 0.23     && < 1.0 ,+        base                        >= 4.11.0.0 && < 5   ,+        aeson                       >= 1.0.0.0  && < 2.3 ,+        aeson-pretty                               < 0.9 ,+        ansi-terminal               >= 0.6.3.1  && < 1.2 ,+        atomic-write                >= 0.2.0.7  && < 0.3 ,+        base16-bytestring           >= 1.0.0.0           ,+        bytestring                                 < 0.13,+        case-insensitive                           < 1.3 ,+        cborg                       >= 0.2.0.0  && < 0.3 ,+        cborg-json                  >= 0.2.2.0  && < 0.3 ,+        containers                  >= 0.5.8.0  && < 0.9 ,+        contravariant                              < 1.6 ,+        data-fix                                   < 0.4 ,+        deepseq                                    < 1.6 ,+        Diff                        >= 0.2      && < 1.1 ,+        directory                   >= 1.3.0.0  && < 1.4 ,+        dotgen                      >= 0.4.2    && < 0.5 ,+        either                      >= 5        && < 5.1,         exceptions                  >= 0.8.3    && < 0.11,-        directory                   >= 1.3      && < 1.4 ,-        filepath                    >= 1.4      && < 1.5 ,-        http-client                 >= 0.4.30   && < 0.6 ,-        http-client-tls             >= 0.2.0    && < 0.4 ,-        insert-ordered-containers   >= 0.1.0.1  && < 0.3 ,-        lens-family-core            >= 1.0.0    && < 1.3 ,-        memory                      >= 0.14     && < 0.15,+        filepath                    >= 1.4      && < 1.6 ,+        half                        >= 0.2.2.3  && < 0.4 ,+        haskeline                   >= 0.7.2.1  && < 0.9 ,+        hashable                    >= 1.2      && < 1.6 ,+        indexed-traversable                        < 0.2 ,+        microlens                   >= 0.4.14.0 && < 0.5 ,+        microlens-mtl               >= 0.1      && < 0.3 ,+        -- megaparsec follows SemVer: https://github.com/mrkkrp/megaparsec/issues/469#issuecomment-927918469+        megaparsec                  >= 8        && < 10  ,+        mmorph                                     < 1.3 ,+        mtl                         >= 2.2.1    && < 2.4 ,+        network-uri                 >= 2.6      && < 2.7 ,+        optparse-applicative        >= 0.14.0.0 && < 0.20,         parsers                     >= 0.12.4   && < 0.13,-        prettyprinter               >= 1.2.0.1  && < 1.3 ,-        prettyprinter-ansi-terminal >= 1.1.1    && < 1.2 ,+        parser-combinators                               ,+        prettyprinter               >= 1.7.0    && < 1.8 ,+        prettyprinter-ansi-terminal >= 1.1.2    && < 1.2 ,+        pretty-simple                              < 4.2 ,+        repline                     >= 0.4.0.0  && < 0.5 ,+        serialise                   >= 0.2.0.0  && < 0.3 ,         scientific                  >= 0.3.0.0  && < 0.4 ,-        text                        >= 0.11.1.0 && < 1.3 ,-        text-format                              < 0.4 ,-        transformers                >= 0.2.0.0  && < 0.6 ,-        trifecta                    >= 1.6      && < 1.8 ,+        template-haskell            >= 2.13.0.0 && < 2.24,+        text                        >= 0.11.1.0 && < 2.2 ,+        text-manipulate             >= 0.2.0.1  && < 0.4 ,+        text-short                  >= 0.1      && < 0.2 ,+        th-lift-instances           >= 0.1.13   && < 0.2 ,+        time                        >= 1.9      && < 1.15,+        transformers                >= 0.5.2.0  && < 0.7 ,+        unix-compat                 >= 0.4.2    && < 0.8 ,         unordered-containers        >= 0.1.3.0  && < 0.3 ,-        vector                      >= 0.11.0.0 && < 0.13+        vector                      >= 0.11.0.0 && < 0.14++    if !os(windows)+      Build-Depends:+        unix                        >= 2.7      && < 2.9 ,++    if flag(with-http)+      CPP-Options:+        -DWITH_HTTP+      if flag(use-http-client-tls)+        CPP-Options:+          -DUSE_HTTP_CLIENT_TLS+      if flag(network-tests)+        CPP-Options:+          -DNETWORK_TESTS+    if flag(cross)+      CPP-Options: -DCROSS++    GHC-Options: -Wall -Wcompat -Wincomplete-uni-patterns -optP-Wno-unicode-homoglyph++Library+    Import: common+    Hs-Source-Dirs: src+    if impl(ghcjs)+      Hs-Source-Dirs: ghcjs-src+      Build-Depends:+        ghcjs-base ,+        ghcjs-xhr+    else+      Hs-Source-Dirs: ghc-src+      Build-Depends:+        cryptohash-sha256+      if flag(with-http)+        Build-Depends:+          http-types                  >= 0.7.0    && < 0.13,+          http-client                 >= 0.5.0    && < 0.8+        if flag(use-http-client-tls)+          Build-Depends:+            http-client-tls           >= 0.2.0    && < 0.4++    Other-Extensions:+        BangPatterns+        CPP+        DefaultSignatures+        DeriveAnyClass+        DeriveDataTypeable+        DeriveFunctor+        DeriveGeneric+        DeriveTraversable+        FlexibleContexts+        FlexibleInstances+        GeneralizedNewtypeDeriving+        MultiParamTypeClasses+        NamedFieldPuns+        OverloadedLists+        OverloadedStrings+        RankNTypes+        RecordWildCards+        ScopedTypeVariables+        StandaloneDeriving+        TupleSections+        TypeFamilies+        TypeOperators+        UnicodeSyntax+    if !flag(cross)+        Other-Extensions:+            TemplateHaskell+     Exposed-Modules:-        Dhall,-        Dhall.Context,-        Dhall.Core,-        Dhall.Import,-        Dhall.Parser,-        Dhall.Pretty,-        Dhall.Tutorial,+        Dhall+        Dhall.Binary+        Dhall.Context+        Dhall.Core+        Dhall.Crypto+        Dhall.Diff+        Dhall.DirectoryTree+        Dhall.Format+        Dhall.Freeze+        Dhall.Import+        Dhall.Lint+        Dhall.Main+        Dhall.Marshal.Decode+        Dhall.Marshal.Encode+        Dhall.Map+        Dhall.Optics+        Dhall.Package+        Dhall.Parser+        Dhall.Parser.Expression+        Dhall.Parser.Token+        Dhall.Pretty+        Dhall.Repl+        Dhall.Schemas+        Dhall.Set+        Dhall.Src+        Dhall.Substitution+        Dhall.Tags+        Dhall.Tutorial         Dhall.TypeCheck+        Dhall.Util+        Dhall.Version+    if !flag(cross)+        Exposed-Modules:+            Dhall.TH+    if impl(ghc >= 8.6.1)+        Exposed-Modules:+          Dhall.Deriving     Other-Modules:+        Dhall.DirectoryTree.Types+        Dhall.Eval+        Dhall.Import.Types+        Dhall.Import.Headers+        Dhall.Marshal.Internal+        Dhall.Normalize+        Dhall.Parser.Combinators         Dhall.Pretty.Internal-    GHC-Options: -Wall+        Dhall.Syntax+        Dhall.Syntax.Binding+        Dhall.Syntax.Chunks+        Dhall.Syntax.Const+        Dhall.Syntax.Expr+        Dhall.Syntax.FunctionBinding+        Dhall.Syntax.Import+        Dhall.Syntax.Instances.Applicative+        Dhall.Syntax.Instances.Bifunctor+        Dhall.Syntax.Instances.Data+        Dhall.Syntax.Instances.Eq+        Dhall.Syntax.Instances.Foldable+        Dhall.Syntax.Instances.Functor+        Dhall.Syntax.Instances.Lift+        Dhall.Syntax.Instances.Monad+        Dhall.Syntax.Instances.NFData+        Dhall.Syntax.Instances.Ord+        Dhall.Syntax.Instances.Pretty+        Dhall.Syntax.Instances.Show+        Dhall.Syntax.Instances.Traversable+        Dhall.Syntax.MultiLet+        Dhall.Syntax.Operations+        Dhall.Syntax.RecordField+        Dhall.Syntax.Types+        Dhall.Syntax.Var+        Dhall.URL+        Paths_dhall+    Autogen-Modules:+        Paths_dhall+    if flag(with-http)+      Other-Modules:+        Dhall.Import.HTTP+        Dhall.Import.Manager +    Default-Language: Haskell2010+ Executable dhall+    Import: common     Hs-Source-Dirs: dhall     Main-Is: Main.hs-    Build-Depends:-        ansi-terminal               >= 0.6.3.1  && < 0.9 ,-        base                        >= 4        && < 5   ,-        dhall                                            ,-        optparse-generic            >= 1.1.1    && < 1.4 ,-        prettyprinter                                    ,-        prettyprinter-ansi-terminal >= 1.1.1    && < 1.2 ,-        trifecta                    >= 1.6      && < 1.8 ,-        text                        >= 0.11.1.0 && < 1.3-    GHC-Options: -Wall-    Other-Modules:-        Paths_dhall+    Build-Depends: dhall+    GHC-Options: -rtsopts+    Default-Language: Haskell2010 -Executable dhall-repl-    Hs-Source-Dirs: dhall-repl-    Main-Is: Main.hs+Test-Suite tasty+    Import: common+    Type: exitcode-stdio-1.0+    Hs-Source-Dirs: tests+    Main-Is: Dhall/Test/Main.hs+    Other-Modules:+        Dhall.Test.Dhall+        Dhall.Test.Diff+        Dhall.Test.DirectoryTree+        Dhall.Test.Tags+        Dhall.Test.Format+        Dhall.Test.Freeze+        Dhall.Test.Import+        Dhall.Test.Lint+        Dhall.Test.Normalization+        Dhall.Test.Package+        Dhall.Test.Parser+        Dhall.Test.QuickCheck+        Dhall.Test.Regression+        Dhall.Test.Schemas+        Dhall.Test.SemanticHash+        Dhall.Test.Substitution+        Dhall.Test.Tutorial+        Dhall.Test.TypeInference+        Dhall.Test.Util+    if !flag(cross)+        Other-Modules:+            Dhall.Test.TH     Build-Depends:-        base             >= 4        && < 5   ,-        ansi-terminal                         ,-        dhall                                 ,-        haskeline        >= 0.7.3.0  && < 0.8 ,-        mtl              >= 2.2.1    && < 2.3 ,-        repline          >= 0.1.6.0  && < 0.2 ,-        prettyprinter                         ,-        prettyprinter-ansi-terminal           ,-        text                                  ,-        trifecta-    GHC-Options: -Wall+        dhall                                          ,+        foldl                                    < 1.5 ,+        generic-random            >= 1.3.0.0  && < 1.6 ,+        http-client                                    ,+        http-client-tls                                ,+        QuickCheck                >= 2.14     && < 2.17,+        quickcheck-instances      >= 0.3.12   && < 0.4 ,+        special-values                           < 0.2 ,+        spoon                                    < 0.4 ,+        tasty                     >= 0.11.2   && < 1.6 ,+        tasty-expected-failure                   < 0.13,+        tasty-hunit               >= 0.10     && < 0.11,+        tasty-quickcheck          >= 0.9.2    && < 0.12,+        tasty-silver                             < 3.4 ,+        temporary                 >= 1.2.1    && < 1.4 ,+        turtle                    >= 1.6      && < 1.7 ,+    Default-Language: Haskell2010 -Executable dhall-format-    Hs-Source-Dirs: dhall-format+Test-Suite doctest+    Import: common+    Type: exitcode-stdio-1.0+    Hs-Source-Dirs: doctest     Main-Is: Main.hs     Build-Depends:-        base                        >= 4        && < 5   ,-        ansi-terminal               >= 0.6.3.1  && < 0.9 ,-        dhall                                ,-        optparse-generic            >= 1.1.1    && < 1.4 ,-        prettyprinter               >= 1.2.0.1  && < 1.3 ,-        prettyprinter-ansi-terminal >= 1.1.1    && < 1.2 ,-        trifecta                    >= 1.6      && < 1.8 ,-        text                        >= 0.11.1.0 && < 1.3-    GHC-Options: -Wall-    Other-Modules:-        Paths_dhall+        mockery                 < 0.4 ,+        doctest   >= 0.7.0+    if os(windows)+      -- https://github.com/dhall-lang/dhall-haskell/issues/2237+      Buildable: False+    Default-Language: Haskell2010 -Executable dhall-hash-    Hs-Source-Dirs: dhall-hash+Benchmark dhall-parser+    Import: common+    Type: exitcode-stdio-1.0+    Hs-Source-Dirs: benchmark/parser     Main-Is: Main.hs     Build-Depends:-        base             >= 4        && < 5  ,-        dhall                                ,-        optparse-generic >= 1.1.1    && < 1.4,-        trifecta         >= 1.6      && < 1.8,-        text             >= 0.11.1.0 && < 1.3-    Other-Modules:-        Paths_dhall+        dhall                                         ,+        tasty-bench               >= 0.4      && < 0.5,+    Default-Language: Haskell2010+    Other-Extensions:+        TypeApplications+    Ghc-Options: -rtsopts -Test-Suite test+Benchmark deep-nested-large-record+    Import: common     Type: exitcode-stdio-1.0-    Hs-Source-Dirs: tests-    Main-Is: Tests.hs-    GHC-Options: -Wall-    Other-Modules:-        Format-        Normalization-        Parser-        Regression-        Tutorial-        TypeCheck-        Util+    Hs-Source-Dirs: benchmark/deep-nested-large-record+    Main-Is: Main.hs     Build-Depends:-        base                      >= 4        && < 5   ,-        deepseq                   >= 1.2.0.1  && < 1.5 ,-        dhall                                          ,-        insert-ordered-containers                      ,-        prettyprinter                                  ,-        tasty                     >= 0.11.2   && < 1.1 ,-        tasty-hunit               >= 0.9.2    && < 0.11,-        text                      >= 0.11.1.0 && < 1.3 ,-        vector                    >= 0.11.0.0 && < 0.13+        dhall                                         ,+        tasty-bench               >= 0.4      && < 0.5,+    Default-Language: Haskell2010
dhall/Main.hs view
@@ -1,117 +1,6 @@-{-# LANGUAGE DataKinds          #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE ExplicitNamespaces #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE TypeOperators      #-}- module Main where -import Control.Exception (SomeException)-import Control.Monad (when)-import Data.Monoid (mempty)-import Data.Version (showVersion)-import Dhall.Core (normalize)-import Dhall.Import (Imported(..), load)-import Dhall.Parser (Src)-import Dhall.Pretty (annToAnsiStyle, prettyExpr)-import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X)-import Options.Generic (Generic, ParseRecord, Wrapped, type (<?>)(..), (:::))-import System.Exit (exitFailure, exitSuccess)-import Text.Trifecta.Delta (Delta(..))--import qualified Paths_dhall as Meta--import qualified Control.Exception-import qualified Data.Text.Lazy.IO-import qualified Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Dhall.Parser-import qualified Dhall.TypeCheck-import qualified Options.Generic-import qualified System.Console.ANSI-import qualified System.IO--data Options w = Options-    { explain :: w ::: Bool <?> "Explain error messages in more detail"-    , version :: w ::: Bool <?> "Display version and exit"-    , plain   :: w ::: Bool <?> "Disable syntax highlighting"-    } deriving (Generic)--instance ParseRecord (Options Wrapped)--opts :: Pretty.LayoutOptions-opts =-    Pretty.defaultLayoutOptions-        { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }+import qualified Dhall.Main  main :: IO ()-main = do-    Options {..} <- Options.Generic.unwrapRecord "Compiler for the Dhall language"-    when version $ do-      putStrLn (showVersion Meta.version)-      exitSuccess--    let handle =-                Control.Exception.handle handler2-            .   Control.Exception.handle handler1-            .   Control.Exception.handle handler0-          where-            handler0 e = do-                let _ = e :: TypeError Src X-                System.IO.hPutStrLn System.IO.stderr ""-                if explain-                    then Control.Exception.throwIO (DetailedTypeError e)-                    else do-                        Data.Text.Lazy.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"-                        Control.Exception.throwIO e--            handler1 (Imported ps e) = do-                let _ = e :: TypeError Src X-                System.IO.hPutStrLn System.IO.stderr ""-                if explain-                    then Control.Exception.throwIO (Imported ps (DetailedTypeError e))-                    else do-                        Data.Text.Lazy.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"-                        Control.Exception.throwIO (Imported ps e)--            handler2 e = do-                let _ = e :: SomeException-                System.IO.hSetEncoding System.IO.stderr System.IO.utf8-                System.IO.hPrint System.IO.stderr e-                System.Exit.exitFailure--    handle (do-        System.IO.hSetEncoding System.IO.stdin System.IO.utf8-        inText <- Data.Text.Lazy.IO.getContents--        expr <- case Dhall.Parser.exprFromText (Directed "(stdin)" 0 0 0 0) inText of-            Left  err -> Control.Exception.throwIO err-            Right x   -> return x--        let render h e = do-                let doc = prettyExpr e--                let layoutOptions = opts-                let stream = Pretty.layoutSmart layoutOptions doc--                supportsANSI <- System.Console.ANSI.hSupportsANSI h-                let ansiStream =-                        if supportsANSI && not plain-                        then fmap annToAnsiStyle stream-                        else Pretty.unAnnotateS stream--                Pretty.renderIO h ansiStream-                Data.Text.Lazy.IO.hPutStrLn h ""---        expr' <- load expr--        typeExpr <- case Dhall.TypeCheck.typeOf expr' of-            Left  err      -> Control.Exception.throwIO err-            Right typeExpr -> return typeExpr--        render System.IO.stderr (normalize typeExpr)-        Data.Text.Lazy.IO.hPutStrLn System.IO.stderr mempty-        render System.IO.stdout (normalize expr') )+main = Dhall.Main.main
+ doctest/Main.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE CPP #-}++module Main (main) where++import System.FilePath ((</>))++import qualified GHC.IO.Encoding+import qualified System.Directory+import qualified System.Environment+import qualified System.IO+import qualified Test.DocTest+import qualified Test.Mockery.Directory++main :: IO ()+main = do+    GHC.IO.Encoding.setLocaleEncoding System.IO.utf8+    args <- System.Environment.getArgs+    pwd <- System.Directory.getCurrentDirectory+    prefix <- System.Directory.makeAbsolute pwd+    let src = prefix </> "src"++    System.Environment.setEnv "XDG_CACHE_HOME" (pwd </> ".cache")++    Test.Mockery.Directory.inTempDirectory $ do+        writeFile "makeBools.dhall" "λ(n : Bool) → [ n && True, n && False, n || True, n || False ]"+        writeFile "bool1" "True"+        writeFile "bool2" "False"+        writeFile "both" "./bool1 && ./bool2"+        writeFile "file2" "./file1"+        writeFile "file1" "./file2"+        writeFile "simon.dhall" $ unlines+          [ "let Name = Text"+          , "let Font = < Arial | `Comic Sans` | Helvetica | `Times New Roman` >"+          , "let Person = { name : Name, favoriteFont : Font }"+          , "in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person"+          ]++        Test.DocTest.doctest $+            [ "-DWITH_HTTP"+            , "-DUSE_HTTP_CLIENT_TLS"+            , "--fast"+            ] <> args <>+            [ prefix </> "ghc-src"++            -- Unfortunately we cannot target the entire @src@ directory.+            -- The reason is that src/Dhall/Version.hs depends on+            -- the generated Paths_dhall module which is "out-of-scope"+            -- when running the testsuite with cabal v1-test.+            -- Instead, we target a selection of modules whose combined module+            -- dependency tree covers all modules that contain doctests.++            -- , src+            , "-i" <> src+#if __GLASGOW_HASKELL__ >= 806+            , src </> "Dhall/Deriving.hs"+#endif+            , src </> "Dhall/Tags.hs"+            , src </> "Dhall/Tutorial.hs"+            ]
+ ghc-src/Dhall/Crypto.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-| This module provides implementations of cryptographic utilities that only+    work for GHC (as opposed to GHCJS)+-}++module Dhall.Crypto (+      SHA256Digest(..)+    , sha256DigestFromByteString+    , sha256Hash+    , toString+    ) where++import Control.DeepSeq         (NFData)+import Data.ByteString         (ByteString)+import Data.Data               (Data)+import GHC.Generics            (Generic)++import qualified Crypto.Hash.SHA256+import qualified Data.ByteString        as ByteString+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8  as ByteString.Char8++-- | A SHA256 digest+newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }+  deriving (Data, Eq, Generic, Ord, NFData)++instance Show SHA256Digest where+  show = toString++{-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning+    `Nothing` if the conversion fails+-}+sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest+sha256DigestFromByteString bytes+  | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+  | otherwise                     = Nothing++-- | Hash a `ByteString` and return the hash as a `SHA256Digest`+sha256Hash :: ByteString -> SHA256Digest+sha256Hash = SHA256Digest . Crypto.Hash.SHA256.hash++-- | 'String' representation of a 'SHA256Digest'+toString :: SHA256Digest -> String+toString (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes
+ ghc-src/Dhall/Import/HTTP.hs view
@@ -0,0 +1,320 @@+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++module Dhall.Import.HTTP+    ( fetchFromHttpUrl+    , fetchFromHttpUrlBytes+    , originHeadersFileExpr+    ) where++import Control.Exception                (Exception)+import Control.Monad.IO.Class           (MonadIO (..))+import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI)+import Data.Dynamic                     (toDyn)+import Data.List.NonEmpty               (NonEmpty (..))+import Data.Text.Encoding               (decodeUtf8)+import Dhall.Core+    ( Expr (..)+    , Directory (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , Scheme (..)+    , URL (..)+    )+import Dhall.Import.Types+import Dhall.Parser                     (Src)+import Dhall.URL                        (renderURL)+import System.Directory                 (getXdgDirectory, XdgDirectory(XdgConfig))+import System.FilePath                  (splitDirectories)+++import Network.HTTP.Client (HttpException (..), HttpExceptionContent (..))++import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.ByteString.Lazy             as ByteString.Lazy+import qualified Data.HashMap.Strict              as HashMap+import qualified Data.Text                        as Text+import qualified Data.Text.Encoding+import qualified Dhall.Util+import qualified Network.HTTP.Client              as HTTP+import qualified Network.HTTP.Types++mkPrettyHttpException :: String -> HttpException -> PrettyHttpException+mkPrettyHttpException url ex =+    PrettyHttpException (renderPrettyHttpException url ex) (toDyn ex)++renderPrettyHttpException :: String -> HttpException -> String+renderPrettyHttpException _ (InvalidUrlException _ r) =+      "\n"+  <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"+  <>  "\n"+  <>  "URL: " <> show r <> "\n"+renderPrettyHttpException url (HttpExceptionRequest _ e) =+  case e of+    ConnectionFailure _ ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Remote host not found\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    InvalidDestinationHost host ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Invalid remote host name:\n"+      <>  "\n"+      <>  "Host: " <> show host <> "\n"+    ResponseTimeout ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: The remote host took too long to respond\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    ConnectionTimeout ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Connection establishment took too long\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    StatusCodeException response body -> prefix <> suffix+      where+        prefix+            | statusCode == 401 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Access unauthorized\n"+            | statusCode == 403 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Access forbidden\n"+            | statusCode == 404 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Remote file not found\n"+            | statusCode == 500 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Server-side failure\n"+            | statusCode == 502 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Upstream failure\n"+            | statusCode == 503 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Server temporarily unavailable\n"+            | statusCode == 504 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Upstream timeout\n"+            | otherwise =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: HTTP request failure\n"++        suffix =+                "\n"+            <>  "HTTP status code: " <> show statusCode <> "\n"+            <>  "\n"+            <>  "URL: " <> url <> "\n"+            <>  message++        statusCode =+            Network.HTTP.Types.statusCode+                (HTTP.responseStatus response)++        message =+            case Data.Text.Encoding.decodeUtf8' body of+                Left _ ->+                        "\n"+                    <>  "Message (non-UTF8 bytes):\n"+                    <>  "\n"+                    <>  truncatedBodyString <> "\n"+                  where+                    bodyString = show body++                    dots = "…"++                    truncatedLength = 80 - length dots++                    truncatedBodyString+                        | truncatedLength < length bodyString =+                            take truncatedLength bodyString <> dots+                        | otherwise =+                            bodyString+                Right "" ->+                    ""+                Right bodyText ->+                        "\n"+                    <>  "Message:\n"+                    <>  "\n"+                    <>  Text.unpack prefixedText+                  where+                    prefixedLines =+                        zipWith combine prefixes (Text.lines bodyText)+                      where+                        prefixes =+                            map (Text.pack . show) [(1 ::Int)..7] ++ [ "…" ]++                        combine n line = n <> "│ " <> line++                    prefixedText = Text.unlines prefixedLines++    e' -> "\n"+      <>  "\ESC[1;31mError\ESC[0m: " <> show e'+      <>  "\n"+      <>  "URL: " <> url <> "\n"++newManager :: StateT Status IO Manager+newManager = do+    Status { _manager = oldManager, ..} <- State.get++    case oldManager of+        Nothing -> do+            manager <- liftIO _newManager++            State.put (Status { _manager = Just manager , ..})++            return manager++        Just manager ->+            return manager++data NotCORSCompliant = NotCORSCompliant+    { expectedOrigins :: [ByteString]+    , actualOrigin    :: ByteString+    }++instance Exception NotCORSCompliant++instance Show NotCORSCompliant where+    show (NotCORSCompliant {..}) =+            Dhall.Util._ERROR <> ": Not CORS compliant\n"+        <>  "\n"+        <>  "Dhall supports transitive imports, meaning that an imported expression can\n"+        <>  "import other expressions.  However, a remote import (the \"parent\" import)\n"+        <>  "cannot import another remote import (the \"child\" import) unless the child\n"+        <>  "import grants permission to do using CORS.  The child import must respond with\n"+        <>  "an `Access-Control-Allow-Origin` response header that matches the parent\n"+        <>  "import, otherwise Dhall rejects the import.\n"+        <>  "\n" <> prologue+      where+        prologue =+            case expectedOrigins of+                [ expectedOrigin ] ->+                        "The following parent import:\n"+                    <>  "\n"+                    <>  "↳ " <> show actualOrigin <> "\n"+                    <>  "\n"+                    <>  "... did not match the expected origin:\n"+                    <>  "\n"+                    <>  "↳ " <> show expectedOrigin <> "\n"+                    <>  "\n"+                    <>  "... so import resolution failed.\n"+                [] ->+                        "The child response did not include any `Access-Control-Allow-Origin` header,\n"+                    <>  "so import resolution failed.\n"+                _:_:_ ->+                        "The child response included more than one `Access-Control-Allow-Origin` header,\n"+                    <>  "when only one such header should have been present, so import resolution\n"+                    <>  "failed.\n"+                    <>  "\n"+                    <>  "This may indicate that the server for the child import is misconfigured.\n"++corsCompliant+    :: MonadIO io+    => ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()+corsCompliant (Remote parentURL) childURL responseHeaders = liftIO $ do+    let toOrigin (URL {..}) =+            Data.Text.Encoding.encodeUtf8 (prefix <> "://" <> authority)+          where+            prefix =+                case scheme of+                    HTTP  -> "http"+                    HTTPS -> "https"++    let actualOrigin = toOrigin parentURL++    let childOrigin = toOrigin childURL++    let predicate (header, _) = header == "Access-Control-Allow-Origin"++    let originHeaders = filter predicate responseHeaders++    let expectedOrigins = map snd originHeaders++    case expectedOrigins of+        [expectedOrigin]+            | expectedOrigin == "*" ->+                return ()+            | expectedOrigin == actualOrigin ->+                return ()+        _   | actualOrigin == childOrigin ->+                return ()+            | otherwise ->+                Control.Exception.throwIO (NotCORSCompliant {..})+corsCompliant _ _ _ = return ()++addHeaders :: OriginHeaders -> Maybe [HTTPHeader] -> HTTP.Request -> HTTP.Request+addHeaders originHeaders urlHeaders request =+    request { HTTP.requestHeaders = (filterHeaders urlHeaders) <> perOriginHeaders }+      where+        origin = decodeUtf8 (HTTP.host request) <> ":" <> Text.pack (show (HTTP.port request))+ +        perOriginHeaders = HashMap.lookupDefault [] origin originHeaders++        filterHeaders = foldMap (filter (not . overridden))++        overridden :: HTTPHeader -> Bool+        overridden (key, _value) = any (matchesKey key) perOriginHeaders++        matchesKey :: CI ByteString -> HTTPHeader -> Bool+        matchesKey key (candidate, _value) = key == candidate++fetchFromHttpUrlBytes+    :: URL -> Maybe [HTTPHeader] -> StateT Status IO ByteString+fetchFromHttpUrlBytes childURL mheaders = do+    Status { _loadOriginHeaders } <- State.get++    originHeaders <- _loadOriginHeaders++    manager <- newManager++    let childURLString = Text.unpack (renderURL childURL)++    baseRequest <- liftIO (HTTP.parseUrlThrow childURLString)++    let requestWithHeaders = addHeaders originHeaders mheaders baseRequest++    let io = HTTP.httpLbs requestWithHeaders manager++    let handler e = do+            let _ = e :: HttpException+            Control.Exception.throwIO (mkPrettyHttpException childURLString e)++    response <- liftIO (Control.Exception.handle handler io)++    Status {..} <- State.get++    case _stack of+        -- We ignore the first import in the stack since that is the same import+        -- as the `childUrl`+        _ :| Chained parentImport : _ -> do+            let parentImportType = importType (importHashed parentImport)++            corsCompliant parentImportType childURL (HTTP.responseHeaders response)+        _ -> do+            return ()++    return (ByteString.Lazy.toStrict (HTTP.responseBody response))++fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text+fetchFromHttpUrl childURL mheaders = do+    bytes <- fetchFromHttpUrlBytes childURL mheaders++    case Data.Text.Encoding.decodeUtf8' bytes of+        Left  err  -> liftIO (Control.Exception.throwIO err)+        Right text -> return text++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = do+    directoryStr <- getXdgDirectory XdgConfig "dhall"+    let components = map Text.pack (splitDirectories directoryStr)+    let directory = Directory (reverse components)+    let file = (File directory "headers.dhall")+    return (Embed (Import (ImportHashed Nothing (Local Absolute file)) Code))
+ ghc-src/Dhall/Import/Manager.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE CPP #-}++{-| Both the GHC and GHCJS implementations of 'Dhall.Import.Manager.Manager'+    export a `Dhall.Import.Manager.Manager` type suitable for use within the+    "Dhall.Import" module++    For the GHC implementation the `Dhall.Import.Manager` type is a real+    `Network.HTTP.Client.Manager` from the @http-client@ package.  For the+    GHCJS implementation the `Dhall.Import.Manager.Manager` type is+    a synonym for @`Data.Void.Void`@ since GHCJS does not use a+    `Network.HTTP.Client.Manager` for HTTP requests.+-}+module Dhall.Import.Manager+    ( -- * Manager+      Manager+    , defaultNewManager+    ) where++import           Network.HTTP.Client (Manager, newManager)+import qualified Network.HTTP.Client as HTTP++#ifdef USE_HTTP_CLIENT_TLS+import Network.HTTP.Client.TLS (tlsManagerSettings)+#endif++defaultNewManager :: IO Manager+defaultNewManager = newManager+#ifdef USE_HTTP_CLIENT_TLS+  tlsManagerSettings+#else+  HTTP.defaultManagerSettings+#endif+    { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (30 * 1000 * 1000) }  -- 30 seconds
+ ghcjs-src/Dhall/Crypto.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE JavaScriptFFI              #-}++{-| This module provides implementations of cryptographic utilities that only+    work for GHCJS+-}++module Dhall.Crypto (+      SHA256Digest(..)+    , sha256DigestFromByteString+    , sha256Hash+    ) where++import Control.DeepSeq                   (NFData)+import Data.ByteString                   (ByteString)+import Data.Data                         (Data)+import GHC.Generics                      (Generic)+import JavaScript.TypedArray.ArrayBuffer (ArrayBuffer)+import System.IO.Unsafe                  (unsafePerformIO)++import qualified Data.ByteString        as ByteString+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8  as ByteString.Char8+import qualified GHCJS.Buffer           as Buffer++-- | A SHA256 digest+newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }+  deriving (Data, Eq, Generic, Ord, NFData)++instance Show SHA256Digest where+  show (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes++{-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning+    `Nothing` if the conversion fails+-}+sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest+sha256DigestFromByteString bytes+  | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+  | otherwise                     = Nothing++-- Use NodeJS' crypto module if there's a 'process' module, e.g. we're running+-- inside GHCJS' THRunner. If we're running in the browser, use the WebCrypto+-- interface.+foreign import javascript interruptible+  "if (typeof process === 'undefined') { \+  \  crypto.subtle.digest('SHA-256', $1).then($c) \+  \} else { \+  \  $c(require('crypto').createHash('sha256').update(Buffer.from($1)).digest().buffer) \+  \}"+  js_sha256Hash :: ArrayBuffer -> IO ArrayBuffer++byteStringToArrayBuffer :: ByteString -> ArrayBuffer+byteStringToArrayBuffer b =+  js_arrayBufferSlice offset len $ Buffer.getArrayBuffer buffer+  where+    (buffer, offset, len) = Buffer.fromByteString b++foreign import javascript unsafe "$3.slice($1, $1 + $2)"+  js_arrayBufferSlice :: Int -> Int -> ArrayBuffer -> ArrayBuffer++arrayBufferToByteString :: ArrayBuffer -> ByteString+arrayBufferToByteString =+  Buffer.toByteString 0 Nothing . Buffer.createFromArrayBuffer++-- | Hash a `ByteString` and return the hash as a `SHA256Digest`+sha256Hash :: ByteString -> SHA256Digest+sha256Hash bytes+  | ByteString.length out == 32 = SHA256Digest out+  | otherwise = error "sha256Hash: didn't produce 32 bytes"+  where+    out =+      arrayBufferToByteString $+      unsafePerformIO $ js_sha256Hash (byteStringToArrayBuffer bytes)
+ ghcjs-src/Dhall/Import/HTTP.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Import.HTTP+    ( fetchFromHttpUrl+    , fetchFromHttpUrlBytes+    , originHeadersFileExpr+    ) where++import Control.Monad.IO.Class           (MonadIO (..))+import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI)+import Dhall.Core                       (URL (..), Expr (..))+import Dhall.Import.Types               (Import, Status)+import Dhall.Parser                     (Src)+import Dhall.URL                        (renderURL)++import qualified Data.Text          as Text+import qualified Data.Text.Encoding as Text.Encoding+import qualified JavaScript.XHR++fetchFromHttpUrl+    :: URL+    -> Maybe [(CI ByteString, ByteString)]+    -> StateT Status IO Text.Text+fetchFromHttpUrl childURL Nothing = do+    let childURLText = renderURL childURL++    let childURLString = Text.unpack childURLText++    -- No need to add a CORS compliance check when using GHCJS.  The browser+    -- will already check the CORS compliance of the following XHR+    (statusCode, body) <- liftIO (JavaScript.XHR.get childURLText)++    case statusCode of+        200 -> return ()+        _   -> fail (childURLString <> " returned a non-200 status code: " <> show statusCode)++    return body+fetchFromHttpUrl _ _ =+    fail "Dhall does not yet support custom headers when built using GHCJS"++fetchFromHTTPUrlBytes+    :: URL+    -> Maybe [(CI ByteString, ByteString)]+    -> StateT Status IO ByteString+fetchFromHTTPUrlBytes childUrl mheader = do+    text <- fetchFromHTTPUrl childUrl mheader+    return (Text.Encoding.encodeUtf8 text)++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = return Missing
+ ghcjs-src/Dhall/Import/Manager.hs view
@@ -0,0 +1,26 @@+{-| Both the GHC and GHCJS implementations of `Dhall.Import.Manager.Manager`+    export a `Dhall.Import.Manager.Manager` type suitable for use within the+    "Dhall.Import" module++    For the GHC implementation the `Dhall.Import.Manager.Manager` type is a real+    `Network.HTTP.Client.Manager` from the @http-client@ package.  For the GHCJS+    implementation the `Dhall.Import.Manager.Manager` type is a synonym for+    @`Data.Void.Void`@ since GHCJS does not use a+    `Network.HTTP.Client.Manager` for HTTP requests.+-}+module Dhall.Import.Manager+    ( -- * Manager+      Manager+    , defaultNewManager+    ) where++{-| The GHCJS implementation does not require a `Network.HTTP.Client.Manager`++    The purpose of this synonym is so that "Dhall.Import.Types" can import a+    `Dhall.Import.Manager.Manager` type from "Dhall.Import.HTTP" that does the+    correct thing for both the GHC and GHCJS implementations+-}+type Manager = ()++defaultNewManager :: IO Manager+defaultNewManager = pure ()
+ man/dhall.1 view
@@ -0,0 +1,100 @@+.\" Automatically generated by Pandoc 2.9.2+.\"+.TH "dhall (1)" "" "" "" ""+.hy+.SH NAME+.PP+dhall - a programmable configuration language+.SH DESCRIPTION+.PP+\f[B]dhall\f[R] is the command-line interface to the Dhall language+.SH SYNOPSIS+.PP+dhall --file check.dhall+.PP+dhall --file error.dhall --explain+.PP+dhall hash --file to-hash.dhall+.PP+dhall freeze --file with-imports.dhall+.PP+dhall repl+.PP+dhall diff \[aq]./file1.dhall\[cq] \[aq]./file2.dhall\[cq]+.PP+dhall type --quiet --file check-ci.dhall+.SH SUBCOMMANDS+.PP+\f[B]version\f[R] - Display version information+.PP+\f[B]resolve\f[R] - Resolve imports+.PP+\f[B]type\f[R] - Infer type of expression+.PP+\f[B]normalize\f[R] - Normalize an expression+.PP+\f[B]repl\f[R] - Open a REPL+.PP+\f[B]diff\f[R] - Show difference between two expressions+.PP+\f[B]hash\f[R] - Compute hash of expression+.PP+\f[B]lint\f[R] - Lint an expression, removing dead code+.PP+\f[B]tags\f[R] - Generate etags (Emacs) file+.PP+\f[B]format\f[R] - Format an expression+.PP+\f[B]freeze\f[R] - Add hashes to import statements+.PP+\f[B]encode\f[R] - Encode a Dhall expression (CBOR)+.PP+\f[B]decode\f[R] - Decode a Dhall expression+.PP+\f[B]text\f[R] - Render a Dhall expression to text+.PP+\f[B]to-directory-tree\f[R] - Convert nested record of Text into a+directory+.SH OPTIONS+.TP+\f[B]-h\f[R] \f[B]--help\f[R]+Display help+.TP+\f[B]--file\f[R]+Name of file containing Dhall source+.TP+\f[B]--output\f[R]+Output file+.TP+\f[B]--annotate\f[R]+Add type annotation to output+.TP+\f[B]--alpha\f[R]+alpha-normalize output+.TP+\f[B]--no-cache\f[R]+Don\[cq]t use cache to resolve imports+.TP+\f[B]--explain\f[R]+Explain error messages in detail+.TP+\f[B]--version\f[R]+Display version information+.TP+\f[B]--plain\f[R]+Disable syntax highlighting in output+.TP+\f[B]--ascii\f[R]+Format code using only ASCII syntax+.TP+\f[B]--censor\f[R]+Hide source code from error messages+.SH EDITOR INTEGRATION+.PP+Up-to-date information on editor integration is available at:+.PP+https://docs.dhall-lang.org/howtos/Text-Editor-Configuration.html+.SH BUGS+.PP+Please report any bugs you may come across to+https://github.com/dhall-lang/dhall-haskell/issues.
src/Dhall.hs view
@@ -1,1060 +1,579 @@-{-# LANGUAGE DefaultSignatures   #-}-{-# LANGUAGE DeriveAnyClass      #-}-{-# LANGUAGE DeriveFunctor       #-}-{-# LANGUAGE DeriveGeneric       #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE RecordWildCards     #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE TypeOperators       #-}--{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining-    how to use the language, the compiler, and this library--}--module Dhall-    (-    -- * Input-      input-    , inputWith-    , detailed--    -- * Types-    , Type(..)-    , InputType(..)-    , Interpret(..)-    , InvalidType(..)-    , auto-    , genericAuto-    , InterpretOptions(..)-    , defaultInterpretOptions-    , bool-    , natural-    , integer-    , scientific-    , double-    , lazyText-    , strictText-    , maybe-    , sequence-    , list-    , vector-    , unit-    , string-    , pair-    , GenericInterpret(..)-    , GenericInject(..)--    , Inject(..)-    , inject--    -- * Miscellaneous-    , rawInput--    -- * Re-exports-    , Natural-    , Seq-    , Text-    , Vector-    , Generic-    ) where--import Control.Applicative (empty, liftA2, (<|>), Alternative)-import Control.Exception (Exception)-import Control.Monad.Trans.State.Strict-import Data.Functor.Contravariant (Contravariant(..))-import Data.Monoid ((<>))-import Data.Scientific (Scientific)-import Data.Sequence (Seq)-import Data.Text.Buildable (Buildable(..))-import Data.Text.Lazy (Text)-import Data.Typeable (Typeable)-import Data.Vector (Vector)-import Data.Word (Word8, Word16, Word32, Word64)-import Dhall.Core (Expr(..), Chunks(..))-import Dhall.Import (Imported(..))-import Dhall.Parser (Src(..))-import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X)-import GHC.Generics-import Numeric.Natural (Natural)-import Prelude hiding (maybe, sequence)-import Text.Trifecta.Delta (Delta(..))--import qualified Control.Exception-import qualified Data.ByteString.Lazy-import qualified Data.Foldable-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.Scientific-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Builder-import qualified Data.Text.Lazy.Encoding-import qualified Data.Vector-import qualified Dhall.Context-import qualified Dhall.Core-import qualified Dhall.Import-import qualified Dhall.Parser-import qualified Dhall.TypeCheck--throws :: Exception e => Either e a -> IO a-throws (Left  e) = Control.Exception.throwIO e-throws (Right r) = return r--{-| Every `Type` must obey the contract that if an expression's type matches the-    the `expected` type then the `extract` function must succeed.  If not, then-    this exception is thrown--    This exception indicates that an invalid `Type` was provided to the `input`-    function--}-data InvalidType = InvalidType deriving (Typeable)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance Show InvalidType where-    show InvalidType =-        _ERROR <> ": Invalid Dhall.Type                                                  \n\-        \                                                                                \n\-        \Every Type must provide an extract function that succeeds if an expression      \n\-        \matches the expected type.  You provided a Type that disobeys this contract     \n"--instance Exception InvalidType--{-| Type-check and evaluate a Dhall program, decoding the result into Haskell--    The first argument determines the type of value that you decode:-->>> input integer "2"-2->>> input (vector double) "[1.0, 2.0]"-[1.0,2.0]--    Use `auto` to automatically select which type to decode based on the-    inferred return type:-->>> input auto "True" :: IO Bool-True--}-input-    :: Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> Text-    -- ^ The Dhall program-    -> IO a-    -- ^ The decoded value in Haskell-input ty txt =-  inputWith ty Dhall.Context.empty (const Nothing) txt--{-| Extend 'input' with a custom typing context and normalization process.---}-inputWith-    :: Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> Dhall.Context.Context (Expr Src X)-    -- ^ The starting context for type-checking-    -> Dhall.Core.Normalizer X-    -> Text-    -- ^ The Dhall program-    -> IO a-    -- ^ The decoded value in Haskell-inputWith (Type {..}) ctx n txt = do-    let delta = Directed "(input)" 0 0 0 0-    expr  <- throws (Dhall.Parser.exprFromText delta txt)-    expr' <- Dhall.Import.loadWithContext ctx expr-    let suffix =-            ( Data.ByteString.Lazy.toStrict-            . Data.Text.Lazy.Encoding.encodeUtf8-            . Data.Text.Lazy.Builder.toLazyText-            . build-            ) expected-    let annot = case expr' of-            Note (Src begin end bytes) _ ->-                Note (Src begin end bytes') (Annot expr' expected)-              where-                bytes' = bytes <> " : " <> suffix-            _ ->-                Annot expr' expected-    _ <- throws (Dhall.TypeCheck.typeWith ctx annot)-    case extract (Dhall.Core.normalizeWith n expr') of-        Just x  -> return x-        Nothing -> Control.Exception.throwIO InvalidType---- | Use this function to extract Haskell values directly from Dhall AST.---   The intended use case is to allow easy extraction of Dhall values for---   making the function `Dhall.Core.normalizeWith` easier to use.------   For other use cases, use `input` from `Dhall` module. It will give you---   a much better user experience.-rawInput-    :: Alternative f-    => Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> Expr s X-    -- ^ a closed form Dhall program, which evaluates to the expected type-    -> f a-    -- ^ The decoded value in Haskell-rawInput (Type {..}) expr = do-    case extract (Dhall.Core.normalize expr) of-        Just x  -> pure x-        Nothing -> empty----{-| Use this to provide more detailed error messages-->> input auto "True" :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> True : Integer->-> (input):1:1-->> detailed (input auto "True") :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> Explanation: You can annotate an expression with its type or kind using the-> ❰:❱ symbol, like this:->->->     ┌───────┐->     │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱->     └───────┘->-> The type checker verifies that the expression's type or kind matches the-> provided annotation->-> For example, all of the following are valid annotations that the type checker-> accepts:->->->     ┌─────────────┐->     │ 1 : Integer │  ❰1❱ is an expression that has type ❰Integer❱, so the type->     └─────────────┘  checker accepts the annotation->->->     ┌────────────────────────┐->     │ Natural/even +2 : Bool │  ❰Natural/even +2❱ has type ❰Bool❱, so the type->     └────────────────────────┘  checker accepts the annotation->->->     ┌────────────────────┐->     │ List : Type → Type │  ❰List❱ is an expression that has kind ❰Type → Type❱,->     └────────────────────┘  so the type checker accepts the annotation->->->     ┌──────────────────┐->     │ List Text : Type │  ❰List Text❱ is an expression that has kind ❰Type❱, so->     └──────────────────┘  the type checker accepts the annotation->->-> However, the following annotations are not valid and the type checker will-> reject them:->->->     ┌──────────┐->     │ 1 : Text │  The type checker rejects this because ❰1❱ does not have type->     └──────────┘  ❰Text❱->->->     ┌─────────────┐->     │ List : Type │  ❰List❱ does not have kind ❰Type❱->     └─────────────┘->->-> You or the interpreter annotated this expression:->-> ↳ True->-> ... with this type or kind:->-> ↳ Integer->-> ... but the inferred type or kind of the expression is actually:->-> ↳ Bool->-> Some common reasons why you might get this error:->-> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation->   matching the expected type->->   For example, if you run the following Haskell code:->->->     ┌───────────────────────────────┐->     │ >>> input auto "1" :: IO Text │->     └───────────────────────────────┘->->->   ... then the interpreter will actually type check the following annotated->   expression:->->->     ┌──────────┐->     │ 1 : Text │->     └──────────┘->->->   ... and then type-checking will fail->-> ────────────────────────────────────────────────────────────────────────────────->-> True : Integer->-> (input):1:1---}-detailed :: IO a -> IO a-detailed =-    Control.Exception.handle handler1 . Control.Exception.handle handler0-  where-    handler0 :: Imported (TypeError Src X) -> IO a-    handler0 (Imported ps e) =-        Control.Exception.throwIO (Imported ps (DetailedTypeError e))--    handler1 :: TypeError Src X -> IO a-    handler1 e = Control.Exception.throwIO (DetailedTypeError e)--{-| A @(Type a)@ represents a way to marshal a value of type @\'a\'@ from Dhall-    into Haskell--    You can produce `Type`s either explicitly:--> example :: Type (Vector Text)-> example = vector text--    ... or implicitly using `auto`:--> example :: Type (Vector Text)-> example = auto--    You can consume `Type`s using the `input` function:--> input :: Type a -> Text -> IO a--}-data Type a = Type-    { extract  :: Expr Src X -> Maybe a-    -- ^ Extracts Haskell value from the Dhall expression-    , expected :: Expr Src X-    -- ^ Dhall type of the Haskell value-    }-    deriving (Functor)--{-| Decode a `Bool`-->>> input bool "True"-True--}-bool :: Type Bool-bool = Type {..}-  where-    extract (BoolLit b) = pure b-    extract  _          = Nothing--    expected = Bool--{-| Decode a `Natural`-->>> input natural "+42"-42--}-natural :: Type Natural-natural = Type {..}-  where-    extract (NaturalLit n) = pure n-    extract  _             = empty--    expected = Natural--{-| Decode an `Integer`-->>> input integer "42"-42--}-integer :: Type Integer-integer = Type {..}-  where-    extract (IntegerLit n) = pure n-    extract  _             = empty--    expected = Integer--{-| Decode a `Scientific`-->>> input scientific "1e1000000000"-1.0e1000000000--}-scientific :: Type Scientific-scientific = Type {..}-  where-    extract (DoubleLit n) = pure n-    extract  _            = empty--    expected = Double--{-| Decode a `Double`-->>> input double "42.0"-42.0--}-double :: Type Double-double = fmap Data.Scientific.toRealFloat scientific--{-| Decode lazy `Text`-->>> input lazyText "\"Test\""-"Test"--}-lazyText :: Type Text-lazyText = Type {..}-  where-    extract (TextLit (Chunks [] t)) = pure (Data.Text.Lazy.Builder.toLazyText t)-    extract  _                      = empty--    expected = Text--{-| Decode strict `Text`-->>> input strictText "\"Test\""-"Test"--}-strictText :: Type Data.Text.Text-strictText = fmap Data.Text.Lazy.toStrict lazyText--{-| Decode a `Maybe`-->>> input (maybe integer) "[1] : Optional Integer"-Just 1--}-maybe :: Type a -> Type (Maybe a)-maybe (Type extractIn expectedIn) = Type extractOut expectedOut-  where-    extractOut (OptionalLit _ es) = traverse extractIn es-    extractOut  _                 = Nothing--    expectedOut = App Optional expectedIn--{-| Decode a `Seq`- -->>> input (sequence integer) "[1, 2, 3]"-[1,2,3]--}-sequence :: Type a -> Type (Seq a)-sequence (Type extractIn expectedIn) = Type extractOut expectedOut-  where-    extractOut (ListLit _ es) = traverse extractIn es-    extractOut  _             = Nothing--    expectedOut = App List expectedIn--{-| Decode a list-->>> input (list integer) "[1, 2, 3]"-[1,2,3]--}-list :: Type a -> Type [a]-list = fmap Data.Foldable.toList . sequence--{-| Decode a `Vector`-->>> input (vector integer) "[1, 2, 3]"-[1,2,3]--}-vector :: Type a -> Type (Vector a)-vector = fmap Data.Vector.fromList . list--{-| Decode `()` from an empty record.-->>> input unit "{=}"-()--}-unit :: Type ()-unit = Type extractOut expectedOut-  where-    extractOut (RecordLit fields)-        | Data.HashMap.Strict.InsOrd.null fields = return ()-    extractOut _ = Nothing--    expectedOut = Record Data.HashMap.Strict.InsOrd.empty--{-| Decode a `String`-->>> input string "\"ABC\""-"ABC"--"-}-string :: Type String-string = Data.Text.Lazy.unpack <$> lazyText--{-| Given a pair of `Type`s, decode a tuple-record into their pairing.-->>> input (pair natural bool) "{ _1 = +42, _2 = False }"-(42, False)--}-pair :: Type a -> Type b -> Type (a, b)-pair l r = Type extractOut expectedOut-  where-    extractOut (RecordLit fields) =-      (,) <$> ( Data.HashMap.Strict.InsOrd.lookup "_1" fields >>= extract l )-          <*> ( Data.HashMap.Strict.InsOrd.lookup "_2" fields >>= extract r )-    extractOut _ = Nothing--    expectedOut =-        Record-            (Data.HashMap.Strict.InsOrd.fromList-                [ ("_1", expected l)-                , ("_2", expected r)-                ]-            )--{-| Any value that implements `Interpret` can be automatically decoded based on-    the inferred return type of `input`-->>> input auto "[1, 2, 3]" :: IO (Vector Integer)-[1,2,3]--    This class auto-generates a default implementation for records that-    implement `Generic`.  This does not auto-generate an instance for recursive-    types.--}-class Interpret a where-    autoWith:: InterpretOptions -> Type a-    default autoWith-        :: (Generic a, GenericInterpret (Rep a)) => InterpretOptions -> Type a-    autoWith options = fmap GHC.Generics.to (evalState (genericAutoWith options) 1)--instance Interpret Bool where-    autoWith _ = bool--instance Interpret Natural where-    autoWith _ = natural--instance Interpret Integer where-    autoWith _ = integer--instance Interpret Scientific where-    autoWith _ = scientific--instance Interpret Double where-    autoWith _ = double--instance {-# OVERLAPS #-} Interpret [Char] where-    autoWith _ = string--instance Interpret Text where-    autoWith _ = lazyText--instance Interpret Data.Text.Text where-    autoWith _ = strictText--instance Interpret a => Interpret (Maybe a) where-    autoWith opts = maybe (autoWith opts)--instance Interpret a => Interpret (Seq a) where-    autoWith opts = sequence (autoWith opts)--instance Interpret a => Interpret [a] where-    autoWith = fmap (fmap Data.Vector.toList) autoWith--instance Interpret a => Interpret (Vector a) where-    autoWith opts = vector (autoWith opts)--instance (Inject a, Interpret b) => Interpret (a -> b) where-    autoWith opts = Type extractOut expectedOut-      where-        extractOut e = Just (\i -> case extractIn (Dhall.Core.normalize (App e (embed i))) of-            Just o  -> o-            Nothing -> error "Interpret: You cannot decode a function if it does not have the correct type" )--        expectedOut = Pi "_" declared expectedIn--        InputType {..} = inject--        Type extractIn expectedIn = autoWith opts--deriving instance (Interpret a, Interpret b) => Interpret (a, b)--{-| Use the default options for interpreting a configuration file--> auto = autoWith defaultInterpretOptions--}-auto :: Interpret a => Type a-auto = autoWith defaultInterpretOptions--{-| `genericAuto` is the default implementation for `auto` if you derive-    `Interpret`.  The difference is that you can use `genericAuto` without-    having to explicitly provide an `Interpret` instance for a type as long as-    the type derives `Generic`--}-genericAuto :: (Generic a, GenericInterpret (Rep a)) => Type a-genericAuto = fmap to (evalState (genericAutoWith defaultInterpretOptions) 1)--{-| Use these options to tweak how Dhall derives a generic implementation of-    `Interpret`--}-data InterpretOptions = InterpretOptions-    { fieldModifier       :: Text -> Text-    -- ^ Function used to transform Haskell field names into their corresponding-    --   Dhall field names-    , constructorModifier :: Text -> Text-    -- ^ Function used to transform Haskell constructor names into their-    --   corresponding Dhall alternative names-    }--{-| Default interpret options, which you can tweak or override, like this:--> autoWith->     (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })--}-defaultInterpretOptions :: InterpretOptions-defaultInterpretOptions = InterpretOptions-    { fieldModifier       = id-    , constructorModifier = id-    }--{-| This is the underlying class that powers the `Interpret` class's support-    for automatically deriving a generic implementation--}-class GenericInterpret f where-    genericAutoWith :: InterpretOptions -> State Int (Type (f a))--instance GenericInterpret f => GenericInterpret (M1 D d f) where-    genericAutoWith options = do-        res <- genericAutoWith options-        pure (fmap M1 res)--instance GenericInterpret V1 where-    genericAutoWith _ = pure Type {..}-      where-        extract _ = Nothing--        expected = Union Data.HashMap.Strict.InsOrd.empty--instance (Constructor c1, Constructor c2, GenericInterpret f1, GenericInterpret f2) => GenericInterpret (M1 C c1 f1 :+: M1 C c2 f2) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        nL :: M1 i c1 f1 a-        nL = undefined--        nR :: M1 i c2 f2 a-        nR = undefined--        nameL = constructorModifier (Data.Text.Lazy.pack (conName nL))-        nameR = constructorModifier (Data.Text.Lazy.pack (conName nR))--        extract (UnionLit name e _)-            | name == nameL = fmap (L1 . M1) (extractL e)-            | name == nameR = fmap (R1 . M1) (extractR e)-            | otherwise     = Nothing-        extract _ = Nothing--        expected =-            Union (Data.HashMap.Strict.InsOrd.fromList [(nameL, expectedL), (nameR, expectedR)])--        Type extractL expectedL = evalState (genericAutoWith options) 1-        Type extractR expectedR = evalState (genericAutoWith options) 1--instance (Constructor c, GenericInterpret (f :+: g), GenericInterpret h) => GenericInterpret ((f :+: g) :+: M1 C c h) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        n :: M1 i c h a-        n = undefined--        name = constructorModifier (Data.Text.Lazy.pack (conName n))--        extract u@(UnionLit name' e _)-            | name == name' = fmap (R1 . M1) (extractR e)-            | otherwise     = fmap  L1       (extractL u)-        extract _ = Nothing--        expected =-            Union (Data.HashMap.Strict.InsOrd.insert name expectedR expectedL)--        Type extractL (Union expectedL) = evalState (genericAutoWith options) 1-        Type extractR        expectedR  = evalState (genericAutoWith options) 1--instance (Constructor c, GenericInterpret f, GenericInterpret (g :+: h)) => GenericInterpret (M1 C c f :+: (g :+: h)) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        n :: M1 i c f a-        n = undefined--        name = constructorModifier (Data.Text.Lazy.pack (conName n))--        extract u@(UnionLit name' e _)-            | name == name' = fmap (L1 . M1) (extractL e)-            | otherwise     = fmap  R1       (extractR u)-        extract _ = Nothing--        expected =-            Union (Data.HashMap.Strict.InsOrd.insert name expectedL expectedR)--        Type extractL        expectedL  = evalState (genericAutoWith options) 1-        Type extractR (Union expectedR) = evalState (genericAutoWith options) 1--instance (GenericInterpret (f :+: g), GenericInterpret (h :+: i)) => GenericInterpret ((f :+: g) :+: (h :+: i)) where-    genericAutoWith options = pure (Type {..})-      where-        extract e = fmap L1 (extractL e) <|> fmap R1 (extractR e)--        expected = Union (Data.HashMap.Strict.InsOrd.union expectedL expectedR)--        Type extractL (Union expectedL) = evalState (genericAutoWith options) 1-        Type extractR (Union expectedR) = evalState (genericAutoWith options) 1--instance GenericInterpret f => GenericInterpret (M1 C c f) where-    genericAutoWith options = do-        res <- genericAutoWith options-        pure (fmap M1 res)--instance GenericInterpret U1 where-    genericAutoWith _ = pure (Type {..})-      where-        extract _ = Just U1--        expected = Record (Data.HashMap.Strict.InsOrd.fromList [])--instance (GenericInterpret f, GenericInterpret g) => GenericInterpret (f :*: g) where-    genericAutoWith options = do-        Type extractL expectedL <- genericAutoWith options-        Type extractR expectedR <- genericAutoWith options-        let Record ktsL = expectedL-        let Record ktsR = expectedR-        pure-            (Type-                { extract = liftA2 (liftA2 (:*:)) extractL extractR-                , expected = Record (Data.HashMap.Strict.InsOrd.union ktsL ktsR)-                }-            )--getSelName :: Selector s => M1 i s f a -> State Int String-getSelName n = case selName n of-    "" -> do i <- get-             put (i + 1)-             pure ("_" ++ show i)-    nn -> pure nn--instance (Selector s, Interpret a) => GenericInterpret (M1 S s (K1 i a)) where-    genericAutoWith opts@(InterpretOptions {..}) = do-        name <- getSelName n-        let extract (RecordLit m) = do-                    let name' = fieldModifier (Data.Text.Lazy.pack name)-                    e <- Data.HashMap.Strict.InsOrd.lookup name' m-                    fmap (M1 . K1) (extract' e)-            extract _            = Nothing-        let expected =-                Record (Data.HashMap.Strict.InsOrd.fromList [(key, expected')])-              where-                key = fieldModifier (Data.Text.Lazy.pack name)-        pure (Type {..})-      where-        n :: M1 i s f a-        n = undefined--        Type extract' expected' = autoWith opts--{-| An @(InputType a)@ represents a way to marshal a value of type @\'a\'@ from-    Haskell into Dhall--}-data InputType a = InputType-    { embed    :: a -> Expr Src X-    -- ^ Embeds a Haskell value as a Dhall expression-    , declared :: Expr Src X-    -- ^ Dhall type of the Haskell value-    }--instance Contravariant InputType where-    contramap f (InputType embed declared) = InputType embed' declared-      where-        embed' x = embed (f x)--{-| This class is used by `Interpret` instance for functions:--> instance (Inject a, Interpret b) => Interpret (a -> b)--    You can convert Dhall functions with "simple" inputs (i.e. instances of this-    class) into Haskell functions.  This works by:--    * Marshaling the input to the Haskell function into a Dhall expression (i.e.-      @x :: Expr Src X@)-    * Applying the Dhall function (i.e. @f :: Expr Src X@) to the Dhall input-      (i.e. @App f x@)-    * Normalizing the syntax tree (i.e. @normalize (App f x)@)-    * Marshaling the resulting Dhall expression back into a Haskell value--}-class Inject a where-    injectWith :: InterpretOptions -> InputType a-    default injectWith-        :: (Generic a, GenericInject (Rep a)) => InterpretOptions -> InputType a-    injectWith options-        = contramap GHC.Generics.from (evalState (genericInjectWith options) 1)--{-| Use the default options for injecting a value--> inject = inject defaultInterpretOptions--}-inject :: Inject a => InputType a-inject = injectWith defaultInterpretOptions--instance Inject Bool where-    injectWith _ = InputType {..}-      where-        embed = BoolLit--        declared = Bool--instance Inject Text where-    injectWith _ = InputType {..}-      where-        embed text =-            TextLit (Chunks [] (Data.Text.Lazy.Builder.fromLazyText text))--        declared = Text--instance Inject Data.Text.Text where-    injectWith _ = InputType {..}-      where-        embed text = TextLit (Chunks [] (Data.Text.Lazy.Builder.fromText text))--        declared = Text--instance Inject Natural where-    injectWith _ = InputType {..}-      where-        embed = NaturalLit--        declared = Natural--instance Inject Integer where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit--        declared = Integer--instance Inject Int where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word8 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word16 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word32 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word64 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Scientific where-    injectWith _ = InputType {..}-      where-        embed = DoubleLit--        declared = Double--instance Inject Double where-    injectWith =-        fmap (contramap (Data.Scientific.fromFloatDigits @Double)) injectWith--instance Inject () where-    injectWith _ = InputType {..}-      where-        embed = const (RecordLit Data.HashMap.Strict.InsOrd.empty)--        declared = Record Data.HashMap.Strict.InsOrd.empty--instance Inject a => Inject (Maybe a) where-    injectWith options = InputType embedOut declaredOut-      where-        embedOut (Just x) =-            OptionalLit declaredIn (pure (embedIn x))-        embedOut Nothing =-            OptionalLit declaredIn  empty--        InputType embedIn declaredIn = injectWith options--        declaredOut = App Optional declaredIn--instance Inject a => Inject (Seq a) where-    injectWith options = InputType embedOut declaredOut-      where-        embedOut xs = ListLit (Just declaredIn) (fmap embedIn xs)--        declaredOut = App List declaredIn--        InputType embedIn declaredIn = injectWith options--instance Inject a => Inject [a] where-    injectWith = fmap (contramap Data.Sequence.fromList) injectWith--instance Inject a => Inject (Vector a) where-    injectWith = fmap (contramap Data.Vector.toList) injectWith--instance Inject a => Inject (Data.Set.Set a) where-    injectWith = fmap (contramap Data.Set.toList) injectWith--deriving instance (Inject a, Inject b) => Inject (a, b)--{-| This is the underlying class that powers the `Interpret` class's support-    for automatically deriving a generic implementation--}-class GenericInject f where-    genericInjectWith :: InterpretOptions -> State Int (InputType (f a))--instance GenericInject f => GenericInject (M1 D d f) where-    genericInjectWith options = do-        res <- genericInjectWith options-        pure (contramap unM1 res)--instance GenericInject f => GenericInject (M1 C c f) where-    genericInjectWith options = do-        res <- genericInjectWith options-        pure (contramap unM1 res)--instance (Constructor c1, Constructor c2, GenericInject f1, GenericInject f2) => GenericInject (M1 C c1 f1 :+: M1 C c2 f2) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 (M1 l)) =-            UnionLit keyL (embedL l) Data.HashMap.Strict.InsOrd.empty--        embed (R1 (M1 r)) =-            UnionLit keyR (embedR r) Data.HashMap.Strict.InsOrd.empty--        declared =-            Union (Data.HashMap.Strict.InsOrd.fromList [(keyL, declaredL), (keyR, declaredR)])--        nL :: M1 i c1 f1 a-        nL = undefined--        nR :: M1 i c2 f2 a-        nR = undefined--        keyL = constructorModifier (Data.Text.Lazy.pack (conName nL))-        keyR = constructorModifier (Data.Text.Lazy.pack (conName nR))--        InputType embedL declaredL = evalState (genericInjectWith options) 1-        InputType embedR declaredR = evalState (genericInjectWith options) 1--instance (Constructor c, GenericInject (f :+: g), GenericInject h) => GenericInject ((f :+: g) :+: M1 C c h) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 l) =-            UnionLit keyL valL (Data.HashMap.Strict.InsOrd.insert keyR declaredR ktsL')-          where-            UnionLit keyL valL ktsL' = embedL l-        embed (R1 (M1 r)) = UnionLit keyR (embedR r) ktsL--        nR :: M1 i c h a-        nR = undefined--        keyR = constructorModifier (Data.Text.Lazy.pack (conName nR))--        declared = Union (Data.HashMap.Strict.InsOrd.insert keyR declaredR ktsL)--        InputType embedL (Union ktsL) = evalState (genericInjectWith options) 1-        InputType embedR  declaredR   = evalState (genericInjectWith options) 1--instance (Constructor c, GenericInject f, GenericInject (g :+: h)) => GenericInject (M1 C c f :+: (g :+: h)) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 (M1 l)) = UnionLit keyL (embedL l) ktsR-        embed (R1 r) =-            UnionLit keyR valR (Data.HashMap.Strict.InsOrd.insert keyL declaredL ktsR')-          where-            UnionLit keyR valR ktsR' = embedR r--        nL :: M1 i c f a-        nL = undefined--        keyL = constructorModifier (Data.Text.Lazy.pack (conName nL))--        declared = Union (Data.HashMap.Strict.InsOrd.insert keyL declaredL ktsR)--        InputType embedL  declaredL   = evalState (genericInjectWith options) 1-        InputType embedR (Union ktsR) = evalState (genericInjectWith options) 1--instance (GenericInject (f :+: g), GenericInject (h :+: i)) => GenericInject ((f :+: g) :+: (h :+: i)) where-    genericInjectWith options = pure (InputType {..})-      where-        embed (L1 l) =-            UnionLit keyL valR (Data.HashMap.Strict.InsOrd.union ktsL' ktsR)-          where-            UnionLit keyL valR ktsL' = embedL l-        embed (R1 r) =-            UnionLit keyR valR (Data.HashMap.Strict.InsOrd.union ktsL ktsR')-          where-            UnionLit keyR valR ktsR' = embedR r--        declared = Union (Data.HashMap.Strict.InsOrd.union ktsL ktsR)--        InputType embedL (Union ktsL) = evalState (genericInjectWith options) 1-        InputType embedR (Union ktsR) = evalState (genericInjectWith options) 1--instance (GenericInject f, GenericInject g) => GenericInject (f :*: g) where-    genericInjectWith options = do-        InputType embedInL declaredInL <- genericInjectWith options-        InputType embedInR declaredInR <- genericInjectWith options--        let embed (l :*: r) =-                RecordLit (Data.HashMap.Strict.InsOrd.union mapL mapR)-              where-                RecordLit mapL = embedInL l-                RecordLit mapR = embedInR r--        let declared = Record (Data.HashMap.Strict.InsOrd.union mapL mapR)-              where-                Record mapL = declaredInL-                Record mapR = declaredInR--        pure (InputType {..})--instance GenericInject U1 where-    genericInjectWith _ = pure (InputType {..})-      where-        embed _ = RecordLit Data.HashMap.Strict.InsOrd.empty--        declared = Record Data.HashMap.Strict.InsOrd.empty--instance (Selector s, Inject a) => GenericInject (M1 S s (K1 i a)) where-    genericInjectWith opts@(InterpretOptions {..}) = do-        name <- fieldModifier . Data.Text.Lazy.pack <$> getSelName n-        let embed (M1 (K1 x)) =-                RecordLit (Data.HashMap.Strict.InsOrd.singleton name (embedIn x))-        let declared =-                Record (Data.HashMap.Strict.InsOrd.singleton name declaredIn)-        pure (InputType {..})-      where-        n :: M1 i s f a-        n = undefined--        InputType embedIn declaredIn = injectWith opts+{-# LANGUAGE ApplicativeDo         #-}+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE UndecidableInstances  #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall+    (+    -- * Input+      input+    , inputWithSettings+    , inputFile+    , inputFileWithSettings+    , inputExpr+    , inputExprWithSettings+    , interpretExpr+    , interpretExprWithSettings+    , fromExpr+    , fromExprWithSettings+    , rootDirectory+    , sourceName+    , startingContext+    , substitutions+    , normalizer+    , newManager+    , defaultInputSettings+    , InputSettings+    , defaultEvaluateSettings+    , EvaluateSettings+    , HasEvaluateSettings(..)+    , detailed++    -- * Decoders+    , module Dhall.Marshal.Decode++    -- * Encoders+    , module Dhall.Marshal.Encode++    -- * Individual phases+    , parseWithSettings+    , resolveWithSettings+    , resolveAndStatusWithSettings+    , typecheckWithSettings+    , checkWithSettings+    , expectWithSettings+    , normalizeWithSettings++    -- * Miscellaneous+    , rawInput+    ) where++import Control.Applicative    (Alternative, empty)+import Control.Monad.Catch    (MonadThrow, throwM)+import Data.Either.Validation (Validation (..))+import Data.Void              (Void)+import Dhall.Import           (Imported (..), Status)+import Dhall.Parser           (Src (..))+import Dhall.Syntax           (Expr (..), Import)+import Dhall.TypeCheck        (DetailedTypeError (..), TypeError)+import GHC.Generics+import Lens.Micro             (Lens', lens)+import Lens.Micro.Extras      (view)+import Prelude                hiding (maybe, sequence)+import System.FilePath        (takeDirectory)++import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Text.IO+import qualified Dhall.Context+import qualified Dhall.Core                       as Core+import qualified Dhall.Import+import qualified Dhall.Parser+import qualified Dhall.Pretty.Internal+import qualified Dhall.Substitution+import qualified Dhall.TypeCheck+import qualified Lens.Micro                       as Lens++import Dhall.Marshal.Decode+import Dhall.Marshal.Encode++-- | @since 1.16+data InputSettings = InputSettings+  { _rootDirectory :: FilePath+  , _sourceName :: FilePath+  , _evaluateSettings :: EvaluateSettings+  }++-- | Default input settings: resolves imports relative to @.@ (the+-- current working directory), report errors as coming from @(input)@,+-- and default evaluation settings from 'defaultEvaluateSettings'.+--+-- @since 1.16+defaultInputSettings :: InputSettings+defaultInputSettings = InputSettings+  { _rootDirectory = "."+  , _sourceName = "(input)"+  , _evaluateSettings = defaultEvaluateSettings+  }+++-- | Access the directory to resolve imports relative to.+--+-- @since 1.16+rootDirectory :: Lens' InputSettings FilePath+rootDirectory = lens _rootDirectory (\s x -> s { _rootDirectory = x })++-- | Access the name of the source to report locations from; this is+-- only used in error messages, so it's okay if this is a best guess+-- or something symbolic.+--+-- @since 1.16+sourceName :: Lens' InputSettings FilePath+sourceName = lens _sourceName (\s x -> s { _sourceName = x})++-- | @since 1.16+data EvaluateSettings = EvaluateSettings+  { _substitutions   :: Dhall.Substitution.Substitutions Src Void+  , _startingContext :: Dhall.Context.Context (Expr Src Void)+  , _normalizer      :: Maybe (Core.ReifiedNormalizer Void)+  , _newManager      :: IO Dhall.Import.Manager+  }++-- | Default evaluation settings: no extra entries in the initial+-- context, and no special normalizer behaviour.+--+-- @since 1.16+defaultEvaluateSettings :: EvaluateSettings+defaultEvaluateSettings = EvaluateSettings+  { _substitutions   = Dhall.Substitution.empty+  , _startingContext = Dhall.Context.empty+  , _normalizer      = Nothing+  , _newManager      = Dhall.Import.defaultNewManager+  }++-- | Access the starting context used for evaluation and type-checking.+--+-- @since 1.16+startingContext+  :: (HasEvaluateSettings s)+  => Lens' s (Dhall.Context.Context (Expr Src Void))+startingContext =+    evaluateSettings+        . lens _startingContext (\s x -> s { _startingContext = x})++-- | Access the custom substitutions.+--+-- @since 1.30+substitutions+  :: (HasEvaluateSettings s)+  => Lens' s (Dhall.Substitution.Substitutions Src Void)+substitutions =+    evaluateSettings+        . lens _substitutions (\s x -> s { _substitutions = x })++-- | Access the custom normalizer.+--+-- @since 1.16+normalizer+  :: (HasEvaluateSettings s)+  => Lens' s (Maybe (Core.ReifiedNormalizer Void))+normalizer =+    evaluateSettings+        . lens _normalizer (\s x -> s { _normalizer = x })++-- | Access the HTTP manager initializer.+--+-- @since 1.36+newManager+  :: (HasEvaluateSettings s)+  => Lens' s (IO Dhall.Import.Manager)+newManager =+    evaluateSettings+        . lens _newManager (\s x -> s { _newManager = x })++-- | @since 1.16+class HasEvaluateSettings s where+  evaluateSettings :: Lens' s EvaluateSettings++instance HasEvaluateSettings InputSettings where+  evaluateSettings =+    lens _evaluateSettings (\s x -> s { _evaluateSettings = x })++instance HasEvaluateSettings EvaluateSettings where+  evaluateSettings = id++-- | Parse an expression, using the supplied `InputSettings`+parseWithSettings :: MonadThrow m => InputSettings -> Text -> m (Expr Src Import)+parseWithSettings settings text =+    either throwM return (Dhall.Parser.exprFromText (view sourceName settings) text)++-- | Type-check an expression, using the supplied `InputSettings`+typecheckWithSettings :: MonadThrow m => InputSettings -> Expr Src Void -> m ()+typecheckWithSettings settings expression =+    either throwM (return . const ()) (Dhall.TypeCheck.typeWith (view startingContext settings) expression)++{-| Type-check an expression against a type provided as a Dhall expreession,+    using the supplied `InputSettings`+-}+checkWithSettings ::+    MonadThrow m =>+    -- | The input settings+    InputSettings ->+    -- | The expected type of the expression+    Expr Src Void ->+    -- | The expression to check+    Expr Src Void ->+    m ()+checkWithSettings settings type_ expression = do+    let suffix = Dhall.Pretty.Internal.prettyToStrictText type_++    let annotated = case expression of+            Note (Src begin end bytes) _ ->+                Note (Src begin end bytes') (Annot expression type_)+              where+                bytes' = bytes <> " : " <> suffix+            _ ->+                Annot expression type_++    typecheckWithSettings settings annotated++{-| Type-check an expression against a `Decoder`'s expected type, using the+    supplied `InputSettings`.+    This is equivalent of using the 'expected' type of a @Decoder@ as the second+    argument to 'checkWithSettings'.+-}+expectWithSettings :: MonadThrow m => InputSettings -> Decoder a -> Expr Src Void -> m ()+expectWithSettings settings Decoder{..} expression = do+    expected' <- case expected of+        Success x -> return x+        Failure e -> throwM e++    checkWithSettings settings expected' expression++{-| Resolve an expression, using the supplied `InputSettings`++    Note that this also applies any substitutions specified in the+    `InputSettings`+-}+resolveWithSettings :: InputSettings -> Expr Src Import -> IO (Expr Src Void)+resolveWithSettings settings expression =+    fst <$> resolveAndStatusWithSettings settings expression++-- | A version of 'resolveWithSettings' that also returns the import 'Status'+-- together with the resolved expression.+resolveAndStatusWithSettings+    :: InputSettings+    -> Expr Src Import+    -> IO (Expr Src Void, Status)+resolveAndStatusWithSettings settings expression = do+    let InputSettings{..} = settings++    let EvaluateSettings{..} = _evaluateSettings++    let transform =+               Lens.set Dhall.Import.substitutions   _substitutions+            .  Lens.set Dhall.Import.normalizer      _normalizer+            .  Lens.set Dhall.Import.startingContext _startingContext++    let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)++    (resolved, status') <- State.runStateT (Dhall.Import.loadWith expression) status++    let substituted = Dhall.Substitution.substitute resolved (view substitutions settings)++    pure (substituted, status')++-- | Normalize an expression, using the supplied `InputSettings`+normalizeWithSettings :: InputSettings -> Expr Src Void -> Expr Src Void+normalizeWithSettings settings =+    Core.normalizeWith (view normalizer settings)++{-| Type-check and evaluate a Dhall program, decoding the result into Haskell++    The first argument determines the type of value that you decode:++>>> input integer "+2"+2+>>> input (vector double) "[1.0, 2.0]"+[1.0,2.0]++    Use `auto` to automatically select which type to decode based on the+    inferred return type:++>>> input auto "True" :: IO Bool+True++    This uses the settings from 'defaultInputSettings'.+-}+input+    :: Decoder a+    -- ^ The decoder for the Dhall value+    -> Text+    -- ^ The Dhall program+    -> IO a+    -- ^ The decoded value in Haskell+input =+  inputWithSettings defaultInputSettings++{-| Extend 'input' with a root directory to resolve imports relative+    to, a file to mention in errors as the source, a custom typing+    context, and a custom normalization process.++@since 1.16+-}+inputWithSettings+    :: InputSettings+    -> Decoder a+    -- ^ The decoder for the Dhall value+    -> Text+    -- ^ The Dhall program+    -> IO a+    -- ^ The decoded value in Haskell+inputWithSettings settings decoder@Decoder{..} text = do+    parsed <- parseWithSettings settings text++    resolved <- resolveWithSettings settings parsed++    expectWithSettings settings decoder resolved++    let normalized = normalizeWithSettings settings resolved++    case extract normalized of+        Success x -> return x+        Failure e -> Control.Exception.throwIO e++{-| Type-check and evaluate a Dhall program that is read from the+    file-system.++    This uses the settings from 'defaultEvaluateSettings'.++    @since 1.16+-}+inputFile+  :: Decoder a+  -- ^ The decoder for the Dhall value+  -> FilePath+  -- ^ The path to the Dhall program.+  -> IO a+  -- ^ The decoded value in Haskell.+inputFile =+  inputFileWithSettings defaultEvaluateSettings++{-| Extend 'inputFile' with a custom typing context and a custom+    normalization process.++@since 1.16+-}+inputFileWithSettings+  :: EvaluateSettings+  -> Decoder a+  -- ^ The decoder for the Dhall value+  -> FilePath+  -- ^ The path to the Dhall program.+  -> IO a+  -- ^ The decoded value in Haskell.+inputFileWithSettings settings ty path = do+  text <- Data.Text.IO.readFile path+  let inputSettings = InputSettings+        { _rootDirectory = takeDirectory path+        , _sourceName = path+        , _evaluateSettings = settings+        }+  inputWithSettings inputSettings ty text++{-| Similar to `input`, but without interpreting the Dhall `Expr` into a Haskell+    type.++    Uses the settings from 'defaultInputSettings'.+-}+inputExpr+    :: Text+    -- ^ The Dhall program+    -> IO (Expr Src Void)+    -- ^ The fully normalized AST+inputExpr =+  inputExprWithSettings defaultInputSettings++{-| Extend 'inputExpr' with a root directory to resolve imports relative+    to, a file to mention in errors as the source, a custom typing+    context, and a custom normalization process.++@since 1.16+-}+inputExprWithSettings+    :: InputSettings+    -> Text+    -- ^ The Dhall program+    -> IO (Expr Src Void)+    -- ^ The fully normalized AST+inputExprWithSettings settings text = do+    parsed <- parseWithSettings settings text++    resolved <- resolveWithSettings settings parsed++    _ <- typecheckWithSettings settings resolved++    pure (Core.normalizeWith (view normalizer settings) resolved)++{-| Interpret a Dhall Expression++    This takes care of import resolution, type-checking, and normalization+-}+interpretExpr :: Expr Src Import -> IO (Expr Src Void)+interpretExpr = interpretExprWithSettings defaultInputSettings++-- | Like `interpretExpr`, but customizable using `InputSettings`+interpretExprWithSettings+    :: InputSettings -> Expr Src Import -> IO (Expr Src Void)+interpretExprWithSettings settings parsed = do+    resolved <- resolveWithSettings settings parsed++    typecheckWithSettings settings resolved++    pure (Core.normalizeWith (view normalizer settings) resolved)++{- | Decode a Dhall expression++    This takes care of import resolution, type-checking and normalization+-}+fromExpr :: Decoder a -> Expr Src Import -> IO a+fromExpr = fromExprWithSettings defaultInputSettings++-- | Like `fromExpr`, but customizable using `InputSettings`+fromExprWithSettings :: InputSettings -> Decoder a -> Expr Src Import -> IO a+fromExprWithSettings settings decoder@Decoder{..} expression = do+    resolved <- resolveWithSettings settings expression++    expectWithSettings settings decoder resolved++    let normalized = Core.normalizeWith (view normalizer settings) resolved++    case extract normalized of+        Success x -> return x+        Failure e -> Control.Exception.throwIO e++-- | Use this function to extract Haskell values directly from Dhall AST.+--   The intended use case is to allow easy extraction of Dhall values for+--   making the function `Core.normalizeWith` easier to use.+--+--   For other use cases, use `input` from "Dhall" module. It will give you+--   a much better user experience.+rawInput+    :: Alternative f+    => Decoder a+    -- ^ The decoder for the Dhall value+    -> Expr s Void+    -- ^ a closed form Dhall program, which evaluates to the expected type+    -> f a+    -- ^ The decoded value in Haskell+rawInput (Decoder {..}) expr =+    case extract (Core.normalize expr) of+        Success x  -> pure x+        Failure _e -> empty++{-| Use this to provide more detailed error messages++>> input auto "True" :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> True : Integer+>+> (input):1:1++>> detailed (input auto "True") :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> Explanation: You can annotate an expression with its type or kind using the+> ❰:❱ symbol, like this:+>+>+>     ┌───────┐+>     │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱+>     └───────┘+>+> The type checker verifies that the expression's type or kind matches the+> provided annotation+>+> For example, all of the following are valid annotations that the type checker+> accepts:+>+>+>     ┌─────────────┐+>     │ 1 : Natural │  ❰1❱ is an expression that has type ❰Natural❱, so the type+>     └─────────────┘  checker accepts the annotation+>+>+>     ┌───────────────────────┐+>     │ Natural/even 2 : Bool │  ❰Natural/even 2❱ has type ❰Bool❱, so the type+>     └───────────────────────┘  checker accepts the annotation+>+>+>     ┌────────────────────┐+>     │ List : Type → Type │  ❰List❱ is an expression that has kind ❰Type → Type❱,+>     └────────────────────┘  so the type checker accepts the annotation+>+>+>     ┌──────────────────┐+>     │ List Text : Type │  ❰List Text❱ is an expression that has kind ❰Type❱, so+>     └──────────────────┘  the type checker accepts the annotation+>+>+> However, the following annotations are not valid and the type checker will+> reject them:+>+>+>     ┌──────────┐+>     │ 1 : Text │  The type checker rejects this because ❰1❱ does not have type+>     └──────────┘  ❰Text❱+>+>+>     ┌─────────────┐+>     │ List : Type │  ❰List❱ does not have kind ❰Type❱+>     └─────────────┘+>+>+> You or the interpreter annotated this expression:+>+> ↳ True+>+> ... with this type or kind:+>+> ↳ Integer+>+> ... but the inferred type or kind of the expression is actually:+>+> ↳ Bool+>+> Some common reasons why you might get this error:+>+> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation+>   matching the expected type+>+>   For example, if you run the following Haskell code:+>+>+>     ┌───────────────────────────────┐+>     │ >>> input auto "1" :: IO Text │+>     └───────────────────────────────┘+>+>+>   ... then the interpreter will actually type check the following annotated+>   expression:+>+>+>     ┌──────────┐+>     │ 1 : Text │+>     └──────────┘+>+>+>   ... and then type-checking will fail+>+> ────────────────────────────────────────────────────────────────────────────────+>+> True : Integer+>+> (input):1:1++-}+detailed :: IO a -> IO a+detailed =+    Control.Exception.handle handler1 . Control.Exception.handle handler0+  where+    handler0 :: Imported (TypeError Src Void) -> IO a+    handler0 (Imported ps e) =+        Control.Exception.throwIO (Imported ps (DetailedTypeError e))++    handler1 :: TypeError Src Void -> IO a+    handler1 e = Control.Exception.throwIO (DetailedTypeError e)
+ src/Dhall/Binary.hs view
@@ -0,0 +1,1437 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++{-| This module contains logic for converting Dhall expressions to and from+    CBOR expressions which can in turn be converted to and from a binary+    representation+-}++module Dhall.Binary+    ( -- * Encoding and decoding+      encodeExpression+    , decodeExpression++      -- * Exceptions+    , DecodingFailure(..)+    ) where++import Codec.CBOR.Decoding  (Decoder, TokenType (..))+import Codec.CBOR.Encoding  (Encoding)+import Codec.Serialise      (Serialise (decode, encode))+import Control.Applicative  (empty, (<|>))+import Control.Exception    (Exception)+import Data.ByteString.Lazy (ByteString)+import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , FunctionBinding (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , MultiLet (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Scheme (..)+    , URL (..)+    , Var (..)+    , WithComponent (..)+    )++import Data.Foldable (toList)+import Data.Ratio    ((%))+import Data.Void     (Void, absurd)+import GHC.Float     (double2Float, float2Double)+import Numeric.Half  (fromHalf, toHalf)+import Prelude       hiding (exponent)++import qualified Codec.CBOR.ByteArray+import qualified Codec.CBOR.Decoding   as Decoding+import qualified Codec.CBOR.Encoding   as Encoding+import qualified Codec.CBOR.Read       as Read+import qualified Codec.Serialise       as Serialise+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Foldable         as Foldable+import qualified Data.List.NonEmpty    as NonEmpty+import qualified Data.Sequence+import qualified Data.Time             as Time+import qualified Dhall.Crypto+import qualified Dhall.Map+import qualified Dhall.Syntax          as Syntax+import qualified Text.Printf           as Printf++{-| Convert a function applied to multiple arguments to the base function and+    the list of arguments+-}+unApply :: Expr s a -> (Expr s a, [Expr s a])+unApply e₀ = (baseFunction₀, diffArguments₀ [])+  where+    ~(baseFunction₀, diffArguments₀) = go e₀++    go (App f a) = (baseFunction, diffArguments . (a :))+      where+        ~(baseFunction, diffArguments) = go f++    go (Note _ e) = go e++    go baseFunction = (baseFunction, id)++decodeExpressionInternal :: (Int -> Decoder s a) -> Decoder s (Expr t a)+decodeExpressionInternal decodeEmbed = go+  where+    go = do+        let die message = fail ("Dhall.Binary.decodeExpressionInternal: " <> message)++        tokenType₀ <- Decoding.peekTokenType++        case tokenType₀ of+            TypeUInt -> do+                !n <- fromIntegral <$> Decoding.decodeWord++                return (Var (V "_" n))++            TypeUInt64 -> do+                !n <- fromIntegral <$> Decoding.decodeWord64++                return (Var (V "_" n))++            TypeFloat16 -> do+                !n <- float2Double <$> Decoding.decodeFloat++                return (DoubleLit (DhallDouble n))++            TypeFloat32 -> do+                !n <- float2Double <$> Decoding.decodeFloat++                return (DoubleLit (DhallDouble n))++            TypeFloat64 -> do+                !n <- Decoding.decodeDouble++                return (DoubleLit (DhallDouble n))++            TypeBool -> do+                !b <- Decoding.decodeBool++                return (BoolLit b)++            TypeString -> do+                !ba <- Decoding.decodeUtf8ByteArray++                let sb = Codec.CBOR.ByteArray.toShortByteString ba++                case Data.ByteString.Short.length sb of+                    4  | sb == "Bool"              -> return Bool+                       | sb == "Date"              -> return Date+                       | sb == "List"              -> return List+                       | sb == "None"              -> return None+                       | sb == "Text"              -> return Text+                       | sb == "Time"              -> return Time+                       | sb == "Type"              -> return (Const Type)+                       | sb == "Kind"              -> return (Const Kind)+                       | sb == "Sort"              -> return (Const Sort)+                    5  | sb == "Bytes"             -> return Bytes+                    6  | sb == "Double"            -> return Double+                    7  | sb == "Integer"           -> return Integer+                       | sb == "Natural"           -> return Natural+                    8  | sb == "Optional"          -> return Optional+                       | sb == "TimeZone"          -> return TimeZone+                    9  | sb == "Date/show"         -> return DateShow+                       | sb == "List/fold"         -> return ListFold+                       | sb == "List/head"         -> return ListHead+                       | sb == "List/last"         -> return ListLast+                       | sb == "Text/show"         -> return TextShow+                       | sb == "Time/show"         -> return TimeShow+                    10 | sb == "List/build"        -> return ListBuild+                    11 | sb == "Double/show"       -> return DoubleShow+                       | sb == "List/length"       -> return ListLength+                       | sb == "Natural/odd"       -> return NaturalOdd+                    12 | sb == "Integer/show"      -> return IntegerShow+                       | sb == "List/indexed"      -> return ListIndexed+                       | sb == "List/reverse"      -> return ListReverse+                       | sb == "Natural/even"      -> return NaturalEven+                       | sb == "Natural/fold"      -> return NaturalFold+                       | sb == "Natural/show"      -> return NaturalShow+                       | sb == "Text/replace"      -> return TextReplace+                    13 | sb == "Integer/clamp"     -> return IntegerClamp+                       | sb == "Natural/build"     -> return NaturalBuild+                       | sb == "TimeZone/show"     -> return TimeZoneShow+                    14 | sb == "Integer/negate"    -> return IntegerNegate+                       | sb == "Natural/isZero"    -> return NaturalIsZero+                    16 | sb == "Integer/toDouble"  -> return IntegerToDouble+                       | sb == "Natural/subtract"  -> return NaturalSubtract+                    17 | sb == "Natural/toInteger" -> return NaturalToInteger+                    _                              -> die ("Unrecognized built-in: " <> show sb)++            TypeListLen -> do+                len <- Decoding.decodeListLen++                case len of+                    0 -> die "Missing tag"+                    _ -> return ()++                tokenType₁ <- Decoding.peekTokenType++                case tokenType₁ of+                    TypeString -> do+                        x <- Decoding.decodeString++                        if x == "_"+                            then die "Non-standard encoding of an α-normalized variable"+                            else return ()++                        tokenType₂ <- Decoding.peekTokenType++                        case tokenType₂ of+                            TypeUInt -> do+                                !n <- fromIntegral <$> Decoding.decodeWord++                                return (Var (V x n))++                            TypeUInt64 -> do+                                !n <- fromIntegral <$> Decoding.decodeWord64++                                return (Var (V x n))++                            _ ->+                                die ("Unexpected token type for variable index: " <> show tokenType₂)++                    TypeUInt -> do+                        tag <- Decoding.decodeWord++                        case tag of+                            0 -> do+                                !f <- go++                                let loop n !acc+                                        | n <= 0    = return acc+                                        | otherwise = do+                                              !x <- go+                                              loop (n - 1) (App acc x)++                                let nArgs = len - 2++                                if nArgs <= 0+                                    then die "Non-standard encoding of a function with no arguments"+                                    else loop nArgs f++                            1 ->+                                case len of+                                    3 -> do+                                        _A <- go++                                        b <- go++                                        return (Lam mempty (Syntax.makeFunctionBinding "_" _A) b)++                                    4 -> do+                                        x <- Decoding.decodeString++                                        if x == "_"+                                            then die "Non-standard encoding of a λ expression"+                                            else return ()++                                        _A <- go++                                        b <- go++                                        return (Lam mempty (Syntax.makeFunctionBinding x _A) b)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a λ expression: " <> show len)++                            2 ->+                                case len of+                                    3 -> do+                                        _A <- go++                                        _B <- go++                                        return (Pi mempty "_" _A _B)++                                    4 -> do+                                        x <- Decoding.decodeString++                                        if x == "_"+                                            then die "Non-standard encoding of a ∀ expression"+                                            else return ()++                                        _A <- go++                                        _B <- go++                                        return (Pi mempty x _A _B)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a ∀ expression: " <> show len)++                            3 -> do+                                opcode <- Decoding.decodeWord++                                op <- case opcode of+                                    0  -> return BoolOr+                                    1  -> return BoolAnd+                                    2  -> return BoolEQ+                                    3  -> return BoolNE+                                    4  -> return NaturalPlus+                                    5  -> return NaturalTimes+                                    6  -> return TextAppend+                                    7  -> return ListAppend+                                    8  -> return (Combine mempty Nothing)+                                    9  -> return (Prefer mempty PreferFromSource)+                                    10 -> return (CombineTypes mempty)+                                    11 -> return ImportAlt+                                    12 -> return (Equivalent mempty)+                                    13 -> return RecordCompletion+                                    _  -> die ("Unrecognized operator code: " <> show opcode)++                                l <- go++                                r <- go++                                return (op l r)++                            4 ->+                                case len of+                                    2 -> do+                                        _T <- go++                                        return (ListLit (Just (App List _T)) empty)++                                    _ -> do+                                        Decoding.decodeNull++                                        xs <- Data.Sequence.replicateA (len - 2) go+                                        return (ListLit Nothing xs)++                            5 -> do+                                Decoding.decodeNull++                                t <- go++                                return (Some t)++                            6 -> do+                                t <- go++                                u <- go++                                case len of+                                    3 ->+                                        return (Merge t u Nothing)++                                    4 -> do+                                        _T <- go++                                        return (Merge t u (Just _T))++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a `merge` expression: " <> show len)++                            7 -> do+                                mapLength <- Decoding.decodeMapLen++                                xTs <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    _T <- go++                                    return (x, Syntax.makeRecordField _T)++                                return (Record (Dhall.Map.fromList xTs))++                            8 -> do+                                mapLength <- Decoding.decodeMapLen++                                xts <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    t <- go++                                    return (x, Syntax.makeRecordField t)++                                return (RecordLit (Dhall.Map.fromList xts))++                            9 -> do+                                t <- go++                                x <- Decoding.decodeString++                                return (Field t (Syntax.makeFieldSelection x))++                            10 -> do+                                t <- go++                                xs <- case len of+                                    3 -> do+                                        tokenType₂ <- Decoding.peekTokenType++                                        case tokenType₂ of+                                            TypeListLen -> do+                                                _ <- Decoding.decodeListLen++                                                _T <- go++                                                return (Right _T)++                                            TypeString -> do+                                                x <- Decoding.decodeString+                                                return (Left [x])++                                            _ ->+                                                die ("Unexpected token type for projection: " <> show tokenType₂)++                                    _ -> do+                                        xs <- replicateDecoder (len - 2) Decoding.decodeString++                                        return (Left xs)++                                return (Project t xs)++                            11 -> do+                                mapLength <- Decoding.decodeMapLen++                                xTs <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    tokenType₂ <- Decoding.peekTokenType++                                    mT <- case tokenType₂ of+                                        TypeNull -> do+                                            Decoding.decodeNull++                                            return Nothing++                                        _ -> do+                                            _T <- go++                                            return (Just _T)++                                    return (x, mT)++                                return (Union (Dhall.Map.fromList xTs))++                            14 -> do+                                t <- go++                                l <- go++                                r <- go++                                return (BoolIf t l r)++                            15 -> do+                                tokenType₂ <- Decoding.peekTokenType++                                case tokenType₂ of+                                    TypeUInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord++                                        return (NaturalLit n)++                                    TypeUInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord64++                                        return (NaturalLit n)++                                    TypeInteger -> do+                                        !n <- fromIntegral <$> Decoding.decodeInteger+                                        return (NaturalLit n)++                                    _ ->+                                        die ("Unexpected token type for Natural literal: " <> show tokenType₂)++                            16 -> do+                                tokenType₂ <- Decoding.peekTokenType++                                case tokenType₂ of+                                    TypeUInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord++                                        return (IntegerLit n)++                                    TypeUInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord64++                                        return (IntegerLit n)++                                    TypeNInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeNegWord++                                        return (IntegerLit $! (-1 - n))++                                    TypeNInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeNegWord64++                                        return (IntegerLit $! (-1 - n))+                                    TypeInteger -> do+                                        n <- Decoding.decodeInteger+                                        return (IntegerLit n)++                                    _ ->+                                        die ("Unexpected token type for Integer literal: " <> show tokenType₂)++                            18 -> do+                                xys <- replicateDecoder ((len - 2) `quot` 2) $ do+                                    x <- Decoding.decodeString++                                    y <- go++                                    return (x, y)++                                z <- Decoding.decodeString++                                return (TextLit (Chunks xys z))++                            19 -> do+                                t <- go++                                return (Assert t)++                            24 ->+                                fmap Embed (decodeEmbed len)++                            25 -> do+                                bindings <- replicateDecoder ((len - 2) `quot` 3) $ do+                                    x <- Decoding.decodeString++                                    tokenType₂ <- Decoding.peekTokenType++                                    mA <- case tokenType₂ of+                                        TypeNull -> do+                                            Decoding.decodeNull++                                            return Nothing++                                        _ -> do+                                            _A <- go++                                            return (Just (Nothing, _A))++                                    a <- go++                                    return (Binding Nothing x Nothing mA Nothing a)++                                b <- go++                                return (foldr Let b bindings)++                            26 -> do+                                t <- go++                                _T <- go++                                return (Annot t _T)++                            27 -> do+                                t <- go++                                mT <- case len of+                                    2 ->+                                        return Nothing++                                    3 -> do+                                        _T <- go++                                        return (Just _T)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a type annotation: " <> show len)++                                return (ToMap t mT)++                            28 -> do+                                _T <- go++                                return (ListLit (Just _T) empty)++                            29 -> do+                                l <- go++                                n <- Decoding.decodeListLen++                                let decodeWithComponent = do+                                        tokenType₂ <- Decoding.peekTokenType+                                        case tokenType₂ of+                                            TypeString -> do+                                                fmap WithLabel Decoding.decodeString+                                            _ -> do+                                                m <- Decoding.decodeInt++                                                case m of+                                                    0 -> return WithQuestion+                                                    _ -> die ("Unexpected integer encoding a with expression: " <> show n)+                                ks₀ <- replicateDecoder n decodeWithComponent++                                ks₁ <- case NonEmpty.nonEmpty ks₀ of+                                    Nothing ->+                                        die "0 field labels in decoded with expression"+                                    Just ks₁ ->+                                        return ks₁++                                r <- go++                                return (With l ks₁ r)++                            30 -> do+                                _YYYY <- Decoding.decodeInt+                                _MM   <- Decoding.decodeInt+                                _HH   <- Decoding.decodeInt++                                case Time.fromGregorianValid (fromIntegral _YYYY) _MM _HH of+                                    Nothing ->+                                        die "Invalid date"+                                    Just day ->+                                        return (DateLiteral day)+                            31 -> do+                                hh <- Decoding.decodeInt+                                mm <- Decoding.decodeInt+                                tag₂ <- Decoding.decodeTag++                                case tag₂ of+                                    4 -> do+                                        return ()+                                    _ -> do+                                        die ("Unexpected tag for decimal fraction: " <> show tag)+                                n <- Decoding.decodeListLen++                                case n of+                                    2 -> do+                                        return ()+                                    _ -> do+                                        die ("Invalid list length for decimal fraction: " <> show n)++                                exponent <- Decoding.decodeInt++                                tokenType₂ <- Decoding.peekTokenType++                                mantissa <- case tokenType₂ of+                                    TypeUInt -> do+                                        fromIntegral <$> Decoding.decodeWord++                                    TypeUInt64 -> do+                                        fromIntegral <$> Decoding.decodeWord64++                                    TypeNInt -> do+                                        !i <- fromIntegral <$> Decoding.decodeNegWord++                                        return (-1 - i)++                                    TypeNInt64 -> do+                                        !i <- fromIntegral <$> Decoding.decodeNegWord64++                                        return (-1 - i)+                                    TypeInteger -> do+                                        Decoding.decodeInteger+                                    _ ->+                                        die ("Unexpected token type for mantissa: " <> show tokenType₂)+                                let precision = fromIntegral (negate exponent)++                                let ss = fromRational (mantissa % (10 ^ precision))++                                return (TimeLiteral (Time.TimeOfDay hh mm ss) precision)+                            32 -> do+                                b   <- Decoding.decodeBool+                                _HH <- Decoding.decodeInt+                                _MM <- Decoding.decodeInt++                                let sign = if b then id else negate++                                let minutes = sign (_HH * 60 + _MM)++                                return (TimeZoneLiteral (Time.TimeZone minutes False ""))++                            33 -> do+                                b <- Decoding.decodeBytes++                                return (BytesLit b)++                            34 -> do+                                t <- go+                                return (ShowConstructor t)+                            _ ->+                                die ("Unexpected tag: " <> show tag)++                    _ ->+                        die ("Unexpected tag type: " <> show tokenType₁)++            _ ->+                die ("Unexpected initial token: " <> show tokenType₀)++encodeExpressionInternal :: (a -> Encoding) -> Expr Void a -> Encoding+encodeExpressionInternal encodeEmbed = go+  where+    go e = case e of+        Var (V "_" n) ->+            Encoding.encodeInt n++        Var (V x n) ->+                Encoding.encodeListLen 2+            <>  Encoding.encodeString x+            <>  Encoding.encodeInt n++        NaturalBuild ->+            Encoding.encodeUtf8ByteArray "Natural/build"++        NaturalFold ->+            Encoding.encodeUtf8ByteArray "Natural/fold"++        NaturalIsZero ->+            Encoding.encodeUtf8ByteArray "Natural/isZero"++        NaturalEven ->+            Encoding.encodeUtf8ByteArray "Natural/even"++        NaturalOdd ->+            Encoding.encodeUtf8ByteArray "Natural/odd"++        NaturalToInteger ->+            Encoding.encodeUtf8ByteArray "Natural/toInteger"++        NaturalShow ->+            Encoding.encodeUtf8ByteArray "Natural/show"++        NaturalSubtract ->+            Encoding.encodeUtf8ByteArray "Natural/subtract"++        IntegerToDouble ->+            Encoding.encodeUtf8ByteArray "Integer/toDouble"++        IntegerClamp ->+            Encoding.encodeUtf8ByteArray "Integer/clamp"++        IntegerNegate ->+            Encoding.encodeUtf8ByteArray "Integer/negate"++        IntegerShow ->+            Encoding.encodeUtf8ByteArray "Integer/show"++        DoubleShow ->+            Encoding.encodeUtf8ByteArray "Double/show"++        ListBuild ->+            Encoding.encodeUtf8ByteArray "List/build"++        ListFold ->+            Encoding.encodeUtf8ByteArray "List/fold"++        ListLength ->+            Encoding.encodeUtf8ByteArray "List/length"++        ListHead ->+            Encoding.encodeUtf8ByteArray "List/head"++        ListLast ->+            Encoding.encodeUtf8ByteArray "List/last"++        ListIndexed ->+            Encoding.encodeUtf8ByteArray "List/indexed"++        ListReverse ->+            Encoding.encodeUtf8ByteArray "List/reverse"++        Bool ->+            Encoding.encodeUtf8ByteArray "Bool"++        Bytes ->+            Encoding.encodeUtf8ByteArray "Bytes"++        Optional ->+            Encoding.encodeUtf8ByteArray "Optional"++        None ->+            Encoding.encodeUtf8ByteArray "None"++        Natural ->+            Encoding.encodeUtf8ByteArray "Natural"++        Integer ->+            Encoding.encodeUtf8ByteArray "Integer"++        Double ->+            Encoding.encodeUtf8ByteArray "Double"++        Text ->+            Encoding.encodeUtf8ByteArray "Text"++        TextReplace ->+            Encoding.encodeUtf8ByteArray "Text/replace"++        TextShow ->+            Encoding.encodeUtf8ByteArray "Text/show"++        Date ->+            Encoding.encodeUtf8ByteArray "Date"++        DateShow ->+            Encoding.encodeUtf8ByteArray "Date/show"++        Time ->+            Encoding.encodeUtf8ByteArray "Time"++        TimeShow ->+            Encoding.encodeUtf8ByteArray "Time/show"++        TimeZone ->+            Encoding.encodeUtf8ByteArray "TimeZone"++        TimeZoneShow ->+            Encoding.encodeUtf8ByteArray "TimeZone/show"++        List ->+            Encoding.encodeUtf8ByteArray "List"++        Const Type ->+            Encoding.encodeUtf8ByteArray "Type"++        Const Kind ->+            Encoding.encodeUtf8ByteArray "Kind"++        Const Sort ->+            Encoding.encodeUtf8ByteArray "Sort"++        a@App{} ->+            encodeListN+                (2 + length arguments)+                ( Encoding.encodeInt 0+                : go function+                : map go arguments+                )+          where+            (function, arguments) = unApply a++        Lam _ (FunctionBinding { functionBindingVariable = "_", functionBindingAnnotation = _A }) b ->+            encodeList3+                (Encoding.encodeInt 1)+                (go _A)+                (go b)++        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+            encodeList4+                (Encoding.encodeInt 1)+                (Encoding.encodeString x)+                (go _A)+                (go b)++        Pi _ "_" _A _B ->+            encodeList3+                (Encoding.encodeInt 2)+                (go _A)+                (go _B)++        Pi _ x _A _B ->+            encodeList4+                (Encoding.encodeInt 2)+                (Encoding.encodeString x)+                (go _A)+                (go _B)++        BoolOr l r ->+            encodeOperator 0 l r++        BoolAnd l r ->+            encodeOperator 1 l r++        BoolEQ l r ->+            encodeOperator 2 l r++        BoolNE l r ->+            encodeOperator 3 l r++        BytesLit b ->+            encodeList2+                (Encoding.encodeInt 33)+                (Encoding.encodeBytes b)++        NaturalPlus l r ->+            encodeOperator 4 l r++        NaturalTimes l r ->+            encodeOperator 5 l r++        TextAppend l r ->+            encodeOperator 6 l r++        ListAppend l r ->+            encodeOperator 7 l r++        Combine _ _ l r ->+            encodeOperator 8 l r++        Prefer _ _ l r ->+            encodeOperator 9 l r++        CombineTypes _ l r ->+            encodeOperator 10 l r++        ImportAlt l r ->+            encodeOperator 11 l r++        Equivalent _ l r ->+            encodeOperator 12 l r++        RecordCompletion l r ->+            encodeOperator 13 l r++        ListLit _T₀ xs+            | null xs ->+                encodeList2 (Encoding.encodeInt label) _T₁+            | otherwise ->+                encodeListN+                    (2 + length xs)+                    ( Encoding.encodeInt 4+                    : Encoding.encodeNull+                    : map go (Data.Foldable.toList xs)+                    )+          where+            (label, _T₁) = case _T₀ of+                Nothing           -> (4 , Encoding.encodeNull)+                Just (App List t) -> (4 , go t               )+                Just  t           -> (28, go t               )++        Some t ->+            encodeList3+                (Encoding.encodeInt 5)+                Encoding.encodeNull+                (go t)++        Merge t u Nothing ->+            encodeList3+                (Encoding.encodeInt 6)+                (go t)+                (go u)++        Merge t u (Just _T) ->+            encodeList4+                (Encoding.encodeInt 6)+                (go t)+                (go u)+                (go _T)++        Record xTs ->+            encodeList2+                (Encoding.encodeInt 7)+                (encodeMapWith (go . recordFieldValue) xTs)++        RecordLit xts ->+            encodeList2+                (Encoding.encodeInt 8)+                (encodeMapWith (go. recordFieldValue) xts)++        Field t (Syntax.fieldSelectionLabel -> x) ->+            encodeList3+                (Encoding.encodeInt 9)+                (go t)+                (Encoding.encodeString x)++        Project t (Left xs) ->+            encodeListN+                (2 + length xs)+                ( Encoding.encodeInt 10+                : go t+                : map Encoding.encodeString xs+                )++        Project t (Right _T) ->+            encodeList3+                (Encoding.encodeInt 10)+                (go t)+                (encodeList1 (go _T))++        Union xTs ->+            encodeList2+                (Encoding.encodeInt 11)+                (encodeMapWith encodeValue xTs)+          where+            encodeValue  Nothing  = Encoding.encodeNull+            encodeValue (Just _T) = go _T++        BoolLit b ->+            Encoding.encodeBool b++        BoolIf t l r ->+            encodeList4+                (Encoding.encodeInt 14)+                (go t)+                (go l)+                (go r)++        NaturalLit n ->+            encodeList2+                (Encoding.encodeInt 15)+                (Encoding.encodeInteger (fromIntegral n))++        IntegerLit n ->+            encodeList2+                (Encoding.encodeInt 16)+                (Encoding.encodeInteger (fromIntegral n))++        DoubleLit (DhallDouble n64)+            | useHalf   -> Encoding.encodeFloat16 n32+            | useFloat  -> Encoding.encodeFloat n32+            | otherwise -> Encoding.encodeDouble n64+          where+            n32 = double2Float n64++            n16 = toHalf n32++            useFloat = n64 == float2Double n32++            useHalf = n64 == (float2Double $ fromHalf n16)++        -- Fast path for the common case of an uninterpolated string+        TextLit (Chunks [] z) ->+            encodeList2+                (Encoding.encodeInt 18)+                (Encoding.encodeString z)++        TextLit (Chunks xys z) ->+            encodeListN+                (2 + 2 * length xys)+                ( Encoding.encodeInt 18+                : concatMap encodePair xys ++ [ Encoding.encodeString z ]+                )+          where+            encodePair (x, y) = [ Encoding.encodeString x, go y ]++        Assert t ->+            encodeList2+                (Encoding.encodeInt 19)+                (go t)++        Embed x ->+            encodeEmbed x++        Let a₀ b₀ ->+            encodeListN+                (2 + 3 * length as)+                ( Encoding.encodeInt 25+                : concatMap encodeBinding (toList as) ++ [ go b₁ ]+                )+          where+            MultiLet as b₁ = Syntax.multiLet a₀ b₀++            encodeBinding (Binding _ x _ mA₀ _ a) =+                [ Encoding.encodeString x+                , mA₁+                , go a+                ]+              where+                mA₁ = case mA₀ of+                    Nothing      -> Encoding.encodeNull+                    Just (_, _A) -> go _A++        Annot t _T ->+            encodeList3+                (Encoding.encodeInt 26)+                (go t)+                (go _T)++        ToMap t Nothing ->+            encodeList2+                (Encoding.encodeInt 27)+                (go t)++        ToMap t (Just _T) ->+            encodeList3+                (Encoding.encodeInt 27)+                (go t)+                (go _T)++        With l ks r ->+            encodeList4+                (Encoding.encodeInt 29)+                (go l)+                (encodeList (fmap encodeWithComponent ks))+                (go r)+          where+            encodeWithComponent  WithQuestion  = Encoding.encodeInt 0+            encodeWithComponent (WithLabel k ) = Encoding.encodeString k++        DateLiteral day ->+            encodeList4+                (Encoding.encodeInt 30)+                (Encoding.encodeInt (fromInteger _YYYY))+                (Encoding.encodeInt _MM)+                (Encoding.encodeInt _DD)+          where+            (_YYYY, _MM, _DD) = Time.toGregorian day++        TimeLiteral (Time.TimeOfDay hh mm ss) precision ->+            encodeList4+                (Encoding.encodeInt 31)+                (Encoding.encodeInt hh)+                (Encoding.encodeInt mm)+                (   Encoding.encodeTag 4+                <>  encodeList2+                        (Encoding.encodeInt exponent)+                        encodedMantissa+                )+          where+            exponent = negate (fromIntegral precision)++            mantissa :: Integer+            mantissa = truncate (ss * 10 ^ precision)++            encodedMantissa+                |  fromIntegral (minBound :: Int) <= mantissa+                && mantissa <= fromIntegral (maxBound :: Int) =+                    Encoding.encodeInt (fromInteger mantissa)+                | otherwise =+                    Encoding.encodeInteger mantissa++        TimeZoneLiteral (Time.TimeZone minutes _ _) ->+            encodeList4+                (Encoding.encodeInt 32)+                (Encoding.encodeBool sign)+                (Encoding.encodeInt _HH)+                (Encoding.encodeInt _MM)+          where+            sign = 0 <= minutes++            (_HH, _MM) = abs minutes `divMod` 60++        ShowConstructor t ->+            encodeList2+                (Encoding.encodeInt 34)+                (go t)++        Note _ b ->+            go b++    encodeOperator n l r =+        encodeList4+            (Encoding.encodeInt 3)+            (Encoding.encodeInt n)+            (go l)+            (go r)++    encodeMapWith encodeValue m =+            Encoding.encodeMapLen (fromIntegral (Dhall.Map.size m))+        <>  foldMap encodeKeyValue (Dhall.Map.toList (Dhall.Map.sort m))+      where+        encodeKeyValue (k, v) = Encoding.encodeString k <> encodeValue v++encodeList1 :: Encoding -> Encoding+encodeList1 a = Encoding.encodeListLen 1 <> a+{-# INLINE encodeList1 #-}++encodeList2 :: Encoding -> Encoding -> Encoding+encodeList2 a b = Encoding.encodeListLen 2 <> a <> b+{-# INLINE encodeList2 #-}++encodeList3 :: Encoding -> Encoding -> Encoding -> Encoding+encodeList3 a b c = Encoding.encodeListLen 3 <> a <> b <> c+{-# INLINE encodeList3 #-}++encodeList4 :: Encoding -> Encoding -> Encoding -> Encoding -> Encoding+encodeList4 a b c d = Encoding.encodeListLen 4 <> a <> b <> c <> d+{-# INLINE encodeList4 #-}++encodeListN :: Foldable f => Int -> f Encoding -> Encoding+encodeListN len xs =+    Encoding.encodeListLen (fromIntegral len) <> Foldable.fold xs+{-# INLINE encodeListN #-}++encodeList :: Foldable f => f Encoding -> Encoding+encodeList xs = encodeListN (length xs) xs+{-# INLINE encodeList #-}++decodeImport :: Int -> Decoder s Import+decodeImport len = do+    let die message = fail ("Dhall.Binary.decodeImport: " <> message)++    tokenType₀ <- Decoding.peekTokenType++    hash <- case tokenType₀ of+        TypeNull -> do+            Decoding.decodeNull++            return Nothing++        TypeBytes -> do+            bytes <- Decoding.decodeBytes++            let (prefix, suffix) = Data.ByteString.splitAt 2 bytes++            case prefix of+                "\x12\x20" -> return ()+                _          -> die ("Unrecognized multihash prefix: " <> show prefix)+            case Dhall.Crypto.sha256DigestFromByteString suffix of+                Nothing     -> die ("Invalid sha256 digest: " <> show bytes)+                Just digest -> return (Just digest)++        _ ->+            die ("Unexpected hash token: " <> show tokenType₀)++    m <- Decoding.decodeWord++    importMode <- case m of+        0 -> return Code+        1 -> return RawText+        2 -> return Location+        3 -> return RawBytes+        _ -> die ("Unexpected code for import mode: " <> show m)++    let remote scheme = do+            tokenType₁ <- Decoding.peekTokenType++            headers <- case tokenType₁ of+                TypeNull -> do+                    Decoding.decodeNull+                    return Nothing++                _ -> do+                    headers <- decodeExpressionInternal decodeImport++                    return (Just headers)++            authority <- Decoding.decodeString++            paths <- replicateDecoder (len - 8) Decoding.decodeString++            file <- Decoding.decodeString++            tokenType₂ <- Decoding.peekTokenType++            query <- case tokenType₂ of+                TypeNull -> do+                    Decoding.decodeNull+                    return Nothing+                _ ->+                    fmap Just Decoding.decodeString++            let components = reverse paths+            let directory  = Directory {..}+            let path       = File {..}++            return (Remote (URL {..}))++    let local prefix = do+            paths <- replicateDecoder (len - 5) Decoding.decodeString++            file <- Decoding.decodeString++            let components = reverse paths+            let directory  = Directory {..}++            return (Local prefix (File {..}))++    let missing = return Missing++    let env = do+            x <- Decoding.decodeString++            return (Env x)++    n <- Decoding.decodeWord++    importType <- case n of+        0 -> remote HTTP+        1 -> remote HTTPS+        2 -> local Absolute+        3 -> local Here+        4 -> local Parent+        5 -> local Home+        6 -> env+        7 -> missing+        _ -> fail ("Unrecognized import type code: " <> show n)++    let importHashed = ImportHashed {..}++    return (Import {..})++encodeImport :: Import -> Encoding+encodeImport import_ =+    case importType of+        Remote (URL { scheme = scheme₀, .. }) ->+            encodeList+                (   prefix+                ++  [ Encoding.encodeInt scheme₁+                    , using+                    , Encoding.encodeString authority+                    ]+                ++  map Encoding.encodeString (reverse components)+                ++  [ Encoding.encodeString file ]+                ++  [ case query of+                         Nothing -> Encoding.encodeNull+                         Just q  -> Encoding.encodeString q+                    ]+                )+          where+            using = case headers of+                Nothing ->+                    Encoding.encodeNull+                Just h ->+                    encodeExpressionInternal encodeImport (Syntax.denote h)++            scheme₁ = case scheme₀ of+                HTTP  -> 0+                HTTPS -> 1++            File{..} = path++            Directory {..} = directory++        Local prefix₀ path ->+            encodeList+                (   prefix+                ++  [ Encoding.encodeInt prefix₁ ]+                ++  map Encoding.encodeString components₁+                ++  [ Encoding.encodeString file ]+                )+          where+            File{..} = path++            Directory{..} = directory++            prefix₁ = case prefix₀ of+                Absolute -> 2+                Here     -> 3+                Parent   -> 4+                Home     -> 5++            components₁ = reverse components++        Env x ->+            encodeList+                (prefix ++ [ Encoding.encodeInt 6, Encoding.encodeString x ])++        Missing ->+            encodeList (prefix ++ [ Encoding.encodeInt 7 ])+  where+    prefix = [ Encoding.encodeInt 24, h, m ]+      where+        h = case hash of+            Nothing ->+                Encoding.encodeNull++            Just digest ->+                Encoding.encodeBytes ("\x12\x20" <> Dhall.Crypto.unSHA256Digest digest)++        m = Encoding.encodeInt (case importMode of+            Code -> 0+            RawText -> 1+            Location -> 2+            RawBytes -> 3 )++    Import{..} = import_++    ImportHashed{..} = importHashed++decodeVoid :: Int -> Decoder s Void+decodeVoid _ = fail "Dhall.Binary.decodeVoid: Cannot decode an uninhabited type"++encodeVoid :: Void -> Encoding+encodeVoid = absurd++instance Serialise (Expr Void Void) where+    encode = encodeExpressionInternal encodeVoid++    decode = decodeExpressionInternal decodeVoid++instance Serialise (Expr Void Import) where+    encode = encodeExpressionInternal encodeImport++    decode = decodeExpressionInternal decodeImport++-- | Encode a Dhall expression as a CBOR-encoded `ByteString`+encodeExpression :: Serialise (Expr Void a) => Expr Void a -> ByteString+encodeExpression = Serialise.serialise++-- | Decode a Dhall expression from a CBOR `Codec.CBOR.Term.Term`+decodeExpression+    :: Serialise (Expr s a) => ByteString -> Either DecodingFailure (Expr s a)+decodeExpression bytes =+    case decodeWithoutVersion <|> decodeWithVersion of+        Just expression -> Right expression+        Nothing         -> Left (CBORIsNotDhall bytes)+  where+    adapt (Right ("", x)) = Just x+    adapt  _              = Nothing++    decode' = decodeWith55799Tag decode++    -- This is the behavior specified by the standard+    decodeWithoutVersion = adapt (Read.deserialiseFromBytes decode' bytes)++    -- tag to ease the migration+    decodeWithVersion = adapt (Read.deserialiseFromBytes decodeWithTag bytes)+      where+        decodeWithTag = do+            2 <- Decoding.decodeListLen++            version <- Decoding.decodeString+++            -- "_" has never been a valid version string, and this ensures that+            -- we don't interpret `[ "_", 0 ]` as the expression `_` (encoded as+            -- `0`) tagged with a version string of `"_"`+            if (version == "_")+                then fail "Dhall.Binary.decodeExpression: \"_\" is not a valid version string"+                else return ()++            decode'++decodeWith55799Tag :: Decoder s a -> Decoder s a+decodeWith55799Tag decoder = do+    tokenType <- Decoding.peekTokenType++    case tokenType of+        TypeTag -> do+            w <- Decoding.decodeTag++            if w /= 55799+                then fail ("Dhall.Binary.decodeWith55799Tag: Unexpected tag: " <> show w)+                else return ()++            decoder+        _ ->+            decoder++{-| This indicates that a given CBOR-encoded `ByteString` did not correspond to+    a valid Dhall expression+-}+newtype DecodingFailure = CBORIsNotDhall ByteString+    deriving (Eq)++instance Exception DecodingFailure++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"++instance Show DecodingFailure where+    show (CBORIsNotDhall bytes) =+            _ERROR <> ": Cannot decode CBOR to Dhall\n"+        <>  "\n"+        <>  "The following bytes do not encode a valid Dhall expression\n"+        <>  "\n"+        <>  "↳ 0x" <> concatMap toHex (Data.ByteString.Lazy.unpack bytes) <> "\n"+      where+        toHex = Printf.printf "%02x "++-- | This specialized version of 'Control.Monad.replicateM' reduces+-- decoding timings by roughly 10%.+replicateDecoder :: Int -> Decoder s a -> Decoder s [a]+replicateDecoder n0 decoder = go n0+  where+    go n+      | n <= 0    = pure []+      | otherwise = do+            x <- decoder+            xs <- go (n - 1)+            pure (x:xs)
src/Dhall/Context.hs view
@@ -1,6 +1,4 @@-{-# LANGUAGE BangPatterns               #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFunctor #-}  -- | This is a utility module that consolidates all `Context`-related operations @@ -14,11 +12,11 @@     , toList     ) where -import Data.Text.Lazy (Text)-import Prelude hiding (lookup)+import Data.Text (Text)+import Prelude   hiding (lookup) -{-| A @(Context a)@ associates `Text` labels with values of type @a@.  Each-    `Text` label can correspond to multiple values of type @a@+{-| A @(Context a)@ associates `Data.Text.Text` labels with values of type @a@.+    Each `Data.Text.Text` label can correspond to multiple values of type @a@      The `Context` is used for type-checking when @(a = Expr X)@ @@ -50,7 +48,6 @@ match :: Context a -> Maybe (Text, a, Context a) match (Context ((k, v) : kvs)) = Just (k, v, Context kvs) match (Context           []  ) = Nothing- {-# INLINABLE match #-}  {-| Look up a key by name and index@@ -60,10 +57,10 @@ > lookup k n (insert k v c) = lookup k (n - 1) c > lookup k n (insert j v c) = lookup k  n      c  -- k /= j -}-lookup :: Text -> Integer -> Context a -> Maybe a-lookup _ !_ (Context         []  ) =+lookup :: Text -> Int -> Context a -> Maybe a+lookup _ _ (Context         []  ) =     Nothing-lookup x !n (Context ((k, v):kvs)) =+lookup x n (Context ((k, v):kvs)) =     if x == k     then if n == 0          then Just v
src/Dhall/Core.hs view
@@ -1,1807 +1,156 @@-{-# LANGUAGE BangPatterns      #-}-{-# LANGUAGE CPP               #-}-{-# LANGUAGE DeriveFoldable    #-}-{-# LANGUAGE DeriveFunctor     #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes        #-}-{-# LANGUAGE RecordWildCards   #-}-{-# LANGUAGE UnicodeSyntax     #-}-{-# OPTIONS_GHC -Wall #-}--{-| This module contains the core calculus for the Dhall language.--    Dhall is essentially a fork of the @morte@ compiler but with more built-in-    functionality, better error messages, and Haskell integration--}--module Dhall.Core (-    -- * Syntax-      Const(..)-    , HasHome(..)-    , PathType(..)-    , PathHashed(..)-    , PathMode(..)-    , Path(..)-    , Var(..)-    , Chunks(..)-    , Expr(..)--    -- * Normalization-    , alphaNormalize-    , normalize-    , normalizeWith-    , Normalizer-    , judgmentallyEqual-    , subst-    , shift-    , isNormalized-    , isNormalizedWith-    , denote--    -- * Pretty-printing-    , pretty--    -- * Miscellaneous-    , internalError-    , reservedIdentifiers-    , escapeText-    ) where--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative (Applicative(..), (<$>))-#endif-import Control.Applicative (empty)-import Crypto.Hash (SHA256)-import Data.Bifunctor (Bifunctor(..))-import Data.Foldable-import Data.HashMap.Strict.InsOrd (InsOrdHashMap)-import Data.HashSet (HashSet)-import Data.Monoid ((<>))-import Data.String (IsString(..))-import Data.Scientific (Scientific)-import Data.Sequence (Seq, ViewL(..), ViewR(..))-import Data.Text.Buildable (Buildable(..))-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-import Data.Text.Prettyprint.Doc (Pretty)-import Data.Traversable-import {-# SOURCE #-} Dhall.Pretty.Internal-import Numeric.Natural (Natural)-import Prelude hiding (succ)--import qualified Control.Monad-import qualified Crypto.Hash-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.HashSet-import qualified Data.Sequence-import qualified Data.Text-import qualified Data.Text.Lazy                        as Text-import qualified Data.Text.Lazy.Builder                as Builder-import qualified Data.Text.Prettyprint.Doc             as Pretty--{-| Constants for a pure type system--    The only axiom is:--> ⊦ Type : Kind--    ... and the valid rule pairs are:--> ⊦ Type ↝ Type : Type  -- Functions from terms to terms (ordinary functions)-> ⊦ Kind ↝ Type : Type  -- Functions from types to terms (polymorphic functions)-> ⊦ Kind ↝ Kind : Kind  -- Functions from types to types (type constructors)--    These are the same rule pairs as System Fω--    Note that Dhall does not support functions from terms to types and therefore-    Dhall is not a dependently typed language--}-data Const = Type | Kind deriving (Show, Eq, Bounded, Enum)--instance Buildable Const where-    build = buildConst---- | Whether or not a path is relative to the user's home directory-data HasHome = Home | Homeless deriving (Eq, Ord, Show)---- | The type of path to import (i.e. local vs. remote vs. environment)-data PathType-    = File HasHome FilePath-    -- ^ Local path-    | URL  Text (Maybe PathHashed)-    -- ^ URL of emote resource and optional headers stored in a path-    | Env  Text-    -- ^ Environment variable-    deriving (Eq, Ord, Show)--instance Buildable PathType where-    build (File Home     file)-        = "~/" <> build (Text.pack file)-    build (File Homeless file)-        |  Text.isPrefixOf  "./" txt-        || Text.isPrefixOf   "/" txt-        || Text.isPrefixOf "../" txt-        = build txt <> " "-        | otherwise-        = "./" <> build txt <> " "-      where-        txt = Text.pack file-    build (URL str  Nothing      ) = build str <> " "-    build (URL str (Just headers)) = build str <> " using " <> build headers <> " "-    build (Env env) = "env:" <> build env---- | How to interpret the path's contents (i.e. as Dhall code or raw text)-data PathMode = Code | RawText deriving (Eq, Ord, Show)---- | A `PathType` extended with an optional hash for semantic integrity checks-data PathHashed = PathHashed-    { hash     :: Maybe (Crypto.Hash.Digest SHA256)-    , pathType :: PathType-    } deriving (Eq, Ord, Show)--instance Buildable PathHashed where-    build (PathHashed  Nothing p) = build p-    build (PathHashed (Just h) p) = build p <> "sha256:" <> build (show h) <> " "---- | Path to an external resource-data Path = Path-    { pathHashed :: PathHashed-    , pathMode   :: PathMode-    } deriving (Eq, Ord, Show)--instance Buildable Path where-    build (Path {..}) = build pathHashed <> suffix-      where-        suffix = case pathMode of-            RawText -> "as Text"-            Code    -> ""--instance Pretty Path where-    pretty path = Pretty.pretty (Builder.toLazyText (build path))--{-| Label for a bound variable--    The `Text` field is the variable's name (i.e. \"@x@\").--    The `Int` field disambiguates variables with the same name if there are-    multiple bound variables of the same name in scope.  Zero refers to the-    nearest bound variable and the index increases by one for each bound-    variable of the same name going outward.  The following diagram may help:-->                               ┌──refers to──┐->                               │             │->                               v             │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0->-> ┌─────────────────refers to─────────────────┐-> │                                           │-> v                                           │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1--    This `Int` behaves like a De Bruijn index in the special case where all-    variables have the same name.--    You can optionally omit the index if it is @0@:-->                               ┌─refers to─┐->                               │           │->                               v           │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x--    Zero indices are omitted when pretty-printing `Var`s and non-zero indices-    appear as a numeric suffix.--}-data Var = V Text !Integer-    deriving (Eq, Show)--instance IsString Var where-    fromString str = V (fromString str) 0--instance Buildable Var where-    build = buildVar---- | Syntax tree for expressions-data Expr s a-    -- | > Const c                                  ~  c-    = Const Const-    -- | > Var (V x 0)                              ~  x-    --   > Var (V x n)                              ~  x@n-    | Var Var-    -- | > Lam x     A b                            ~  λ(x : A) -> b-    | Lam Text (Expr s a) (Expr s a)-    -- | > Pi "_" A B                               ~        A  -> B-    --   > Pi x   A B                               ~  ∀(x : A) -> B-    | Pi  Text (Expr s a) (Expr s a)-    -- | > App f a                                  ~  f a-    | App (Expr s a) (Expr s a)-    -- | > Let x Nothing  r e                       ~  let x     = r in e-    --   > Let x (Just t) r e                       ~  let x : t = r in e-    | Let Text (Maybe (Expr s a)) (Expr s a) (Expr s a)-    -- | > Annot x t                                ~  x : t-    | Annot (Expr s a) (Expr s a)-    -- | > Bool                                     ~  Bool-    | Bool-    -- | > BoolLit b                                ~  b-    | BoolLit Bool-    -- | > BoolAnd x y                              ~  x && y-    | BoolAnd (Expr s a) (Expr s a)-    -- | > BoolOr  x y                              ~  x || y-    | BoolOr  (Expr s a) (Expr s a)-    -- | > BoolEQ  x y                              ~  x == y-    | BoolEQ  (Expr s a) (Expr s a)-    -- | > BoolNE  x y                              ~  x != y-    | BoolNE  (Expr s a) (Expr s a)-    -- | > BoolIf x y z                             ~  if x then y else z-    | BoolIf (Expr s a) (Expr s a) (Expr s a)-    -- | > Natural                                  ~  Natural-    | Natural-    -- | > NaturalLit n                             ~  +n-    | NaturalLit Natural-    -- | > NaturalFold                              ~  Natural/fold-    | NaturalFold-    -- | > NaturalBuild                             ~  Natural/build-    | NaturalBuild-    -- | > NaturalIsZero                            ~  Natural/isZero-    | NaturalIsZero-    -- | > NaturalEven                              ~  Natural/even-    | NaturalEven-    -- | > NaturalOdd                               ~  Natural/odd-    | NaturalOdd-    -- | > NaturalToInteger                         ~  Natural/toInteger-    | NaturalToInteger-    -- | > NaturalShow                              ~  Natural/show-    | NaturalShow-    -- | > NaturalPlus x y                          ~  x + y-    | NaturalPlus (Expr s a) (Expr s a)-    -- | > NaturalTimes x y                         ~  x * y-    | NaturalTimes (Expr s a) (Expr s a)-    -- | > Integer                                  ~  Integer-    | Integer-    -- | > IntegerLit n                             ~  n-    | IntegerLit Integer-    -- | > IntegerShow                              ~  Integer/show-    | IntegerShow-    -- | > Double                                   ~  Double-    | Double-    -- | > DoubleLit n                              ~  n-    | DoubleLit Scientific-    -- | > DoubleShow                               ~  Double/show-    | DoubleShow-    -- | > Text                                     ~  Text-    | Text-    -- | > TextLit (Chunks [(t1, e1), (t2, e2)] t3) ~  "t1${e1}t2${e2}t3"-    | TextLit (Chunks s a)-    -- | > TextAppend x y                           ~  x ++ y-    | TextAppend (Expr s a) (Expr s a)-    -- | > List                                     ~  List-    | List-    -- | > ListLit (Just t ) [x, y, z]              ~  [x, y, z] : List t-    --   > ListLit  Nothing  [x, y, z]              ~  [x, y, z]-    | ListLit (Maybe (Expr s a)) (Seq (Expr s a))-    -- | > ListAppend x y                           ~  x # y-    | ListAppend (Expr s a) (Expr s a)-    -- | > ListBuild                                ~  List/build-    | ListBuild-    -- | > ListFold                                 ~  List/fold-    | ListFold-    -- | > ListLength                               ~  List/length-    | ListLength-    -- | > ListHead                                 ~  List/head-    | ListHead-    -- | > ListLast                                 ~  List/last-    | ListLast-    -- | > ListIndexed                              ~  List/indexed-    | ListIndexed-    -- | > ListReverse                              ~  List/reverse-    | ListReverse-    -- | > Optional                                 ~  Optional-    | Optional-    -- | > OptionalLit t (Just e)                   ~  [e] : Optional t-    --   > OptionalLit t Nothing                    ~  []  : Optional t-    | OptionalLit (Expr s a) (Maybe (Expr s a))-    -- | > OptionalFold                             ~  Optional/fold-    | OptionalFold-    -- | > OptionalBuild                            ~  Optional/build-    | OptionalBuild-    -- | > Record            [(k1, t1), (k2, t2)]   ~  { k1 : t1, k2 : t1 }-    | Record    (InsOrdHashMap Text (Expr s a))-    -- | > RecordLit         [(k1, v1), (k2, v2)]   ~  { k1 = v1, k2 = v2 }-    | RecordLit (InsOrdHashMap Text (Expr s a))-    -- | > Union             [(k1, t1), (k2, t2)]   ~  < k1 : t1 | k2 : t2 >-    | Union     (InsOrdHashMap Text (Expr s a))-    -- | > UnionLit (k1, v1) [(k2, t2), (k3, t3)]   ~  < k1 = t1 | k2 : t2 | k3 : t3 >-    | UnionLit Text (Expr s a) (InsOrdHashMap Text (Expr s a))-    -- | > Combine x y                              ~  x ∧ y-    | Combine (Expr s a) (Expr s a)-    -- | > CombineRight x y                         ~  x ⫽ y-    | Prefer (Expr s a) (Expr s a)-    -- | > Merge x y (Just t )                      ~  merge x y : t-    --   > Merge x y  Nothing                       ~  merge x y-    | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))-    -- | > Constructors e                           ~  constructors e-    | Constructors (Expr s a)-    -- | > Field e x                                ~  e.x-    | Field (Expr s a) Text-    -- | > Note s x                                 ~  e-    | Note s (Expr s a)-    -- | > Embed path                               ~  path-    | Embed a-    deriving (Functor, Foldable, Traversable, Show, Eq)--instance Applicative (Expr s) where-    pure = Embed--    (<*>) = Control.Monad.ap--instance Monad (Expr s) where-    return = pure--    Const a              >>= _ = Const a-    Var a                >>= _ = Var a-    Lam a b c            >>= k = Lam a (b >>= k) (c >>= k)-    Pi  a b c            >>= k = Pi a (b >>= k) (c >>= k)-    App a b              >>= k = App (a >>= k) (b >>= k)-    Let a b c d          >>= k = Let a (fmap (>>= k) b) (c >>= k) (d >>= k)-    Annot a b            >>= k = Annot (a >>= k) (b >>= k)-    Bool                 >>= _ = Bool-    BoolLit a            >>= _ = BoolLit a-    BoolAnd a b          >>= k = BoolAnd (a >>= k) (b >>= k)-    BoolOr  a b          >>= k = BoolOr  (a >>= k) (b >>= k)-    BoolEQ  a b          >>= k = BoolEQ  (a >>= k) (b >>= k)-    BoolNE  a b          >>= k = BoolNE  (a >>= k) (b >>= k)-    BoolIf a b c         >>= k = BoolIf (a >>= k) (b >>= k) (c >>= k)-    Natural              >>= _ = Natural-    NaturalLit a         >>= _ = NaturalLit a-    NaturalFold          >>= _ = NaturalFold-    NaturalBuild         >>= _ = NaturalBuild-    NaturalIsZero        >>= _ = NaturalIsZero-    NaturalEven          >>= _ = NaturalEven-    NaturalOdd           >>= _ = NaturalOdd-    NaturalToInteger     >>= _ = NaturalToInteger-    NaturalShow          >>= _ = NaturalShow-    NaturalPlus  a b     >>= k = NaturalPlus  (a >>= k) (b >>= k)-    NaturalTimes a b     >>= k = NaturalTimes (a >>= k) (b >>= k)-    Integer              >>= _ = Integer-    IntegerLit a         >>= _ = IntegerLit a-    IntegerShow          >>= _ = IntegerShow-    Double               >>= _ = Double-    DoubleLit a          >>= _ = DoubleLit a-    DoubleShow           >>= _ = DoubleShow-    Text                 >>= _ = Text-    TextLit (Chunks a b) >>= k = TextLit (Chunks (fmap (fmap (>>= k)) a) b)-    TextAppend a b       >>= k = TextAppend (a >>= k) (b >>= k)-    List                 >>= _ = List-    ListLit a b          >>= k = ListLit (fmap (>>= k) a) (fmap (>>= k) b)-    ListAppend a b       >>= k = ListAppend (a >>= k) (b >>= k)-    ListBuild            >>= _ = ListBuild-    ListFold             >>= _ = ListFold-    ListLength           >>= _ = ListLength-    ListHead             >>= _ = ListHead-    ListLast             >>= _ = ListLast-    ListIndexed          >>= _ = ListIndexed-    ListReverse          >>= _ = ListReverse-    Optional             >>= _ = Optional-    OptionalLit a b      >>= k = OptionalLit (a >>= k) (fmap (>>= k) b)-    OptionalFold         >>= _ = OptionalFold-    OptionalBuild        >>= _ = OptionalBuild-    Record    a          >>= k = Record (fmap (>>= k) a)-    RecordLit a          >>= k = RecordLit (fmap (>>= k) a)-    Union     a          >>= k = Union (fmap (>>= k) a)-    UnionLit a b c       >>= k = UnionLit a (b >>= k) (fmap (>>= k) c)-    Combine a b          >>= k = Combine (a >>= k) (b >>= k)-    Prefer a b           >>= k = Prefer (a >>= k) (b >>= k)-    Merge a b c          >>= k = Merge (a >>= k) (b >>= k) (fmap (>>= k) c)-    Constructors a       >>= k = Constructors (a >>= k)-    Field a b            >>= k = Field (a >>= k) b-    Note a b             >>= k = Note a (b >>= k)-    Embed a              >>= k = k a--instance Bifunctor Expr where-    first _ (Const a             ) = Const a-    first _ (Var a               ) = Var a-    first k (Lam a b c           ) = Lam a (first k b) (first k c)-    first k (Pi a b c            ) = Pi a (first k b) (first k c)-    first k (App a b             ) = App (first k a) (first k b)-    first k (Let a b c d         ) = Let a (fmap (first k) b) (first k c) (first k d)-    first k (Annot a b           ) = Annot (first k a) (first k b)-    first _  Bool                  = Bool-    first _ (BoolLit a           ) = BoolLit a-    first k (BoolAnd a b         ) = BoolAnd (first k a) (first k b)-    first k (BoolOr a b          ) = BoolOr (first k a) (first k b)-    first k (BoolEQ a b          ) = BoolEQ (first k a) (first k b)-    first k (BoolNE a b          ) = BoolNE (first k a) (first k b)-    first k (BoolIf a b c        ) = BoolIf (first k a) (first k b) (first k c)-    first _  Natural               = Natural-    first _ (NaturalLit a        ) = NaturalLit a-    first _  NaturalFold           = NaturalFold-    first _  NaturalBuild          = NaturalBuild-    first _  NaturalIsZero         = NaturalIsZero-    first _  NaturalEven           = NaturalEven-    first _  NaturalOdd            = NaturalOdd-    first _  NaturalToInteger      = NaturalToInteger-    first _  NaturalShow           = NaturalShow-    first k (NaturalPlus a b     ) = NaturalPlus (first k a) (first k b)-    first k (NaturalTimes a b    ) = NaturalTimes (first k a) (first k b)-    first _  Integer               = Integer-    first _ (IntegerLit a        ) = IntegerLit a-    first _  IntegerShow           = IntegerShow-    first _  Double                = Double-    first _ (DoubleLit a         ) = DoubleLit a-    first _  DoubleShow            = DoubleShow-    first _  Text                  = Text-    first k (TextLit (Chunks a b)) = TextLit (Chunks (fmap (fmap (first k)) a) b)-    first k (TextAppend a b      ) = TextAppend (first k a) (first k b)-    first _  List                  = List-    first k (ListLit a b         ) = ListLit (fmap (first k) a) (fmap (first k) b)-    first k (ListAppend a b      ) = ListAppend (first k a) (first k b)-    first _  ListBuild             = ListBuild-    first _  ListFold              = ListFold-    first _  ListLength            = ListLength-    first _  ListHead              = ListHead-    first _  ListLast              = ListLast-    first _  ListIndexed           = ListIndexed-    first _  ListReverse           = ListReverse-    first _  Optional              = Optional-    first k (OptionalLit a b     ) = OptionalLit (first k a) (fmap (first k) b)-    first _  OptionalFold          = OptionalFold-    first _  OptionalBuild         = OptionalBuild-    first k (Record a            ) = Record (fmap (first k) a)-    first k (RecordLit a         ) = RecordLit (fmap (first k) a)-    first k (Union a             ) = Union (fmap (first k) a)-    first k (UnionLit a b c      ) = UnionLit a (first k b) (fmap (first k) c)-    first k (Combine a b         ) = Combine (first k a) (first k b)-    first k (Prefer a b          ) = Prefer (first k a) (first k b)-    first k (Merge a b c         ) = Merge (first k a) (first k b) (fmap (first k) c)-    first k (Constructors a      ) = Constructors (first k a)-    first k (Field a b           ) = Field (first k a) b-    first k (Note a b            ) = Note (k a) (first k b)-    first _ (Embed a             ) = Embed a--    second = fmap--instance IsString (Expr s a) where-    fromString str = Var (fromString str)---- | The body of an interpolated @Text@ literal-data Chunks s a = Chunks [(Builder, Expr s a)] Builder-    deriving (Functor, Foldable, Traversable, Show, Eq)--instance Monoid (Chunks s a) where-    mempty = Chunks [] mempty--#if MIN_VERSION_base(4,11,0)-instance Semigroup (Chunks s a) where-    (<>) (Chunks xysL zL) (Chunks         []    zR) =-        Chunks xysL (zL <> zR)-    (<>) (Chunks xysL zL) (Chunks ((x, y):xysR) zR) =-        Chunks (xysL ++ (zL <> x, y):xysR) zR-#else-    mappend (Chunks xysL zL) (Chunks         []    zR) =-        Chunks xysL (zL <> zR)-    mappend (Chunks xysL zL) (Chunks ((x, y):xysR) zR) =-        Chunks (xysL ++ (zL <> x, y):xysR) zR-#endif--instance IsString (Chunks s a) where-    fromString str = Chunks [] (fromString str)--{-  There is a one-to-one correspondence between the builders in this section-    and the sub-parsers in "Dhall.Parser".  Each builder is named after the-    corresponding parser and the relationship between builders exactly matches-    the relationship between parsers.  This leads to the nice emergent property-    of automatically getting all the parentheses and precedences right.--    This approach has one major disadvantage: you can get an infinite loop if-    you add a new constructor to the syntax tree without adding a matching-    case the corresponding builder.--}---- | Generates a syntactically valid Dhall program-instance Buildable a => Buildable (Expr s a) where-    build = buildExpr--instance Pretty a => Pretty (Expr s a) where-    pretty = Pretty.unAnnotate . prettyExpr--{-| `shift` is used by both normalization and type-checking to avoid variable-    capture by shifting variable indices--    For example, suppose that you were to normalize the following expression:--> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x--    If you were to substitute @y@ with @x@ without shifting any variable-    indices, then you would get the following incorrect result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x  -- Incorrect normalized form--    In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in-    order to avoid being misinterpreted as the @x@ bound by the innermost-    lambda.  If we perform that `shift` then we get the correct result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x@1--    As a more worked example, suppose that you were to normalize the following-    expression:-->     λ(a : Type)-> →   λ(f : a → a → a)-> →   λ(x : a)-> →   λ(x : a)-> →   (λ(x : a) → f x x@1) x@1--    The correct normalized result would be:-->     λ(a : Type)-> →   λ(f : a → a → a)-> →   λ(x : a)-> →   λ(x : a)-> →   f x@1 x--    The above example illustrates how we need to both increase and decrease-    variable indices as part of substitution:--    * We need to increase the index of the outer @x\@1@ to @x\@2@ before we-      substitute it into the body of the innermost lambda expression in order-      to avoid variable capture.  This substitution changes the body of the-      lambda expression to @(f x\@2 x\@1)@--    * We then remove the innermost lambda and therefore decrease the indices of-      both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one-      less @x@ variable is now bound within that scope--    Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to-    the indices of all variables named @x@ whose indices are greater than-    @(n + m)@, where @m@ is the number of bound variables of the same name-    within that scope--    In practice, @d@ is always @1@ or @-1@ because we either:--    * increment variables by @1@ to avoid variable capture during substitution-    * decrement variables by @1@ when deleting lambdas after substitution--    @n@ starts off at @0@ when substitution begins and increments every time we-    descend into a lambda or let expression that binds a variable of the same-    name in order to avoid shifting the bound variables by mistake.--}-shift :: Integer -> Var -> Expr s a -> Expr s a-shift _ _ (Const a) = Const a-shift d (V x n) (Var (V x' n')) = Var (V x' n'')-  where-    n'' = if x == x' && n <= n' then n' + d else n'-shift d (V x n) (Lam x' _A b) = Lam x' _A' b'-  where-    _A' = shift d (V x n ) _A-    b'  = shift d (V x n') b-      where-        n' = if x == x' then n + 1 else n-shift d (V x n) (Pi x' _A _B) = Pi x' _A' _B'-  where-    _A' = shift d (V x n ) _A-    _B' = shift d (V x n') _B-      where-        n' = if x == x' then n + 1 else n-shift d v (App f a) = App f' a'-  where-    f' = shift d v f-    a' = shift d v a-shift d (V x n) (Let f mt r e) = Let f mt' r' e'-  where-    e' = shift d (V x n') e-      where-        n' = if x == f then n + 1 else n--    mt' = fmap (shift d (V x n)) mt-    r'  =       shift d (V x n)  r-shift d v (Annot a b) = Annot a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ Bool = Bool-shift _ _ (BoolLit a) = BoolLit a-shift d v (BoolAnd a b) = BoolAnd a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolOr a b) = BoolOr a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolEQ a b) = BoolEQ a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolNE a b) = BoolNE a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolIf a b c) = BoolIf a' b' c'-  where-    a' = shift d v a-    b' = shift d v b-    c' = shift d v c-shift _ _ Natural = Natural-shift _ _ (NaturalLit a) = NaturalLit a-shift _ _ NaturalFold = NaturalFold-shift _ _ NaturalBuild = NaturalBuild-shift _ _ NaturalIsZero = NaturalIsZero-shift _ _ NaturalEven = NaturalEven-shift _ _ NaturalOdd = NaturalOdd-shift _ _ NaturalToInteger = NaturalToInteger-shift _ _ NaturalShow = NaturalShow-shift d v (NaturalPlus a b) = NaturalPlus a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (NaturalTimes a b) = NaturalTimes a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ Integer = Integer-shift _ _ (IntegerLit a) = IntegerLit a-shift _ _ IntegerShow = IntegerShow-shift _ _ Double = Double-shift _ _ (DoubleLit a) = DoubleLit a-shift _ _ DoubleShow = DoubleShow-shift _ _ Text = Text-shift d v (TextLit (Chunks a b)) = TextLit (Chunks a' b)-  where-    a' = fmap (fmap (shift d v)) a-shift d v (TextAppend a b) = TextAppend a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ List = List-shift d v (ListLit a b) = ListLit a' b'-  where-    a' = fmap (shift d v) a-    b' = fmap (shift d v) b-shift _ _ ListBuild = ListBuild-shift d v (ListAppend a b) = ListAppend a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ ListFold = ListFold-shift _ _ ListLength = ListLength-shift _ _ ListHead = ListHead-shift _ _ ListLast = ListLast-shift _ _ ListIndexed = ListIndexed-shift _ _ ListReverse = ListReverse-shift _ _ Optional = Optional-shift d v (OptionalLit a b) = OptionalLit a' b'-  where-    a' =       shift d v  a-    b' = fmap (shift d v) b-shift _ _ OptionalFold = OptionalFold-shift _ _ OptionalBuild = OptionalBuild-shift d v (Record a) = Record a'-  where-    a' = fmap (shift d v) a-shift d v (RecordLit a) = RecordLit a'-  where-    a' = fmap (shift d v) a-shift d v (Union a) = Union a'-  where-    a' = fmap (shift d v) a-shift d v (UnionLit a b c) = UnionLit a b' c'-  where-    b' =       shift d v  b-    c' = fmap (shift d v) c-shift d v (Combine a b) = Combine a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (Prefer a b) = Prefer a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (Merge a b c) = Merge a' b' c'-  where-    a' =       shift d v  a-    b' =       shift d v  b-    c' = fmap (shift d v) c-shift d v (Constructors a) = Constructors a'-  where-    a' = shift d v  a-shift d v (Field a b) = Field a' b-  where-    a' = shift d v a-shift d v (Note a b) = Note a b'-  where-    b' = shift d v b--- The Dhall compiler enforces that all embedded values are closed expressions--- and `shift` does nothing to a closed expression-shift _ _ (Embed p) = Embed p--{-| Substitute all occurrences of a variable with an expression--> subst x C B  ~  B[x := C]--}-subst :: Var -> Expr s a -> Expr s a -> Expr s a-subst _ _ (Const a) = Const a-subst (V x n) e (Lam y _A b) = Lam y _A' b'-  where-    _A' = subst (V x n )                  e  _A-    b'  = subst (V x n') (shift 1 (V y 0) e)  b-    n'  = if x == y then n + 1 else n-subst (V x n) e (Pi y _A _B) = Pi y _A' _B'-  where-    _A' = subst (V x n )                  e  _A-    _B' = subst (V x n') (shift 1 (V y 0) e) _B-    n'  = if x == y then n + 1 else n-subst v e (App f a) = App f' a'-  where-    f' = subst v e f-    a' = subst v e a-subst v e (Var v') = if v == v' then e else Var v'-subst (V x n) e (Let f mt r b) = Let f mt' r' b'-  where-    b' = subst (V x n') (shift 1 (V f 0) e) b-      where-        n' = if x == f then n + 1 else n--    mt' = fmap (subst (V x n) e) mt-    r'  =       subst (V x n) e  r-subst x e (Annot a b) = Annot a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ Bool = Bool-subst _ _ (BoolLit a) = BoolLit a-subst x e (BoolAnd a b) = BoolAnd a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolOr a b) = BoolOr a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolEQ a b) = BoolEQ a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolNE a b) = BoolNE a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolIf a b c) = BoolIf a' b' c'-  where-    a' = subst x e a-    b' = subst x e b-    c' = subst x e c-subst _ _ Natural = Natural-subst _ _ (NaturalLit a) = NaturalLit a-subst _ _ NaturalFold = NaturalFold-subst _ _ NaturalBuild = NaturalBuild-subst _ _ NaturalIsZero = NaturalIsZero-subst _ _ NaturalEven = NaturalEven-subst _ _ NaturalOdd = NaturalOdd-subst _ _ NaturalToInteger = NaturalToInteger-subst _ _ NaturalShow = NaturalShow-subst x e (NaturalPlus a b) = NaturalPlus a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (NaturalTimes a b) = NaturalTimes a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ Integer = Integer-subst _ _ (IntegerLit a) = IntegerLit a-subst _ _ IntegerShow = IntegerShow-subst _ _ Double = Double-subst _ _ (DoubleLit a) = DoubleLit a-subst _ _ DoubleShow = DoubleShow-subst _ _ Text = Text-subst x e (TextLit (Chunks a b)) = TextLit (Chunks a' b)-  where-    a' = fmap (fmap (subst x e)) a-subst x e (TextAppend a b) = TextAppend a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ List = List-subst x e (ListLit a b) = ListLit a' b'-  where-    a' = fmap (subst x e) a-    b' = fmap (subst x e) b-subst x e (ListAppend a b) = ListAppend a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ ListBuild = ListBuild-subst _ _ ListFold = ListFold-subst _ _ ListLength = ListLength-subst _ _ ListHead = ListHead-subst _ _ ListLast = ListLast-subst _ _ ListIndexed = ListIndexed-subst _ _ ListReverse = ListReverse-subst _ _ Optional = Optional-subst x e (OptionalLit a b) = OptionalLit a' b'-  where-    a' =       subst x e  a-    b' = fmap (subst x e) b-subst _ _ OptionalFold = OptionalFold-subst _ _ OptionalBuild = OptionalBuild-subst x e (Record       kts) = Record                   (fmap (subst x e) kts)-subst x e (RecordLit    kvs) = RecordLit                (fmap (subst x e) kvs)-subst x e (Union        kts) = Union                    (fmap (subst x e) kts)-subst x e (UnionLit a b kts) = UnionLit a (subst x e b) (fmap (subst x e) kts)-subst x e (Combine a b) = Combine a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (Prefer a b) = Prefer a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (Merge a b c) = Merge a' b' c'-  where-    a' =       subst x e  a-    b' =       subst x e  b-    c' = fmap (subst x e) c-subst x e (Constructors a) = Constructors a'-  where-    a' = subst x e  a-subst x e (Field a b) = Field a' b-  where-    a' = subst x e a-subst x e (Note a b) = Note a b'-  where-    b' = subst x e b--- The Dhall compiler enforces that all embedded values are closed expressions--- and `subst` does nothing to a closed expression-subst _ _ (Embed p) = Embed p--{-| α-normalize an expression by renaming all variables to @\"_\"@ and using-    De Bruijn indices to distinguish them--}-alphaNormalize :: Expr s a -> Expr s a-alphaNormalize (Const c) =-    Const c-alphaNormalize (Var v) =-    Var v-alphaNormalize (Lam x _A₀ b₀) =-    Lam "_" _A₁ b₃-  where-    _A₁ = alphaNormalize _A₀--    v₀ = Var (V "_" 0)-    v₁ = shift 1 (V x 0) v₀-    b₁ = subst (V x 0) v₁ b₀-    b₂ = shift (-1) (V x 0) b₁-    b₃ = alphaNormalize b₂-alphaNormalize (Pi x _A₀ _B₀) =-    Pi "_" _A₁ _B₃-  where-    _A₁ = alphaNormalize _A₀--    v₀  = Var (V "_" 0)-    v₁  = shift 1 (V x 0) v₀-    _B₁ = subst (V x 0) v₁ _B₀-    _B₂ = shift (-1) (V x 0) _B₁-    _B₃ = alphaNormalize _B₂-alphaNormalize (App f₀ a₀) =-    App f₁ a₁-  where-    f₁ = alphaNormalize f₀--    a₁ = alphaNormalize a₀-alphaNormalize (Let x (Just _A₀) a₀ b₀) =-    Let "_" (Just _A₁) a₁ b₃-  where-    _A₁ = alphaNormalize _A₀--    a₁ = alphaNormalize a₀--    v₀ = Var (V "_" 0)-    v₁ = shift 1 (V x 0) v₀-    b₁ = subst (V x 0) v₁ b₀-    b₂ = shift (-1) (V x 0) b₁-    b₃ = alphaNormalize b₂-alphaNormalize (Let x Nothing a₀ b₀) =-    Let "_" Nothing a₁ b₃-  where-    a₁ = alphaNormalize a₀--    v₀ = Var (V "_" 0)-    v₁ = shift 1 (V x 0) v₀-    b₁ = subst (V x 0) v₁ b₀-    b₂ = shift (-1) (V x 0) b₁-    b₃ = alphaNormalize b₂-alphaNormalize (Annot t₀ _T₀) =-    Annot t₁ _T₁-  where-    t₁ = alphaNormalize t₀--    _T₁ = alphaNormalize _T₀-alphaNormalize Bool =-    Bool-alphaNormalize (BoolLit b) =-    BoolLit b-alphaNormalize (BoolAnd l₀ r₀) =-    BoolAnd l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (BoolOr l₀ r₀) =-    BoolOr l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (BoolEQ l₀ r₀) =-    BoolEQ l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (BoolNE l₀ r₀) =-    BoolNE l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (BoolIf t₀ l₀ r₀) =-    BoolIf t₁ l₁ r₁-  where-    t₁ = alphaNormalize t₀--    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize Natural =-    Natural-alphaNormalize (NaturalLit n) =-    NaturalLit n-alphaNormalize NaturalFold =-    NaturalFold-alphaNormalize NaturalBuild =-    NaturalBuild-alphaNormalize NaturalIsZero =-    NaturalIsZero-alphaNormalize NaturalEven =-    NaturalEven-alphaNormalize NaturalOdd =-    NaturalOdd-alphaNormalize NaturalToInteger =-    NaturalToInteger-alphaNormalize NaturalShow =-    NaturalShow-alphaNormalize (NaturalPlus l₀ r₀) =-    NaturalPlus l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (NaturalTimes l₀ r₀) =-    NaturalTimes l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize Integer =-    Integer-alphaNormalize (IntegerLit n) =-    IntegerLit n-alphaNormalize IntegerShow =-    IntegerShow-alphaNormalize Double =-    Double-alphaNormalize (DoubleLit n) =-    DoubleLit n-alphaNormalize DoubleShow =-    DoubleShow-alphaNormalize Text =-    Text-alphaNormalize (TextLit (Chunks xys₀ z)) =-    TextLit (Chunks xys₁ z)-  where-    xys₁ = do-        (x, y₀) <- xys₀-        let y₁ = alphaNormalize y₀-        return (x, y₁)-alphaNormalize (TextAppend l₀ r₀) =-    TextAppend l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize List =-    List-alphaNormalize (ListLit (Just _T₀) ts₀) =-    ListLit (Just _T₁) ts₁-  where-    _T₁ = alphaNormalize _T₀--    ts₁ = fmap alphaNormalize ts₀-alphaNormalize (ListLit Nothing ts₀) =-    ListLit Nothing ts₁-  where-    ts₁ = fmap alphaNormalize ts₀-alphaNormalize (ListAppend l₀ r₀) =-    ListAppend l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize ListBuild =-    ListBuild-alphaNormalize ListFold =-    ListFold-alphaNormalize ListLength =-    ListLength-alphaNormalize ListHead =-    ListHead-alphaNormalize ListLast =-    ListLast-alphaNormalize ListIndexed =-    ListIndexed-alphaNormalize ListReverse =-    ListReverse-alphaNormalize Optional =-    Optional-alphaNormalize (OptionalLit _T₀ ts₀) =-    OptionalLit _T₁ ts₁-  where-    _T₁ = alphaNormalize _T₀--    ts₁ = fmap alphaNormalize ts₀-alphaNormalize OptionalFold =-    OptionalFold-alphaNormalize OptionalBuild =-    OptionalBuild-alphaNormalize (Record kts₀) =-    Record kts₁-  where-    kts₁ = fmap alphaNormalize kts₀-alphaNormalize (RecordLit kvs₀) =-    RecordLit kvs₁-  where-    kvs₁ = fmap alphaNormalize kvs₀-alphaNormalize (Union kts₀) =-    Union kts₁-  where-    kts₁ = fmap alphaNormalize kts₀-alphaNormalize (UnionLit k v₀ kts₀) =-    UnionLit k v₁ kts₁-  where-    v₁ = alphaNormalize v₀--    kts₁ = fmap alphaNormalize kts₀-alphaNormalize (Combine l₀ r₀) =-    Combine l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (Prefer l₀ r₀) =-    Prefer l₁ r₁-  where-    l₁ = alphaNormalize l₀--    r₁ = alphaNormalize r₀-alphaNormalize (Merge t₀ u₀ _T₀) =-    Merge t₁ u₁ _T₁-  where-    t₁ = alphaNormalize t₀--    u₁ = alphaNormalize u₀--    _T₁ = fmap alphaNormalize _T₀-alphaNormalize (Constructors u₀) =-    Constructors u₁-  where-    u₁ = alphaNormalize u₀-alphaNormalize (Field e₀ a) =-    Field e₁ a-  where-    e₁ = alphaNormalize e₀-alphaNormalize (Note s e₀) =-    Note s e₁-  where-    e₁ = alphaNormalize e₀-alphaNormalize (Embed a) =-    Embed a--{-| Reduce an expression to its normal form, performing beta reduction--    `normalize` does not type-check the expression.  You may want to type-check-    expressions before normalizing them since normalization can convert an-    ill-typed expression into a well-typed expression.--    However, `normalize` will not fail if the expression is ill-typed and will-    leave ill-typed sub-expressions unevaluated.--}-normalize :: Eq a => Expr s a -> Expr t a-normalize = normalizeWith (const Nothing)--{-| This function is used to determine whether folds like @Natural/fold@ or-    @List/fold@ should be lazy or strict in their accumulator based on the type-    of the accumulator--    If this function returns `True`, then they will be strict in their-    accumulator since we can guarantee an upper bound on the amount of work to-    normalize the accumulator on each step of the loop.  If this function-    returns `False` then they will be lazy in their accumulator and only-    normalize the final result at the end of the fold--}-boundedType :: Expr s a -> Bool-boundedType Bool             = True-boundedType Natural          = True-boundedType Integer          = True-boundedType Double           = True-boundedType Text             = True-boundedType (App List _)     = False-boundedType (App Optional t) = boundedType t-boundedType (Record kvs)     = all boundedType kvs-boundedType (Union kvs)      = all boundedType kvs-boundedType _                = False---- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)-denote :: Expr s a -> Expr t a-denote (Note _ b            ) = denote b-denote (Const a             ) = Const a-denote (Var a               ) = Var a-denote (Lam a b c           ) = Lam a (denote b) (denote c)-denote (Pi a b c            ) = Pi a (denote b) (denote c)-denote (App a b             ) = App (denote a) (denote b)-denote (Let a b c d         ) = Let a (fmap denote b) (denote c) (denote d)-denote (Annot a b           ) = Annot (denote a) (denote b)-denote  Bool                  = Bool-denote (BoolLit a           ) = BoolLit a-denote (BoolAnd a b         ) = BoolAnd (denote a) (denote b)-denote (BoolOr a b          ) = BoolOr (denote a) (denote b)-denote (BoolEQ a b          ) = BoolEQ (denote a) (denote b)-denote (BoolNE a b          ) = BoolNE (denote a) (denote b)-denote (BoolIf a b c        ) = BoolIf (denote a) (denote b) (denote c)-denote  Natural               = Natural-denote (NaturalLit a        ) = NaturalLit a-denote  NaturalFold           = NaturalFold-denote  NaturalBuild          = NaturalBuild-denote  NaturalIsZero         = NaturalIsZero-denote  NaturalEven           = NaturalEven-denote  NaturalOdd            = NaturalOdd-denote  NaturalToInteger      = NaturalToInteger-denote  NaturalShow           = NaturalShow-denote (NaturalPlus a b     ) = NaturalPlus (denote a) (denote b)-denote (NaturalTimes a b    ) = NaturalTimes (denote a) (denote b)-denote  Integer               = Integer-denote (IntegerLit a        ) = IntegerLit a-denote  IntegerShow           = IntegerShow-denote  Double                = Double-denote (DoubleLit a         ) = DoubleLit a-denote  DoubleShow            = DoubleShow-denote  Text                  = Text-denote (TextLit (Chunks a b)) = TextLit (Chunks (fmap (fmap denote) a) b)-denote (TextAppend a b      ) = TextAppend (denote a) (denote b)-denote  List                  = List-denote (ListLit a b         ) = ListLit (fmap denote a) (fmap denote b)-denote (ListAppend a b      ) = ListAppend (denote a) (denote b)-denote  ListBuild             = ListBuild-denote  ListFold              = ListFold-denote  ListLength            = ListLength-denote  ListHead              = ListHead-denote  ListLast              = ListLast-denote  ListIndexed           = ListIndexed-denote  ListReverse           = ListReverse-denote  Optional              = Optional-denote (OptionalLit a b     ) = OptionalLit (denote a) (fmap denote b)-denote  OptionalFold          = OptionalFold-denote  OptionalBuild         = OptionalBuild-denote (Record a            ) = Record (fmap denote a)-denote (RecordLit a         ) = RecordLit (fmap denote a)-denote (Union a             ) = Union (fmap denote a)-denote (UnionLit a b c      ) = UnionLit a (denote b) (fmap denote c)-denote (Combine a b         ) = Combine (denote a) (denote b)-denote (Prefer a b          ) = Prefer (denote a) (denote b)-denote (Merge a b c         ) = Merge (denote a) (denote b) (fmap denote c)-denote (Constructors a      ) = Constructors (denote a)-denote (Field a b           ) = Field (denote a) b-denote (Embed a             ) = Embed a--{-| Reduce an expression to its normal form, performing beta reduction and applying-    any custom definitions.--    `normalizeWith` is designed to be used with function `typeWith`. The `typeWith`-    function allows typing of Dhall functions in a custom typing context whereas-    `normalizeWith` allows evaluating Dhall expressions in a custom context.--    To be more precise `normalizeWith` applies the given normalizer when it finds an-    application term that it cannot reduce by other means.--    Note that the context used in normalization will determine the properties of normalization.-    That is, if the functions in custom context are not total then the Dhall language, evaluated-    with those functions is not total either.---}-normalizeWith :: Eq a => Normalizer a -> Expr s a -> Expr t a-normalizeWith ctx e0 = loop (denote e0)- where- loop e =  case e of-    Const k -> Const k-    Var v -> Var v-    Lam x _A b -> Lam x _A' b'-      where-        _A' = loop _A-        b'  = loop b-    Pi  x _A _B -> Pi  x _A' _B'-      where-        _A' = loop _A-        _B' = loop _B-    App f a -> case loop f of-        Lam x _A b -> loop b''  -- Beta reduce-          where-            a'  = shift   1  (V x 0) a-            b'  = subst (V x 0) a' b-            b'' = shift (-1) (V x 0) b'-        f' -> case App f' a' of-            -- build/fold fusion for `List`-            App (App ListBuild _) (App (App ListFold _) e') -> loop e'--            -- build/fold fusion for `Natural`-            App NaturalBuild (App NaturalFold e') -> loop e'--            -- build/fold fusion for `Optional`-            App (App OptionalBuild _) (App (App OptionalFold _) e') -> loop e'--            App (App (App (App NaturalFold (NaturalLit n0)) t) succ') zero ->-                if boundedType (loop t) then strict else lazy-              where-                strict =       strictLoop n0-                lazy   = loop (  lazyLoop n0)--                strictLoop !0 = loop zero-                strictLoop !n = loop (App succ' (strictLoop (n - 1)))--                lazyLoop !0 = zero-                lazyLoop !n = App succ' (lazyLoop (n - 1))-            App NaturalBuild g -> loop (App (App (App g Natural) succ) zero)-              where-                succ = Lam "x" Natural (NaturalPlus "x" (NaturalLit 1))--                zero = NaturalLit 0-            App NaturalIsZero (NaturalLit n) -> BoolLit (n == 0)-            App NaturalEven (NaturalLit n) -> BoolLit (even n)-            App NaturalOdd (NaturalLit n) -> BoolLit (odd n)-            App NaturalToInteger (NaturalLit n) -> IntegerLit (toInteger n)-            App NaturalShow (NaturalLit n) ->-                TextLit (Chunks [] ("+" <> buildNatural n))-            App IntegerShow (IntegerLit n) ->-                TextLit (Chunks [] (buildNumber n))-            App DoubleShow (DoubleLit n) ->-                TextLit (Chunks [] (buildScientific n))-            App (App OptionalBuild _A₀) g ->-                loop (App (App (App g optional) just) nothing)-              where-                _A₁ = shift 1 "a" _A₀--                optional = App Optional _A₀--                just = Lam "a" _A₀ (OptionalLit _A₁ (pure "a"))--                nothing = OptionalLit _A₀ empty-            App (App ListBuild _A₀) g -> loop (App (App (App g list) cons) nil)-              where-                _A₁ = shift 1 "a" _A₀--                list = App List _A₀--                cons =-                    Lam "a" _A₀-                        (Lam "as"-                            (App List _A₁)-                            (ListAppend (ListLit Nothing (pure "a")) "as")-                        )--                nil = ListLit (Just _A₀) empty-            App (App (App (App (App ListFold _) (ListLit _ xs)) t) cons) nil ->-                if boundedType (loop t) then strict else lazy-              where-                strict =       foldr strictCons strictNil xs-                lazy   = loop (foldr   lazyCons   lazyNil xs)--                strictNil = loop nil-                lazyNil   =      nil--                strictCons y ys = loop (App (App cons y) ys)-                lazyCons   y ys =       App (App cons y) ys-            App (App ListLength _) (ListLit _ ys) ->-                NaturalLit (fromIntegral (Data.Sequence.length ys))-            App (App ListHead t) (ListLit _ ys) -> loop (OptionalLit t m)-              where-                m = case Data.Sequence.viewl ys of-                        y :< _ -> Just y-                        _      -> Nothing-            App (App ListLast t) (ListLit _ ys) -> loop (OptionalLit t m)-              where-                m = case Data.Sequence.viewr ys of-                        _ :> y -> Just y-                        _      -> Nothing-            App (App ListIndexed _A₀) (ListLit _A₁ as₀) ->-                loop (ListLit (Just _A₂) as₁)-              where-                as₁ = Data.Sequence.mapWithIndex adapt as₀--                _A₂ = Record (Data.HashMap.Strict.InsOrd.fromList kts)-                  where-                    kts = [ ("index", Natural)-                          , ("value", _A₀)-                          ]--                adapt n a_ =-                    RecordLit (Data.HashMap.Strict.InsOrd.fromList kvs)-                  where-                    kvs = [ ("index", NaturalLit (fromIntegral n))-                          , ("value", a_)-                          ]-            App (App ListReverse t) (ListLit _ xs) ->-                loop (ListLit m (Data.Sequence.reverse xs))-              where-                m = if Data.Sequence.null xs then Just t else Nothing-            App (App (App (App (App OptionalFold _) (OptionalLit _ xs)) _) just) nothing ->-                loop (maybe nothing just' xs)-              where-                just' = App just-            _ ->  case ctx (App f' a') of-                    Nothing -> App f' a'-                    Just app' -> loop app'-          where-            a' = loop a-    Let f _ r b -> loop b''-      where-        r'  = shift   1  (V f 0) r-        b'  = subst (V f 0) r' b-        b'' = shift (-1) (V f 0) b'-    Annot x _ -> loop x-    Bool -> Bool-    BoolLit b -> BoolLit b-    BoolAnd x y -> decide (loop x) (loop y)-      where-        decide (BoolLit True )  r              = r-        decide (BoolLit False)  _              = BoolLit False-        decide  l              (BoolLit True ) = l-        decide  _              (BoolLit False) = BoolLit False-        decide  l               r-            | judgmentallyEqual l r = l-            | otherwise             = BoolAnd l r-    BoolOr x y -> decide (loop x) (loop y)-      where-        decide (BoolLit False)  r              = r-        decide (BoolLit True )  _              = BoolLit True-        decide  l              (BoolLit False) = l-        decide  _              (BoolLit True ) = BoolLit True-        decide  l               r-            | judgmentallyEqual l r = l-            | otherwise             = BoolOr l r-    BoolEQ x y -> decide (loop x) (loop y)-      where-        decide (BoolLit True )  r              = r-        decide  l              (BoolLit True ) = l-        decide  l               r-            | judgmentallyEqual l r = BoolLit True-            | otherwise             = BoolEQ l r-    BoolNE x y -> decide (loop x) (loop y)-      where-        decide (BoolLit False)  r              = r-        decide  l              (BoolLit False) = l-        decide  l               r-            | judgmentallyEqual l r = BoolLit False-            | otherwise             = BoolNE l r-    BoolIf bool true false -> decide (loop bool) (loop true) (loop false)-      where-        decide (BoolLit True )  l              _              = l-        decide (BoolLit False)  _              r              = r-        decide  b              (BoolLit True) (BoolLit False) = b-        decide  b               l              r-            | judgmentallyEqual l r = l-            | otherwise             = BoolIf b l r-    Natural -> Natural-    NaturalLit n -> NaturalLit n-    NaturalFold -> NaturalFold-    NaturalBuild -> NaturalBuild-    NaturalIsZero -> NaturalIsZero-    NaturalEven -> NaturalEven-    NaturalOdd -> NaturalOdd-    NaturalToInteger -> NaturalToInteger-    NaturalShow -> NaturalShow-    NaturalPlus x y -> decide (loop x) (loop y)-      where-        decide (NaturalLit 0)  r             = r-        decide  l             (NaturalLit 0) = l-        decide (NaturalLit m) (NaturalLit n) = NaturalLit (m + n)-        decide  l              r             = NaturalPlus l r-    NaturalTimes x y -> decide (loop x) (loop y)-      where-        decide (NaturalLit 1)  r             = r-        decide  l             (NaturalLit 1) = l-        decide (NaturalLit 0)  _             = NaturalLit 0-        decide  _             (NaturalLit 0) = NaturalLit 0-        decide (NaturalLit m) (NaturalLit n) = NaturalLit (m * n)-        decide  l              r             = NaturalTimes l r-    Integer -> Integer-    IntegerLit n -> IntegerLit n-    IntegerShow -> IntegerShow-    Double -> Double-    DoubleLit n -> DoubleLit n-    DoubleShow -> DoubleShow-    Text -> Text-    TextLit (Chunks xys z) ->-        case mconcat chunks of-            Chunks [("", x)] "" -> x-            c                   -> TextLit c-      where-        chunks = concatMap process xys ++ [Chunks [] z]--        process (x, y) = case loop y of-            TextLit c -> [Chunks [] x, c]-            y'        -> [Chunks [(x, y')] mempty]-    TextAppend x y -> decide (loop x) (loop y)-      where-        isEmpty (Chunks [] "") = True-        isEmpty  _             = False--        decide (TextLit m)  r          | isEmpty m = r-        decide  l          (TextLit n) | isEmpty n = l-        decide (TextLit m) (TextLit n)             = TextLit (m <> n)-        decide  l           r                      = TextAppend l r-    List -> List-    ListLit t es -> ListLit t' es'-      where-        t'  = fmap loop t-        es' = fmap loop es-    ListAppend x y -> decide (loop x) (loop y)-      where-        decide (ListLit _ m)  r            | Data.Sequence.null m = r-        decide  l            (ListLit _ n) | Data.Sequence.null n = l-        decide (ListLit t m) (ListLit _ n)                        = ListLit t (m <> n)-        decide  l             r                                   = ListAppend l r-    ListBuild -> ListBuild-    ListFold -> ListFold-    ListLength -> ListLength-    ListHead -> ListHead-    ListLast -> ListLast-    ListIndexed -> ListIndexed-    ListReverse -> ListReverse-    Optional -> Optional-    OptionalLit t es -> OptionalLit t' es'-      where-        t'  =      loop t-        es' = fmap loop es-    OptionalFold -> OptionalFold-    OptionalBuild -> OptionalBuild-    Record kts -> Record kts'-      where-        kts' = fmap loop kts-    RecordLit kvs -> RecordLit kvs'-      where-        kvs' = fmap loop kvs-    Union kts -> Union kts'-      where-        kts' = fmap loop kts-    UnionLit k v kvs -> UnionLit k v' kvs'-      where-        v'   =      loop v-        kvs' = fmap loop kvs-    Combine x y -> decide (loop x) (loop y)-      where-        decide (RecordLit m) r | Data.HashMap.Strict.InsOrd.null m =-            r-        decide l (RecordLit n) | Data.HashMap.Strict.InsOrd.null n =-            l-        decide (RecordLit m) (RecordLit n) =-            RecordLit (Data.HashMap.Strict.InsOrd.unionWith decide m n)-        decide l r =-            Combine l r-    Prefer x y -> decide (loop x) (loop y)-      where-        decide (RecordLit m) r | Data.HashMap.Strict.InsOrd.null m =-            r-        decide l (RecordLit n) | Data.HashMap.Strict.InsOrd.null n =-            l-        decide (RecordLit m) (RecordLit n) =-            RecordLit (Data.HashMap.Strict.InsOrd.union n m)-        decide l r =-            Prefer l r-    Merge x y t      ->-        case x' of-            RecordLit kvsX ->-                case y' of-                    UnionLit kY vY _ ->-                        case Data.HashMap.Strict.InsOrd.lookup kY kvsX of-                            Just vX -> loop (App vX vY)-                            Nothing -> Merge x' y' t'-                    _ -> Merge x' y' t'-            _ -> Merge x' y' t'-      where-        x' =      loop x-        y' =      loop y-        t' = fmap loop t-    Constructors t   ->-        case t' of-            Union kts -> RecordLit kvs-              where-                kvs = Data.HashMap.Strict.InsOrd.mapWithKey adapt kts--                adapt k t_ = Lam k t_ (UnionLit k (Var (V k 0)) rest)-                  where-                    rest = Data.HashMap.Strict.InsOrd.delete k kts-            _ -> Constructors t'-      where-        t' = loop t-    Field r x        ->-        case loop r of-            RecordLit kvs ->-                case Data.HashMap.Strict.InsOrd.lookup x kvs of-                    Just v  -> loop v-                    Nothing -> Field (RecordLit (fmap loop kvs)) x-            r' -> Field r' x-    Note _ e' -> loop e'-    Embed a -> Embed a--{-| Returns `True` if two expressions are α-equivalent and β-equivalent and-    `False` otherwise--}-judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool-judgmentallyEqual eL0 eR0 = alphaBetaNormalize eL0 == alphaBetaNormalize eR0-  where-    alphaBetaNormalize :: Eq a => Expr s a -> Expr () a-    alphaBetaNormalize = alphaNormalize . normalize---- | Use this to wrap you embedded functions (see `normalizeWith`) to make them---   polymorphic enough to be used.-type Normalizer a = forall s. Expr s a -> Maybe (Expr s a)---- | Check if an expression is in a normal form given a context of evaluation.---   Unlike `isNormalized`, this will fully normalize and traverse through the expression.------   It is much more efficient to use `isNormalized`.-isNormalizedWith :: (Eq s, Eq a) => Normalizer a -> Expr s a -> Bool-isNormalizedWith ctx e = e == (normalizeWith ctx e)----- | Quickly check if an expression is in normal form-isNormalized :: Expr s a -> Bool-isNormalized e = case denote e of-    Const _ -> True-    Var _ -> True-    Lam _ a b -> isNormalized a && isNormalized b-    Pi _ a b -> isNormalized a && isNormalized b-    App f a -> isNormalized f && isNormalized a && case App f a of-        App (Lam _ _ _) _ -> False--        -- build/fold fusion for `List`-        App (App ListBuild _) (App (App ListFold _) _) -> False--        -- build/fold fusion for `Natural`-        App NaturalBuild (App NaturalFold _) -> False--        -- build/fold fusion for `Optional`-        App (App OptionalBuild _) (App (App OptionalFold _) _) -> False--        App (App (App (App NaturalFold (NaturalLit _)) _) _) _ -> False-        App NaturalBuild _ -> False-        App NaturalIsZero (NaturalLit _) -> False-        App NaturalEven (NaturalLit _) -> False-        App NaturalOdd (NaturalLit _) -> False-        App NaturalShow (NaturalLit _) -> False-        App NaturalToInteger (NaturalLit _) -> False-        App IntegerShow (IntegerLit _) -> False-        App DoubleShow (DoubleLit _) -> False-        App (App OptionalBuild _) _ -> False-        App (App ListBuild _) _ -> False-        App (App (App (App (App ListFold _) (ListLit _ _)) _) _) _ ->-            False-        App (App ListLength _) (ListLit _ _) -> False-        App (App ListHead _) (ListLit _ _) -> False-        App (App ListLast _) (ListLit _ _) -> False-        App (App ListIndexed _) (ListLit _ _) -> False-        App (App ListReverse _) (ListLit _ _) -> False-        App (App (App (App (App OptionalFold _) (OptionalLit _ _)) _) _) _ ->-            False-        _ -> True-    Let _ _ _ _ -> False-    Annot _ _ -> False-    Bool -> True-    BoolLit _ -> True-    BoolAnd x y -> isNormalized x && isNormalized y &&-        case x of-            BoolLit _ ->-                case y of-                    BoolLit _ -> False-                    _ -> True-            _ -> True-    BoolOr x y -> isNormalized x && isNormalized y &&-        case x of-            BoolLit _ ->-                case y of-                    BoolLit _ -> False-                    _ -> True-            _ -> True-    BoolEQ x y -> isNormalized x && isNormalized y &&-        case x of-            BoolLit _ ->-                case y of-                    BoolLit _ -> False-                    _ -> True-            _ -> True-    BoolNE x y -> isNormalized x && isNormalized y &&-        case x of-            BoolLit _ ->-                case y of-                    BoolLit _ -> False-                    _ -> True-            _ -> True-    BoolIf b true false -> isNormalized b && case b of-        BoolLit _ -> False-        _         -> isNormalized true && isNormalized false-    Natural -> True-    NaturalLit _ -> True-    NaturalFold -> True-    NaturalBuild -> True-    NaturalIsZero -> True-    NaturalEven -> True-    NaturalOdd -> True-    NaturalShow -> True-    NaturalToInteger -> True-    NaturalPlus x y -> isNormalized x && isNormalized y &&-        case x of-            NaturalLit _ ->-                case y of-                    NaturalLit _ -> False-                    _ -> True-            _ -> True-    NaturalTimes x y -> isNormalized x && isNormalized y &&-        case x of-            NaturalLit _ ->-                case y of-                    NaturalLit _ -> False-                    _ -> True-            _ -> True-    Integer -> True-    IntegerLit _ -> True-    IntegerShow -> True-    Double -> True-    DoubleLit _ -> True-    DoubleShow -> True-    Text -> True-    TextLit (Chunks xys _) -> all (all isNormalized) xys-    TextAppend x y -> isNormalized x && isNormalized y &&-        case x of-            TextLit _ ->-                case y of-                    TextLit _ -> False-                    _ -> True-            _ -> True-    List -> True-    ListLit t es -> all isNormalized t && all isNormalized es-    ListAppend x y -> isNormalized x && isNormalized y &&-        case x of-            ListLit _ _ ->-                case y of-                    ListLit _ _ -> False-                    _ -> True-            _ -> True-    ListBuild -> True-    ListFold -> True-    ListLength -> True-    ListHead -> True-    ListLast -> True-    ListIndexed -> True-    ListReverse -> True-    Optional -> True-    OptionalLit t es -> isNormalized t && all isNormalized es-    OptionalFold -> True-    OptionalBuild -> True-    Record kts -> all isNormalized kts-    RecordLit kvs -> all isNormalized kvs-    Union kts -> all isNormalized kts-    UnionLit _ v kvs -> isNormalized v && all isNormalized kvs-    Combine x y -> isNormalized x && isNormalized y && combine-      where-        combine = case x of-            RecordLit _ -> case y of-                RecordLit _ -> False-                _ -> True-            _ -> True-    Prefer x y -> isNormalized x && isNormalized y && combine-      where-        combine = case x of-            RecordLit _ -> case y of-                RecordLit _ -> False-                _ -> True-            _ -> True-    Merge x y t -> isNormalized x && isNormalized y && any isNormalized t &&-        case x of-            RecordLit kvsX ->-                case y of-                    UnionLit kY _  _ ->-                        case Data.HashMap.Strict.InsOrd.lookup kY kvsX of-                            Just _  -> False-                            Nothing -> True-                    _ -> True-            _ -> True-    Constructors t -> isNormalized t &&-        case t of-            Union _ -> False-            _       -> True-    Field r x -> isNormalized r &&-        case r of-            RecordLit kvs ->-                case Data.HashMap.Strict.InsOrd.lookup x kvs of-                    Just _  -> False-                    Nothing -> True-            _ -> True-    Note _ e' -> isNormalized e'-    Embed _ -> True--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--{-| Utility function used to throw internal errors that should never happen-    (in theory) but that are not enforced by the type system--}-internalError :: Data.Text.Text -> forall b . b-internalError text = error (unlines-    [ _ERROR <> ": Compiler bug                                                        "-    , "                                                                                "-    , "Explanation: This error message means that there is a bug in the Dhall compiler."-    , "You didn't do anything wrong, but if you would like to see this problem fixed   "-    , "then you should report the bug at:                                              "-    , "                                                                                "-    , "https://github.com/dhall-lang/dhall-haskell/issues                              "-    , "                                                                                "-    , "Please include the following text in your bug report:                           "-    , "                                                                                "-    , "```                                                                             "-    , Data.Text.unpack text <> "                                                       "-    , "```                                                                             "-    ] )---- | The set of reserved identifiers for the Dhall language-reservedIdentifiers :: HashSet Text-reservedIdentifiers =-    Data.HashSet.fromList-        [ "let"-        , "in"-        , "Type"-        , "Kind"-        , "forall"-        , "Bool"-        , "True"-        , "False"-        , "merge"-        , "if"-        , "then"-        , "else"-        , "as"-        , "using"-        , "constructors"-        , "Natural"-        , "Natural/fold"-        , "Natural/build"-        , "Natural/isZero"-        , "Natural/even"-        , "Natural/odd"-        , "Natural/toInteger"-        , "Natural/show"-        , "Integer"-        , "Integer/show"-        , "Double"-        , "Double/show"-        , "Text"-        , "List"-        , "List/build"-        , "List/fold"-        , "List/length"-        , "List/head"-        , "List/last"-        , "List/indexed"-        , "List/reverse"-        , "Optional"-        , "Optional/build"-        , "Optional/fold"-        ]+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE RecordWildCards #-}++{-| This module contains the core calculus for the Dhall language.++    Dhall is essentially a fork of the @morte@ compiler but with more built-in+    functionality, better error messages, and Haskell integration+-}++module Dhall.Core (+    -- * Syntax+      Const(..)+    , Directory(..)+    , File(..)+    , FilePrefix(..)+    , Import(..)+    , ImportHashed(..)+    , ImportMode(..)+    , ImportType(..)+    , URL(..)+    , Scheme(..)+    , DhallDouble(..)+    , Var(..)+    , Binding(..)+    , makeBinding+    , Chunks(..)+    , PreferAnnotation(..)+    , RecordField(..)+    , makeRecordField+    , FunctionBinding(..)+    , makeFunctionBinding+    , FieldSelection (..)+    , makeFieldSelection+    , WithComponent (..)+    , Expr(..)++    -- * Normalization+    , alphaNormalize+    , normalize+    , normalizeWith+    , normalizeWithM+    , Normalizer+    , NormalizerM+    , ReifiedNormalizer (..)+    , judgmentallyEqual+    , subst+    , shift+    , isNormalized+    , isNormalizedWith+    , denote+    , renote+    , shallowDenote+    , freeIn++    -- * Pretty-printing+    , pretty++    -- * Optics+    , subExpressions+    , subExpressionsWith+    , chunkExprs+    , bindingExprs+    , recordFieldExprs+    , functionBindingExprs++    -- * Let-blocks+    , multiLet+    , wrapInLets+    , MultiLet(..)++    -- * Miscellaneous+    , internalError+    , reservedIdentifiers+    , escapeText+    , pathCharacter+    , throws+    , Eval.textShow+    , censorExpression+    , censorText+    ) where++import Control.Exception      (Exception)+import Control.Monad.IO.Class (MonadIO (..))+import Data.Text              (Text)+import Dhall.Normalize+import Dhall.Pretty.Internal+import Dhall.Src              (Src (..))+import Dhall.Syntax+import Instances.TH.Lift      ()+import Lens.Micro             (over)+import Prettyprinter          (Pretty)++import qualified Control.Exception+import qualified Data.Text+import qualified Dhall.Eval        as Eval++-- | Pretty-print a value+pretty :: Pretty a => a -> Text+pretty = pretty_+{-# INLINE pretty #-}++{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules++    Note that the result does not include surrounding quotes+-}+escapeText :: Text -> Text+escapeText = escapeText_+{-# INLINE escapeText #-}+++{-| Utility used to implement the @--censor@ flag, by:++    * Replacing all `Src` text with spaces+    * Replacing all `Dhall.Syntax.Text` literals inside type errors with spaces+-}+censorExpression :: Expr Src a -> Expr Src a+censorExpression (TextLit chunks) = TextLit (censorChunks chunks)+censorExpression (Note src     e) = Note (censorSrc src) (censorExpression e)+censorExpression  e               = over subExpressions censorExpression e++censorChunks :: Chunks Src a -> Chunks Src a+censorChunks (Chunks xys z) = Chunks xys' z'+  where+    z' = censorText z++    xys' = [ (censorText x, censorExpression y) | (x, y) <- xys ]++{-| Utility used to censor `Data.Text.Text` by replacing all characters with a+    space+-}+censorText :: Text -> Text+censorText = Data.Text.map (\_ -> ' ')++censorSrc :: Src -> Src+censorSrc (Src { srcText = oldText, .. }) = Src { srcText = newText, .. }+  where+    newText = censorText oldText++{-| Convenience utility for converting `Either`-based exceptions to `IO`-based+    exceptions+-}+throws :: (Exception e, MonadIO io) => Either e a -> io a+throws (Left  e) = liftIO (Control.Exception.throwIO e)+throws (Right r) = return r+{-# INLINABLE throws #-}++{- $setup+>>> import qualified Codec.Serialise+>>> import qualified Dhall.Binary+>>> import Data.SpecialValues+>>> import Test.QuickCheck (Arbitrary(..), oneof, elements)+>>> :{+  instance Arbitrary DhallDouble where+    arbitrary = fmap DhallDouble (oneof [ arbitrary, elements specialValues ])+:}+-}
− src/Dhall/Core.hs-boot
@@ -1,7 +0,0 @@-module Dhall.Core where--data Const--data Var--data Expr s a
+ src/Dhall/Deriving.hs view
@@ -0,0 +1,547 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE PolyKinds            #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Newtypes for writing customizable 'FromDhall' and 'ToDhall' instances+    through the DerivingVia strategy.++    Inspired by Matt Parson's blog post+    [Mirror Mirror: Reflection and Encoding Via](https://www.parsonsmatt.org/2020/02/04/mirror_mirror.html),+    but applied to Dhall instead of JSON.++    This module is intended to be used with+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    so it's only available for GHC >= v8.6.1.++    Check the section /Letting DerivingVia do the work/ if you want to see this module in action. (Click "Dhall.Deriving#derivingVia" to jump there)++-}++module Dhall.Deriving+  (+    -- * Introduction+    -- $introduction++    -- * Writing FromDhall instances by hand+    -- $instancesByHand++    -- * Letting DerivingVia do the work+    -- $derivingVia++    -- * Behind the scenes of Codec+    -- $behindTheScenes++    -- * DerivingVia newtype+    Codec (..)++    -- * Type-level functions on InterpretOptions+  , ModifyOptions (..)+  , Field+  , Constructor+  , SetSingletonConstructors++    -- * Type-level functions on Text+  , TextFunction (..)+  , DropPrefix+  , TitleCase+  , CamelCase+  , PascalCase+  , SnakeCase+  , SpinalCase+  , TrainCase++    -- * Type-level versions of SingletonConstructors+  , ToSingletonConstructors(..)+  , Bare+  , Wrapped+  , Smart++    -- * Identity and Composition for ModifyOptions and TextFunction+  , AsIs+  , type (<<<)++    -- * Helper function on Text+  , dropPrefix++    -- * InterpretOptions setters+  , addFieldModifier+  , addConstructorModifier+  , setSingletonConstructors++  ) where++import Data.Proxy   (Proxy (..))+import Dhall+import GHC.Generics (Generic (Rep))+import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)++import qualified Data.Text            as Text+import qualified Data.Text.Manipulate as Case++-- | Intended for use on @deriving via@ clauses for types with a+--   'Generic' instance. The @tag@ argument is used to construct an+--   'InterpretOptions' value which is used as the first argument+--   to 'genericAutoWith'.+newtype Codec tag a = Codec { unCodec :: a }++instance (Generic a, GenericFromDhall a (Rep a), ModifyOptions tag) => FromDhall (Codec tag a) where+  autoWith _ = Codec <$> genericAutoWith (modifyOptions @tag defaultInterpretOptions)++instance (Generic a, GenericToDhall (Rep a), ModifyOptions tag) => ToDhall (Codec tag a) where+  injectWith _ = unCodec >$< genericToDhallWith (modifyOptions @tag defaultInterpretOptions)++-- | Convert a type into a @InterpretOptions -> InterpretOptions@ function+class ModifyOptions a where+  modifyOptions :: InterpretOptions -> InterpretOptions+++-- | The identity for functions on 'InterpretOptions' and on @Text@.+--   Useful for deriving @FromDhall@ and @ToDhall@ with the default options.+type AsIs = ()++instance ModifyOptions AsIs where+  modifyOptions = id++instance TextFunction AsIs where+  textFunction = id+++-- | Composition for functions on 'InterpretOptions' and on @Text@.+--   We use @<<<@ since @.@ isn't a valid type operator yet+--   (it will be valid starting from ghc-8.8.1)+data a <<< b+infixr 1 <<<++instance (ModifyOptions a, ModifyOptions b) => ModifyOptions (a <<< b) where+  modifyOptions = modifyOptions @a . modifyOptions @b++instance (TextFunction a, TextFunction b) => TextFunction (a <<< b) where+  textFunction = textFunction @a . textFunction @b+++-- | @Field t@ post-composes the @fieldModifier@ from @options@ with the+--   value-level version of @t@, obtained with @TextFunction@+data Field a+instance TextFunction a => ModifyOptions (Field a) where+  modifyOptions = addFieldModifier (textFunction @a)++-- | @Constructor t@ post-composes the @constructorModifier@ from @options@+--   with the value-level version of @t@, obtained with @TextFunction@+data Constructor a+instance TextFunction a => ModifyOptions (Constructor a) where+  modifyOptions = addConstructorModifier (textFunction @a)+++-- * Text Functions++-- | Convert a type into a @Text -> Text@ function+class TextFunction a where+  textFunction :: Text -> Text++-- | @DropPrefix prefix@ corresponds to the value level+--   function @'dropPrefix' prefix@+data DropPrefix (s :: Symbol)+instance KnownSymbol s => TextFunction (DropPrefix s) where+  textFunction = dropPrefix (Text.pack (symbolVal @s Proxy))++-- | Convert casing to @Title Cased Phrase@+data TitleCase+instance TextFunction TitleCase where+  textFunction = Case.toTitle++-- | Convert casing to @camelCasedPhrase@+data CamelCase+instance TextFunction CamelCase where+  textFunction = Case.toCamel++-- | Convert casing to @PascalCasedPhrase@+data PascalCase+instance TextFunction PascalCase where+  textFunction = Case.toPascal++-- | Convert casing to @snake_cased_phrase@+data SnakeCase+instance TextFunction SnakeCase where+  textFunction = Case.toSnake++-- | Convert casing to @spinal-cased-phrase@+data SpinalCase+instance TextFunction SpinalCase where+  textFunction = Case.toSpinal++-- | Convert casing to @Train-Cased-Phrase@+data TrainCase+instance TextFunction TrainCase where+  textFunction = Case.toTrain+++-- | @SetSingletonConstructors t@ replaces the @singletonConstructors@+--  from @options@ with the value-level version of @t@.+data SetSingletonConstructors a+instance ToSingletonConstructors a => ModifyOptions (SetSingletonConstructors a) where+  modifyOptions = setSingletonConstructors (asSingletonConstructors @a)++-- | Convert a type of kind @SingletonConstructors@+--   into a value of type @SingletonConstructors@+class ToSingletonConstructors (a :: SingletonConstructors) where+  asSingletonConstructors :: SingletonConstructors++-- | Type-level version of 'Dhall.Bare'.+-- Never wrap the field of a singleton constructor in a record+type Bare = 'Bare+instance ToSingletonConstructors Bare where+  asSingletonConstructors = Bare++-- | Type-level version of 'Dhall.Wrapped'+-- Always wrap the field of a singleton constructor in a record+type Wrapped = 'Wrapped+instance ToSingletonConstructors Wrapped where+  asSingletonConstructors = Wrapped++-- | Type-level version of 'Dhall.Smart'+-- Wrap the field of a singleton constructor in a record+-- only if the field is named+type Smart = 'Smart+instance ToSingletonConstructors Smart where+  asSingletonConstructors = Smart+++-- * Text helper++-- | @dropPrefix prefix text@ returns the suffix of @text@ if its prefix+--   matches @prefix@, or the entire @text@ otherwise+dropPrefix :: Text -> (Text -> Text)+dropPrefix prefix text = case Text.stripPrefix prefix text of+  Nothing -> text+  Just e -> e++-- * InterpretOptions setters++-- | @addFieldModifier f options@ post-composes the @fieldModifier@+--  from @options@ with @f@.+addFieldModifier :: (Text -> Text) -> InterpretOptions -> InterpretOptions+addFieldModifier f options = options+  { fieldModifier = f . fieldModifier options }++-- | @addConstructorModifier f options@ post-composes the @constructorModifier@+--   from @options@ with @f@.+addConstructorModifier :: (Text -> Text) -> InterpretOptions -> InterpretOptions+addConstructorModifier f options = options+  { constructorModifier = f . constructorModifier options }++-- | @setSingletonConstructors v options@ replaces the @singletonConstructors@+--  from @options@ with @v@.+setSingletonConstructors :: SingletonConstructors -> InterpretOptions -> InterpretOptions+setSingletonConstructors v options = options+  { singletonConstructors = v }++{- $introduction++Let's take the following Haskell data types:++>>> :set -XDerivingStrategies++>>> :{+newtype Name = Name { getName :: Text }+  deriving stock (Show)+:}++>>> :{+data Font = Arial | ComicSans | Helvetica | TimesNewRoman+  deriving stock (Show)+:}++>>> :{+data Person = Person+  { personName :: Name+  , personFavoriteFont :: Font+  }+  deriving stock (Show)+:}++And assume we want to read the following Dhall file as a @Person@:++@+-- ./simon.dhall+let Name = Text+let Font = \< Arial | `Comic Sans` | Helvetica | `Times New Roman` \>+let Person = { name : Name, favoriteFont : Font }+in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person+@++Usually, you would build a 'Decoder' by hand, like this++>>> :{+font :: Decoder Font+font =+  union+    (  (Arial         <$ constructor "Arial"           unit)+    <> (ComicSans     <$ constructor "Comic Sans"      unit)+    <> (Helvetica     <$ constructor "Helvetica"       unit)+    <> (TimesNewRoman <$ constructor "Times New Roman" unit)+    )+:}++>>> :{+name :: Decoder Name+name = Name <$> strictText+:}++>>> :{+person :: Decoder Person+person =+  record+    ( Person <$> field "name"         name+             <*> field "favoriteFont" font+    )+:}++and then you use it like this++>>> input person "./simon.dhall"+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++So, it works! However, this is quite mechanic, and the compiler has pretty+much all the information it needs to do it for you. Besides, you'd like to+provide an instance of 'FromDhall' so you can use the polymorphic 'Decoder'+'auto' instead of explicitly calling @person@.+-}++{- $instancesByHand+"Aha!," you think, "I'll write an empty @instance 'FromDhall' Person@".+That in turn requires you to add two other instances for @Font@ and for @Name@,+plus 'Generic' instances for each of those, but that's okay.++>>> :set -XStandaloneDeriving+>>> :set -XDeriveGeneric++>>> :{+deriving stock instance Generic Name+deriving stock instance Generic Font+deriving stock instance Generic Person+:}++>>> :{+instance FromDhall Name+instance FromDhall Font+instance FromDhall Person+:}++However, when you try to read the same file with 'auto', you get this:++>>> input auto "./simon.dhall" :: IO Person+*** Exception:+...Error...: Expression doesn't match annotation+...+{ - personFavoriteFont : …+, - personName : …+, + favoriteFont : …+, + name : …+}+...+1│ ./simon.dhall : { personName : { getName : Text }+2│ , personFavoriteFont : < Arial | ComicSans | Helvetica | TimesNewRoman >+3│ }+...++What happened? The field names don't quite match, since we're using prefixed+field names in Haskell but no prefixes in Dhall. "Okay," you think,+"I can write a custom instance which builds on 'Generic' thanks to+'genericAutoWith', I only need to supply a function to drop the prefixes+and @camelCase@ the rest". So, using 'Data.Text.Manipulate.toCamel':++>>> import Data.Text.Manipulate (toCamel)+>>> import qualified Data.Text as Text+>>> :{+instance FromDhall Person where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { fieldModifier = toCamel . Text.drop (Text.length "person") }+:}++Let's try to read that again:++>>> input auto "./simon.dhall":: IO Person+*** Exception:+...Error...: Expression doesn't match annotation+...+{ favoriteFont : < - ComicSans : …+                 | - TimesNewRoman : …+                 | + `Comic Sans` : …+                 | + `Times New Roman` : …+                 | …+                 >+, name : - { … : … } (a record type)+         + Text+}+...+1│ ./simon.dhall : { name : { getName : Text }+2│ , favoriteFont : < Arial | ComicSans | Helvetica | TimesNewRoman >+3│ }+...++Okay, we're almost there. We have two things to solve now.+First, the @Font@ constructors are @PascalCased@ in Haskell,+but @Title Cased@ in Dhall. We can communicate this to our+'FromDhall' instance using 'Data.Text.Manipulate.toTitle':++>>> import Data.Text.Manipulate (toTitle)+>>> :{+instance FromDhall Font where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { constructorModifier = toTitle }+:}++Second, we defined the @Name@ type in Haskell as a newtype over @Text@, with a+@getName@ field for unwrapping. In Dhall, however, @Name@ is a synonym of+'Data.Text.Text', which is why 'Dhall.input' above was expecting a record.+The 'Dhall.Bare' option for 'singletonConstructors' is a perfect fit here:+it translates Haskell singleton constructors into the Dhall version of the+nested type, without wrapping it into a record.+We can then tweak our 'FromDhall' instance like this:++>>> :{+instance FromDhall Name where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { singletonConstructors = Bare }+:}++Since we're running this interactively, we also need to update the+instance for @Person@, but it's the same as before.++>>> :{+instance FromDhall Person where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { fieldModifier = toCamel . Text.drop (Text.length "person") }+:}++Now, for the moment of truth:++>>> input auto "./simon.dhall":: IO Person+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++That took a bit more work than we wanted, though, and a lot of it was just+boilerplate for defining the instances through `genericAutoWith`, tweaking+a single parameter at a time. Even worse, if we also wanted to provide+'ToDhall' instances we would need to keep the options in sync between both+instances, since otherwise the values wouldn't be able to round-trip from+Dhall to Dhall through Haskell.++-}++{- $derivingVia+   #derivingVia#++Starting with this dhall file:++@+-- ./simon.dhall+let Name = Text+let Font = \< Arial | `Comic Sans` | Helvetica | `Times New Roman` \>+let Person = { name : Name, favoriteFont : Font }+in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person+@++We can define the equivalent Haskell types as follows. Note that we+derive the 'FromDhall' and 'ToDhall' instances @via 'Codec' tag TheType@,+using a different @tag@ depending on the transformations we need to apply to+the Haskell type to get the Dhall equivalent:++>>> :set -XDataKinds+>>> :set -XDeriveGeneric+>>> :set -XDerivingVia+>>> :set -XTypeOperators++>>> :{+newtype Name = Name { getName :: Text }+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (SetSingletonConstructors Bare) Name+:}++>>> :{+data Font = Arial | ComicSans | Helvetica | TimesNewRoman+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (Constructor TitleCase) Font+:}++>>> :{+data Person = Person+  { personName :: Name+  , personFavoriteFont :: Font+  }+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (Field (CamelCase <<< DropPrefix "person")) Person+:}++we can then read the file using 'auto':++>>> simon <- input auto "./simon.dhall":: IO Person+>>> print simon+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++And using 'inject' we can get @simon@ back as a Dhall value:++>>> import qualified Data.Text.IO as Text+>>> import Dhall.Core (pretty)+>>> Text.putStrLn . pretty . embed inject $ simon+{ name = "Simon"+, favoriteFont =+    < Arial | `Comic Sans` | Helvetica | `Times New Roman` >.`Comic Sans`+}++-}++{- $behindTheScenes++@'Codec' tag a@ is really just a newtype over @a@, equipped with a+phantom @tag@. The 'FromDhall' instance for 'Codec' uses the generic+representation of @a@, together with the 'InterpretOptions' defined by @tag@ as+a series of modifications to be applied on 'defaultInterpretOptions'.++For the default behavior, using 'AsIs' (a synonym for @()@) as the @tag@+leaves the interpret options alone, so it's equivalent to the empty instance+we first tried to use.++@'Field' a@ and @'Constructor' a@ can be used to modify, respectively, the+'fieldModifier' and 'constructorModifier' options of 'InterpretOptions', by+post-composing the modifier with @'textFunction' \@a@, that is, the value-level+equivalent of @a@, obtained through the 'TextFunction' class.++In the case of @Person@, we used++@+  Codec (Field (CamelCase <<< DropPrefix "person")) Person+@++which means that the @Text -> Text@ version of++@+  CamelCase <<< DropPrefix "person"+@++was used to modify the @fieldModifier@ option.++In the value level, this translates to composing ('<<<')+'Data.Text.Manipulate.toCamel' ('CamelCase') with @'dropPrefix' "person"@+(@'DropPrefix' "person"@).++Finally, @'SetSingletonConstructors' a@ can be used to set the+'singletonConstructors' option of 'InterpretOptions', by replacing the option+with the value-level equivalent of @a@.+-}++{- $setup+>>> :set -XOverloadedStrings+-}
+ src/Dhall/Diff.hs view
@@ -0,0 +1,1477 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE ViewPatterns      #-}++{-| This module provides functionality for concisely displaying the difference+    between two expressions++    For example, this is used in type errors to explain why the actual type does+    not match the expected type+-}++module Dhall.Diff (+    -- * Diff+      Diff (..)+    , diffNormalized+    , diff+    ) where++import Data.ByteString       (ByteString)+import Data.Foldable         (fold, toList)+import Data.List.NonEmpty    (NonEmpty (..))+import Data.Monoid           (Any (..))+import Data.Sequence         (Seq)+import Data.String           (IsString (..))+import Data.Text             (Text)+import Data.Void             (Void)+import Dhall.Map             (Map)+import Dhall.Pretty.Internal (Ann)+import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Expr (..)+    , FunctionBinding (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )+import Numeric.Natural       (Natural)+import Prettyprinter         (Doc, Pretty)++import qualified Data.Algorithm.Diff   as Algo.Diff+import qualified Data.List.NonEmpty+import qualified Data.Set+import qualified Data.Text+import qualified Data.Time             as Time+import qualified Dhall.Map+import qualified Dhall.Normalize       as Normalize+import qualified Dhall.Pretty.Internal as Internal+import qualified Dhall.Syntax          as Syntax+import qualified Prettyprinter         as Pretty++{-| This type is a `Doc` enriched with a `same` flag to efficiently track if+    any difference was detected+-}+data Diff =+    Diff+        { same :: Bool+        , doc  :: Doc Ann+        }++instance Semigroup Diff where+    Diff sameL docL <> Diff sameR docR = Diff (sameL && sameR) (docL <> docR)++instance Monoid (Diff) where+    mempty = Diff {..}+      where+        same = True++        doc = mempty++instance IsString (Diff) where+    fromString string = Diff {..}+      where+        same = True++        doc = fromString string++ignore :: Diff+ignore = "…"++align :: Diff -> Diff+align (Diff {doc = docOld, ..}) = Diff {doc = Pretty.align docOld, .. }++hardline :: Diff+hardline = token Pretty.hardline++minus :: Diff -> Diff+minus l = ("- " <> l) { same = False }++plus :: Diff -> Diff+plus r = ("+ " <> r) { same = False }++difference :: Diff -> Diff -> Diff+difference l r = align (minus l <> hardline <> plus r)++token :: Doc Ann -> Diff+token doc = Diff {..}+  where+    same = True++format :: Diff -> Diff -> Diff+format suffix doc = doc <> (if same doc then suffix else hardline)++builtin :: Doc Ann -> Diff+builtin doc = token (Internal.builtin doc)++keyword :: Doc Ann -> Diff+keyword doc = token (Internal.keyword doc)++operator :: Doc Ann -> Diff+operator doc = token (Internal.operator doc)++colon :: Diff+colon = token Internal.colon++comma :: Diff+comma = token Internal.comma++dot :: Diff+dot = token Internal.dot++equals :: Diff+equals = token Internal.equals++forall_ :: Diff+forall_ = token (Internal.forall_ Internal.Unicode)++lambda :: Diff+lambda = token (Internal.lambda Internal.Unicode)++langle :: Diff+langle = token Internal.langle++lbrace :: Diff+lbrace = token Internal.lbrace++lbracket :: Diff+lbracket = token Internal.lbracket++lparen :: Diff+lparen = token Internal.lparen++pipe :: Diff+pipe = token Internal.pipe++rangle :: Diff+rangle = token Internal.rangle++rarrow :: Diff+rarrow = token (Internal.rarrow Internal.Unicode)++rbrace :: Diff+rbrace = token Internal.rbrace++rbracket :: Diff+rbracket = token Internal.rbracket++rparen :: Diff+rparen = token Internal.rparen++-- | Render the difference between the normal form of two expressions+diffNormalized :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffNormalized l0 r0 = Dhall.Diff.diff l1 r1+  where+    l1 = Normalize.alphaNormalize (Normalize.normalize l0)+    r1 = Normalize.alphaNormalize (Normalize.normalize r0)++diffPrimitive :: Eq a => (a -> Diff) -> a -> a -> Diff+diffPrimitive f l r+    | l == r    = ignore+    | otherwise = difference (f l) (f r)++diffLabel :: Text -> Text -> Diff+diffLabel = diffPrimitive (token . Internal.prettyLabel)++diffLabels :: [Text] -> [Text] -> Diff+diffLabels ksL ksR =+    braced (diffFieldNames <> (if anyEqual then [ ignore ] else []))+  where+    setL = Data.Set.fromList ksL+    setR = Data.Set.fromList ksR++    extraL = Data.Set.difference setL setR+    extraR = Data.Set.difference setR setL++    diffFieldNames = foldMap (adapt minus) extraL <> foldMap (adapt plus) extraR+      where+        adapt sign key = [ sign (token (Internal.prettyLabel key)) ]++    anyEqual = not (Data.Set.null (Data.Set.intersection setL setR))++diffNatural :: Natural -> Natural -> Diff+diffNatural = diffPrimitive (token . Internal.prettyNatural)++diffDouble :: DhallDouble -> DhallDouble -> Diff+diffDouble = diffPrimitive (token . Internal.prettyDouble . getDhallDouble)++diffDateLiteral :: Time.Day -> Time.Day -> Diff+diffDateLiteral =+    diffPrimitive (token . Internal.prettyExpr @(Expr Void Void) . DateLiteral)++diffTimeLiteral :: Time.TimeOfDay -> Word -> Time.TimeOfDay -> Word -> Diff+diffTimeLiteral tL pL tR pR =+    diffPrimitive+        (token . Internal.prettyExpr @(Expr Void Void) . uncurry TimeLiteral)+        (tL, pL)+        (tR, pR)++diffTimeZoneLiteral :: Time.TimeZone -> Time.TimeZone -> Diff+diffTimeZoneLiteral =+    diffPrimitive+        (token . Internal.prettyExpr @(Expr Void Void) . TimeZoneLiteral)++diffConst :: Const -> Const -> Diff+diffConst = diffPrimitive (token . Internal.prettyConst)++diffBool :: Bool -> Bool -> Diff+diffBool = diffPrimitive bool+  where+    bool True  = builtin "True"+    bool False = builtin "False"++diffInteger :: Integer -> Integer -> Diff+diffInteger = diffPrimitive (token . Internal.prettyNumber)++diffInt :: Int -> Int -> Diff+diffInt = diffPrimitive (token . Internal.prettyInt)++diffVar :: Var -> Var -> Diff+diffVar (V xL nL) (V xR nR) =+    format mempty label <> if same natural then mempty else "@" <> natural+  where+    label = diffLabel xL xR++    natural = diffInt nL nR++diffPretty :: (Eq a, Pretty a) => a -> a -> Diff+diffPretty = diffPrimitive (token . Pretty.pretty)++diffMaybe :: Diff -> (a -> a -> Diff) -> (Maybe a -> Maybe a -> Diff)+diffMaybe _ _ Nothing Nothing =+    mempty+diffMaybe prefix _ Nothing (Just _) =+    difference mempty (prefix <> ignore)+diffMaybe prefix _ (Just _) Nothing =+    difference (prefix <> ignore) mempty+diffMaybe prefix f (Just l) (Just r) =+    prefix <> f l r++enclosed+    :: Diff+    -> Diff+    -> Diff+    -> [Diff]+    -> Diff+enclosed l _ r []   = l <> r+enclosed l m r docs = align (fold (zipWith (<>) prefixes docs) <> suffix)+  where+    prefixes = l : repeat (hardline <> m)++    suffix = hardline <> r++enclosed'+    :: Diff+    -> Diff+    -> NonEmpty (Diff)+    -> Diff+enclosed' l m docs =+    align (fold (Data.List.NonEmpty.zipWith (<>) prefixes docs))+  where+    prefixes = l :| repeat (hardline <> m)++diffKeyVals+    :: (Eq a, Pretty a)+    => Diff+    -> Map Text (RecordField Void a)+    -> Map Text (RecordField Void a)+    -> [Diff]+diffKeyVals assign kvsL kvsR = diffKeysWith assign diff+    (recordFieldValue <$> kvsL)+    (recordFieldValue <$> kvsR)++diffKeysWith+    :: Diff+    -> (a -> a -> Diff)+    -> Map Text a+    -> Map Text a+    -> [Diff]+diffKeysWith assign diffVals kvsL kvsR =+    diffFieldNames <> diffFieldValues <> (if anyEqual then [ ignore ] else [])+  where+    ksL = Dhall.Map.keysSet kvsL+    ksR = Dhall.Map.keysSet kvsR++    extraL = Data.Set.difference ksL ksR+    extraR = Data.Set.difference ksR ksL++    diffFieldNames = foldMap (adapt minus) extraL <> foldMap (adapt plus) extraR+      where+        adapt sign key =+            [   sign (token (Internal.prettyLabel key))+            <>  " "+            <>  assign+            <>  " "+            <>  ignore+            ]++    shared = Dhall.Map.intersectionWith diffVals kvsL kvsR++    diffFieldValues =+        filter (not . same) (Dhall.Map.foldMapWithKey adapt shared)+      where+        adapt key doc =+            [   (if ksL == ksR then mempty else "  ")+            <>  token (Internal.prettyLabel key)+            <>  " "+            <>  assign+            <>  " "+            <>  doc+            ]++    anyEqual = getAny (foldMap (Any . same) shared)++braced :: [Diff] -> Diff+braced = enclosed (lbrace <> " ") (comma <> " ") rbrace++angled :: [Diff] -> Diff+angled = enclosed (langle <> " ") (pipe <> " ") rangle++bracketed :: [Diff] -> Diff+bracketed = enclosed (lbracket <> " ") (comma <> " ") rbracket++diffText :: Text -> Text -> Diff+diffText l r = "\"" <> foldMap prettyPart parts <> "\""+  where+    -- TODO: check for color support from the TTY+    colorDiff colorCode chars =+            "\ESC["+        <>  colorCode+        <>  "m"+        <>  fromString chars+        <>  "\ESC[0m"++    prettyPart part =+      case part of+        -- Only present in left+        Algo.Diff.First  chars ->+            -- Red background+            (colorDiff "41" chars) { same = False }++        -- Only present in right+        Algo.Diff.Second chars ->+            -- Green background+            (colorDiff "42" chars) { same = False }++        -- Present in both+        Algo.Diff.Both _ chars ->+            -- Dim foreground+            colorDiff "2" chars++    parts = Algo.Diff.getGroupedDiff (Data.Text.unpack l) (Data.Text.unpack r)++diffChunks+    :: (Eq a, Pretty a)+    => Chunks Void a -> Chunks Void a -> Diff+diffChunks cL cR+  | null chunks             = "\"\""+  | [c] <- chunks           = c+  | otherwise               = align (enclosed "   " "++ " "" chunks)+  where+    toEitherList (Chunks te t) =+        concatMap (\(a, b) -> [Left a, Right b]) te ++ [Left t]++    diffTextSkeleton = difference textSkeleton textSkeleton++    chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR)++    chunkDiff a b =+      case (a, b) of+        (Left  x, Left y ) -> diffText x y+        (Right x, Right y) -> diff x y+        _                  -> diffTextSkeleton++diffBytes :: ByteString -> ByteString -> Diff+diffBytes l r =+    "0x" <> diffText (Internal.prettyBase16 l) (Internal.prettyBase16 r)++diffList+    :: (Eq a, Pretty a)+    => Seq (Expr Void a) -> Seq (Expr Void a) -> Diff+diffList l r = bracketed (loop parts₀)+  where+    -- Sections of the list that are only in left, only in right, or in both+    parts₀ = Algo.Diff.getGroupedDiffBy equal (toList l) (toList r)++    equal a b = same (diff a b)++    -- Render each element of a list using an extra rendering function f+    prettyElems f = map (f . token . Internal.prettyExpr)++    loop [] =+        mempty+    loop (Algo.Diff.First as : Algo.Diff.Second bs : parts)+        | length as == length bs = zipWith diff as bs <> loop parts+    loop (part : parts) =+        diffPart part <> loop parts++    diffPart part =+      case part of+        -- Only present in left+        Algo.Diff.First  elements ->+            prettyElems minus elements++        -- Only present in right+        Algo.Diff.Second elements ->+            prettyElems plus  elements++        -- Present in both+        Algo.Diff.Both _ _        ->+            pure ignore++diffRecord+    :: (Eq a, Pretty a)+    => Map Text (RecordField Void a) -> Map Text (RecordField Void a) -> Diff+diffRecord kvsL kvsR = braced (diffKeyVals colon kvsL kvsR)++diffRecordLit+    :: (Eq a, Pretty a)+    => Map Text (RecordField Void a) -> Map Text (RecordField Void a) -> Diff+diffRecordLit kvsL kvsR = braced (diffKeyVals equals kvsL kvsR)++diffUnion+    :: (Eq a, Pretty a)+    => Map Text (Maybe (Expr Void a)) -> Map Text (Maybe (Expr Void a)) -> Diff+diffUnion kvsL kvsR = angled (diffKeysWith colon diffVals kvsL kvsR)+  where+    diffVals = diffMaybe (colon <> " ") diff++textSkeleton :: Diff+textSkeleton =+        "\""+    <>  ignore+    <>  "\""++skeleton :: Pretty a => Expr s a -> Diff+skeleton (Lam {}) =+        lambda+    <>  lparen+    <>  ignore+    <>  " "+    <>  colon+    <>  " "+    <>  ignore+    <>  rparen+    <>  " "+    <>  rarrow+    <>  " "+    <>  ignore+    <> " (a function)"+skeleton (Pi {}) =+        ignore+    <>  " "+    <>  rarrow+    <>  " "+    <>  ignore+    <> " (a function type)"+skeleton (App Optional _) =+        "Optional "+    <>  ignore+skeleton (App None _) =+        "None "+    <>  ignore+skeleton (Some _) =+        "Some "+    <>  ignore+skeleton (App List _) =+        "List "+    <>  ignore+skeleton (App {}) =+        ignore+    <>  " "+    <>  ignore+skeleton (Let {}) =+        keyword "let"+    <>  " "+    <>  ignore+    <>  " "+    <>  equals+    <>  " "+    <>  ignore+    <>  " "+    <>  keyword "in"+    <>  " "+    <>  ignore+skeleton (Annot {}) =+        ignore+    <>  " "+    <>  colon+    <>  " "+    <>  ignore+skeleton (BoolAnd {}) =+        ignore+    <>  " "+    <>  operator "&&"+    <>  " "+    <>  ignore+skeleton (BoolOr {}) =+        ignore+    <>  " "+    <>  operator "||"+    <>  " "+    <>  ignore+skeleton (BoolEQ {}) =+        ignore+    <>  " "+    <>  operator "=="+    <>  " "+    <>  ignore+skeleton (BoolNE {}) =+        ignore+    <>  " "+    <>  operator "!="+    <>  " "+    <>  ignore+skeleton (BoolIf {}) =+        keyword "if"+    <>  " "+    <>  ignore+    <>  " "+    <>  keyword "then"+    <>  " "+    <>  ignore+    <>  " "+    <>  keyword "else"+    <>  " "+    <>  ignore+skeleton (BytesLit {}) =+        "0x\""+    <>  ignore+    <>  "\""+skeleton (NaturalPlus {}) =+        ignore+    <>  " "+    <>  operator "+"+    <>  " "+    <>  ignore+skeleton (NaturalTimes {}) =+        ignore+    <>  " "+    <>  operator "*"+    <>  " "+    <>  ignore+skeleton (TextLit {}) =+        textSkeleton+skeleton (TextAppend {}) =+        ignore+    <>  " "+    <>  operator "++"+    <>  " "+    <>  ignore+skeleton (ListLit _ elems)+    | null elems =+            lbracket+        <>  rbracket+        <>  " "+        <>  colon+        <>  " "+        <>  ignore+    | otherwise =+            lbracket+        <>  " "+        <>  ignore+        <>  " "+        <>  rbracket+skeleton (ListAppend {}) =+        ignore+    <>  " "+    <>  operator "#"+    <>  " "+    <>  ignore+skeleton (Record {}) =+        lbrace+    <>  " "+    <>  ignore+    <>  " "+    <>  colon+    <>  " "+    <>  ignore+    <>  " "+    <>  rbrace+    <>  " (a record type)"+skeleton (RecordLit {}) =+        lbrace+    <>  " "+    <>  ignore+    <>  " "+    <>  equals+    <>  " "+    <>  ignore+    <>  " "+    <>  rbrace+    <> " (a record)"+skeleton (Union {}) =+        langle+    <>  " "+    <>  ignore+    <>  " "+    <>  colon+    <>  " "+    <>  ignore+    <>  " "+    <>  rangle+    <> " (a union type)"+skeleton (Combine {}) =+        ignore+    <>  " "+    <>  operator "∧"+    <>  " "+    <>  ignore+skeleton (CombineTypes {}) =+        ignore+    <>  " "+    <>  operator "⩓"+    <>  " "+    <>  ignore+skeleton (Prefer {}) =+        ignore+    <>  " "+    <>  operator "⫽"+    <>  " "+    <>  ignore+skeleton (RecordCompletion {}) =+        ignore+    <>  operator "::"+    <>  ignore+skeleton (Merge {}) =+        keyword "merge"+    <>  " "+    <>  ignore+    <>  " "+    <>  ignore+skeleton (ToMap {}) =+        keyword "toMap"+    <>  " "+    <>  ignore+skeleton (ShowConstructor {}) =+        keyword "showConstructor"+    <>  " "+    <>  ignore+skeleton (Field {}) =+        ignore+    <>  dot+    <>  ignore+skeleton (Project {}) =+        ignore+    <>  dot+    <>  lbrace+    <>  " "+    <>  ignore+    <>  " "+    <>  rbrace+skeleton (With {}) =+         ignore+    <>   " "+    <>   keyword "with"+    <>   " "+    <>   ignore+skeleton x = token (Pretty.pretty x)++mismatch :: Pretty a => Expr s a -> Expr s a -> Diff+mismatch l r = difference (skeleton l) (skeleton r)++-- | Render the difference between two expressions+diff :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diff l@(Lam {}) r@(Lam {}) =+    enclosed' "  " (rarrow <> " ") (docs l r)+  where+    docs+        (Lam _ (FunctionBinding { functionBindingVariable = aL, functionBindingAnnotation = bL }) cL)+        (Lam _ (FunctionBinding { functionBindingVariable = aR, functionBindingAnnotation = bR }) cR) =+        Data.List.NonEmpty.cons (align doc) (docs cL cR)+      where+        doc =   lambda+            <>  lparen+            <>  format " " (diffLabel aL aR)+            <>  colon+            <>  " "+            <>  format mempty (diff bL bR)+            <>  rparen++    docs aL aR =+        pure (diff aL aR)+diff l@(Lam {}) r =+    mismatch l r+diff l r@(Lam {}) =+    mismatch l r+diff l@(BoolIf {}) r@(BoolIf {}) =+    enclosed' "      " (keyword "else" <> "  ") (docs l r)+  where+    docs (BoolIf aL bL cL) (BoolIf aR bR cR) =+        Data.List.NonEmpty.cons (align doc) (docs cL cR)+      where+        doc =   keyword "if"+            <>  " "+            <>  format " " (diff aL aR)+            <>  keyword "then"+            <>  " "+            <>  diff bL bR+    docs aL aR =+        pure (diff aL aR)+diff l@(BoolIf {}) r =+    mismatch l r+diff l r@(BoolIf {}) =+    mismatch l r+diff l@(Let {}) r@(Let {}) =+    enclosed' "    " (keyword "in" <> "  ") (docs l r)+  where+    docs (Let (Binding _ aL _ bL _ cL) dL) (Let (Binding _ aR _ bR _ cR) dR) =+        Data.List.NonEmpty.cons (align doc) (docs dL dR)+      where+        bL' = fmap snd bL+        bR' = fmap snd bR++        doc =   keyword "let"+            <>  " "+            <>  format " " (diffLabel aL aR)+            <>  format " " (diffMaybe (colon <> " ") diff bL' bR')+            <>  equals+            <>  " "+            <>  diff cL cR+    docs aL aR = pure (diff aL aR)+diff l@(Let {}) r =+    mismatch l r+diff l r@(Let {}) =+    mismatch l r+diff l@(Pi {}) r@(Pi {}) =+    enclosed' "  " (rarrow <> " ") (docs l r)+  where+    docs (Pi _ aL bL cL) (Pi _ aR bR cR) =+        Data.List.NonEmpty.cons (align doc) (docs cL cR)+      where+        doc | same docA && same docB = ignore+            | same docA =+                format mempty docB+            | otherwise =+                    forall_+                <>  lparen+                <>  format " " docA+                <>  colon+                <>  " "+                <>  format mempty docB+                <>  rparen+          where+            docA = diffLabel aL aR++            docB = diff bL bR++    docs aL aR = pure (diff aL aR)+diff l@(Pi {}) r =+    mismatch l r+diff l r@(Pi {}) =+    mismatch l r+diff (Assert aL) (Assert aR) =+    align+        (  "  " <> keyword "assert"+        <> hardline <> colon <> " " <> diff aL aR+        )+diff l@(Assert {}) r =+    mismatch l r+diff l r@(Assert {}) =+    mismatch l r+diff l r =+    diffAnnotatedExpression l r++diffAnnotatedExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffAnnotatedExpression (Merge aL bL cL) (Merge aR bR cR) = align doc+  where+    doc =   keyword "merge"+        <>  " "+        <>  format " " (diffWithExpression aL aR)+        <>  format " " (diffWithExpression bL bR)+        <>  diffMaybe (colon <> " ") diffApplicationExpression cL cR+diffAnnotatedExpression l@(Merge {}) r =+    mismatch l r+diffAnnotatedExpression l r@(Merge {}) =+    mismatch l r+diffAnnotatedExpression (ToMap aL bL) (ToMap aR bR) = align doc+  where+    doc =   keyword "toMap"+        <>  " "+        <>  format " " (diffWithExpression aL aR)+        <>  diffMaybe (colon <> " ") diffApplicationExpression bL bR+diffAnnotatedExpression l@(ToMap {}) r =+    mismatch l r+diffAnnotatedExpression l r@(ToMap {}) =+    mismatch l r+diffAnnotatedExpression (ShowConstructor aL) (ShowConstructor aR) = align doc+  where+    doc =   keyword "showConstructor"+        <>  " "+        <>  format " " (diffWithExpression aL aR)+diffAnnotatedExpression l@(ShowConstructor {}) r =+    mismatch l r+diffAnnotatedExpression l r@(ShowConstructor {}) =+    mismatch l r+diffAnnotatedExpression (ListLit aL@(Just _) bL) (ListLit aR bR) = align doc+  where+    doc =   format " " (diffList bL bR)+        <>  format " " (diffMaybe (colon <> " ") diffApplicationExpression aL aR)+diffAnnotatedExpression (ListLit aL bL) (ListLit aR@(Just _) bR) = align doc+  where+    doc =   format " " (diffList bL bR)+        <>  format " " (diffMaybe (colon <> " ") diffApplicationExpression aL aR)+diffAnnotatedExpression l@(Annot {}) r@(Annot {}) =+    enclosed' "  " (colon <> " ") (docs l r)+  where+    docs (Annot aL bL) (Annot aR bR) =+        Data.List.NonEmpty.cons (align doc) (docs bL bR)+      where+        doc = diffOperatorExpression aL aR+    docs aL aR =+        diff aL aR :| []+diffAnnotatedExpression l@(Annot {}) r =+    mismatch l r+diffAnnotatedExpression l r@(Annot {}) =+    mismatch l r+diffAnnotatedExpression l r =+    diffOperatorExpression l r++{- Whitespace in diffs of operator expressions:++All indentation (whether pretty-printing or diffing) is a multiple of two+spaces, so if the operator is one character long (like ?) then the diff pads+the left margin to two space:++    ␣␣e₀+    ?␣e₁++... but if the operator is two characters long (like ||) then the diff pads+the left margin to four spaces:++     ␣␣␣␣e₀+     ||␣␣e₁+-}+diffOperatorExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffOperatorExpression = diffImportAltExpression++diffImportAltExpression :: (Pretty a, Eq a) => Expr Void a -> Expr Void a -> Diff+diffImportAltExpression l@(ImportAlt {}) r@(ImportAlt {}) =+    enclosed' "  " (operator "?" <> " ") (docs l r)+  where+    docs (ImportAlt aL bL) (ImportAlt aR bR) =+        Data.List.NonEmpty.cons (diffOrExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffOrExpression aL aR)+diffImportAltExpression l@(ImportAlt {}) r =+    mismatch l r+diffImportAltExpression l r@(ImportAlt {}) =+    mismatch l r+diffImportAltExpression l r =+    diffOrExpression l r++diffOrExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffOrExpression l@(BoolOr {}) r@(BoolOr {}) =+    enclosed' "    " (operator "||" <> "  ") (docs l r)+  where+    docs (BoolOr aL bL) (BoolOr aR bR) =+        Data.List.NonEmpty.cons (diffPlusExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffPlusExpression aL aR)+diffOrExpression l@(BoolOr {}) r =+    mismatch l r+diffOrExpression l r@(BoolOr {}) =+    mismatch l r+diffOrExpression l r =+    diffPlusExpression l r++diffPlusExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffPlusExpression l@(NaturalPlus {}) r@(NaturalPlus {}) =+    enclosed' "  " (operator "+" <> " ") (docs l r)+  where+    docs (NaturalPlus aL bL) (NaturalPlus aR bR) =+        Data.List.NonEmpty.cons (diffTextAppendExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffTextAppendExpression aL aR)+diffPlusExpression l@(NaturalPlus {}) r =+    mismatch l r+diffPlusExpression l r@(NaturalPlus {}) =+    mismatch l r+diffPlusExpression l r =+    diffTextAppendExpression l r++diffTextAppendExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffTextAppendExpression l@(TextAppend {}) r@(TextAppend {}) =+    enclosed' "    " (operator "++" <> "  ") (docs l r)+  where+    docs (TextAppend aL bL) (TextAppend aR bR) =+        Data.List.NonEmpty.cons (diffListAppendExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffListAppendExpression aL aR)+diffTextAppendExpression l@(TextAppend {}) r =+    mismatch l r+diffTextAppendExpression l r@(TextAppend {}) =+    mismatch l r+diffTextAppendExpression l r =+    diffListAppendExpression l r++diffListAppendExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffListAppendExpression l@(ListAppend {}) r@(ListAppend {}) =+    enclosed' "  " (operator "#" <> " ") (docs l r)+  where+    docs (ListAppend aL bL) (ListAppend aR bR) =+        Data.List.NonEmpty.cons (diffAndExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffAndExpression aL aR)+diffListAppendExpression l@(ListAppend {}) r =+    mismatch l r+diffListAppendExpression l r@(ListAppend {}) =+    mismatch l r+diffListAppendExpression l r =+    diffAndExpression l r++diffAndExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffAndExpression l@(BoolAnd {}) r@(BoolAnd {}) =+    enclosed' "    " (operator "&&" <> "  ") (docs l r)+  where+    docs (BoolAnd aL bL) (BoolAnd aR bR) =+        Data.List.NonEmpty.cons (diffCombineExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffCombineExpression aL aR)+diffAndExpression l@(BoolAnd {}) r =+    mismatch l r+diffAndExpression l r@(BoolAnd {}) =+    mismatch l r+diffAndExpression l r =+    diffCombineExpression l r++diffCombineExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffCombineExpression l@(Combine {}) r@(Combine {}) =+    enclosed' "  " (operator "∧" <> " ") (docs l r)+  where+    docs (Combine _ _ aL bL) (Combine _ _ aR bR) =+        Data.List.NonEmpty.cons (diffPreferExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffPreferExpression aL aR)+diffCombineExpression l@(Combine {}) r =+    mismatch l r+diffCombineExpression l r@(Combine {}) =+    mismatch l r+diffCombineExpression l r =+    diffPreferExpression l r++diffPreferExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffPreferExpression l@(Prefer {}) r@(Prefer {}) =+    enclosed' "  " (operator "⫽" <> " ") (docs l r)+  where+    docs (Prefer _ _ aL bL) (Prefer _ _ aR bR) =+        Data.List.NonEmpty.cons (diffCombineTypesExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffCombineTypesExpression aL aR)+diffPreferExpression l@(Prefer {}) r =+    mismatch l r+diffPreferExpression l r@(Prefer {}) =+    mismatch l r+diffPreferExpression l r =+    diffCombineTypesExpression l r++diffCombineTypesExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffCombineTypesExpression l@(CombineTypes {}) r@(CombineTypes {}) =+    enclosed' "  " (operator "*" <> " ") (docs l r)+  where+    docs (CombineTypes _ aL bL) (CombineTypes _ aR bR) =+        Data.List.NonEmpty.cons (diffTimesExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffTimesExpression aL aR)+diffCombineTypesExpression l@(CombineTypes {}) r =+    mismatch l r+diffCombineTypesExpression l r@(CombineTypes {}) =+    mismatch l r+diffCombineTypesExpression l r =+    diffTimesExpression l r++diffTimesExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffTimesExpression l@(NaturalTimes {}) r@(NaturalTimes {}) =+    enclosed' "  " (operator "*" <> " ") (docs l r)+  where+    docs (NaturalTimes aL bL) (NaturalTimes aR bR) =+        Data.List.NonEmpty.cons (diffEqualExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffEqualExpression aL aR)+diffTimesExpression l@(NaturalTimes {}) r =+    mismatch l r+diffTimesExpression l r@(NaturalTimes {}) =+    mismatch l r+diffTimesExpression l r =+    diffEqualExpression l r++diffEqualExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffEqualExpression l@(BoolEQ {}) r@(BoolEQ {}) =+    enclosed' "    " (operator "==" <> "  ") (docs l r)+  where+    docs (BoolEQ aL bL) (BoolEQ aR bR) =+        Data.List.NonEmpty.cons (diffNotEqualExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffNotEqualExpression aL aR)+diffEqualExpression l@(BoolEQ {}) r =+    mismatch l r+diffEqualExpression l r@(BoolEQ {}) =+    mismatch l r+diffEqualExpression l r =+    diffNotEqualExpression l r++diffNotEqualExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffNotEqualExpression l@(BoolNE {}) r@(BoolNE {}) =+    enclosed' "    " (operator "!=" <> "  ") (docs l r)+  where+    docs (BoolNE aL bL) (BoolNE aR bR) =+        Data.List.NonEmpty.cons (diffEquivalentExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffEquivalentExpression aL aR)+diffNotEqualExpression l@(BoolNE {}) r =+    mismatch l r+diffNotEqualExpression l r@(BoolNE {}) =+    mismatch l r+diffNotEqualExpression l r =+    diffEquivalentExpression l r++diffEquivalentExpression+    :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffEquivalentExpression l@(Equivalent {}) r@(Equivalent {}) =+    enclosed' "  " (operator "≡" <> " ") (docs l r)+  where+    docs (Equivalent _ aL bL) (Equivalent _ aR bR) =+        Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffApplicationExpression aL aR)+diffEquivalentExpression l@(Equivalent {}) r =+    mismatch l r+diffEquivalentExpression l r@(Equivalent {}) =+    mismatch l r+diffEquivalentExpression l r =+    diffApplicationExpression l r++diffApplicationExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffApplicationExpression l@(App {}) r@(App {}) =+    enclosed' mempty mempty (Data.List.NonEmpty.reverse (docs l r))+  where+    docs (App aL bL) (App aR bR) =+        Data.List.NonEmpty.cons (diffWithExpression bL bR) (docs aL aR)+    docs (Some aL) (Some aR) =+        diffWithExpression aL aR :| [ builtin "Some" ]+    docs aL aR@(Some {}) =+        pure (mismatch aL aR)+    docs aL@(Some {}) aR =+        pure (mismatch aL aR)+    docs aL aR =+        pure (diffWithExpression aL aR)+diffApplicationExpression l@(App {}) r =+    mismatch l r+diffApplicationExpression l r@(App {}) =+    mismatch l r+diffApplicationExpression (Some l) (Some r) =+    enclosed' mempty mempty (builtin "Some" :| [ diffWithExpression l r ])+diffApplicationExpression l@(Some {}) r =+    mismatch l r+diffApplicationExpression l r@(Some {}) =+    mismatch l r+diffApplicationExpression l r =+    diffWithExpression l r++diffWithExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffWithExpression (With eL ksL vL) (With eR ksR vR) =+    align+        (   format " " (diffImportExpression eL eR)+        <>  "with "+        <>  align+            (   format " " (diffPath (fmap toText ksL) (fmap toText ksR))+            <>  "= "+            <>  diffOperatorExpression vL vR+            )+        )+  where+    toText  WithQuestion  = "?"+    toText (WithLabel k ) = k++    diffPath (kL :| []) (kR :| []) =+        diffLabel kL kR+    diffPath (kL₀ :| kL₁ : ksL') (kR₀ :| kR₁ : ksR') =+            format "" (diffLabel kL₀ kR₀)+        <>  dot+        <>  diffPath (kL₁ :| ksL') (kR₁ :| ksR')+    diffPath (kL :| []) (kR₀ :| kR₁ : ksR') =+            format "" (diffLabel kL kR₀)+        <>  plus (foldMap (\k -> dot <> token (Internal.prettyLabel k)) (kR₁ :| ksR'))+    diffPath (kL₀ :| kL₁ : ksL') (kR :| []) =+            format "" (diffLabel kL₀ kR)+        <>  minus (foldMap (\k -> dot <> token (Internal.prettyLabel k)) (kL₁ :| ksL'))+diffWithExpression l r@With{} =+    mismatch l r+diffWithExpression l@With{} r =+    mismatch l r+diffWithExpression l r =+    diffImportExpression l r++diffImportExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffImportExpression (Embed l) (Embed r) =+    diffPretty l r+diffImportExpression l@(Embed {}) r =+    mismatch l r+diffImportExpression l r@(Embed {}) =+    mismatch l r+diffImportExpression l r =+    diffRecordCompletionExpression l r++diffRecordCompletionExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffRecordCompletionExpression (RecordCompletion aL bL) (RecordCompletion aR bR) =+       diffSelectorExpression aL aR <> "::" <> diffSelectorExpression bL bR+diffRecordCompletionExpression l@(RecordCompletion {}) r =+    mismatch l r+diffRecordCompletionExpression l r@(RecordCompletion {}) =+    mismatch l r+diffRecordCompletionExpression l r =+    diffSelectorExpression l r++diffSelectorExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffSelectorExpression l@(Field {}) r@(Field {}) =+    enclosed' "  " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r))+  where+    docs (Field aL (Syntax.fieldSelectionLabel -> bL)) (Field aR (Syntax.fieldSelectionLabel -> bR)) =+        Data.List.NonEmpty.cons (diffLabel bL bR) (docs aL aR)+    docs (Project aL (Left bL)) (Project aR (Left bR)) =+        Data.List.NonEmpty.cons (diffLabels bL bR) (docs aL aR)+    docs (Project aL (Right bL)) (Project aR (Right bR)) =+        Data.List.NonEmpty.cons (diff bL bR) (docs aL aR)+    docs aL aR =+        pure (diffPrimitiveExpression aL aR)+diffSelectorExpression l@(Field {}) r =+    mismatch l r+diffSelectorExpression l r@(Field {}) =+    mismatch l r+diffSelectorExpression l@(Project {}) r@(Project {}) =+    enclosed' "  " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r))+  where+    docs (Field aL (Syntax.fieldSelectionLabel -> bL)) (Field aR (Syntax.fieldSelectionLabel ->bR)) =+        Data.List.NonEmpty.cons (diffLabel bL bR) (docs aL aR)+    docs (Project aL (Left bL)) (Project aR (Left bR)) =+        Data.List.NonEmpty.cons (diffLabels bL bR) (docs aL aR)+    docs (Project aL (Right bL)) (Project aR (Right bR)) =+        Data.List.NonEmpty.cons (diff bL bR) (docs aL aR)+    docs aL aR =+        pure (diffPrimitiveExpression aL aR)+diffSelectorExpression l@(Project {}) r =+    mismatch l r+diffSelectorExpression l r@(Project {}) =+    mismatch l r+diffSelectorExpression l r =+    diffPrimitiveExpression l r++diffPrimitiveExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffPrimitiveExpression (Var aL) (Var aR) =+    diffVar aL aR+diffPrimitiveExpression l@(Var {}) r =+    mismatch l r+diffPrimitiveExpression l r@(Var {}) =+    mismatch l r+diffPrimitiveExpression (Const aL) (Const aR) =+    diffConst aL aR+diffPrimitiveExpression l@(Const {}) r =+    mismatch l r+diffPrimitiveExpression l r@(Const {}) =+    mismatch l r+diffPrimitiveExpression Bool Bool =+    "…"+diffPrimitiveExpression l@Bool r =+    mismatch l r+diffPrimitiveExpression l r@Bool =+    mismatch l r+diffPrimitiveExpression Bytes Bytes =+    "…"+diffPrimitiveExpression l@Bytes r =+    mismatch l r+diffPrimitiveExpression l r@Bytes =+    mismatch l r+diffPrimitiveExpression (BytesLit l) (BytesLit r) =+    diffBytes l r+diffPrimitiveExpression l@(BytesLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(BytesLit {}) =+    mismatch l r+diffPrimitiveExpression Natural Natural =+    "…"+diffPrimitiveExpression l@Natural r =+    mismatch l r+diffPrimitiveExpression l r@Natural =+    mismatch l r+diffPrimitiveExpression NaturalFold NaturalFold =+    "…"+diffPrimitiveExpression l@NaturalFold r =+    mismatch l r+diffPrimitiveExpression l r@NaturalFold =+    mismatch l r+diffPrimitiveExpression NaturalBuild NaturalBuild =+    "…"+diffPrimitiveExpression l@NaturalBuild r =+    mismatch l r+diffPrimitiveExpression l r@NaturalBuild =+    mismatch l r+diffPrimitiveExpression NaturalIsZero NaturalIsZero =+    "…"+diffPrimitiveExpression l@NaturalIsZero r =+    mismatch l r+diffPrimitiveExpression l r@NaturalIsZero =+    mismatch l r+diffPrimitiveExpression NaturalEven NaturalEven =+    "…"+diffPrimitiveExpression l@NaturalEven r =+    mismatch l r+diffPrimitiveExpression l r@NaturalEven =+    mismatch l r+diffPrimitiveExpression NaturalOdd NaturalOdd =+    "…"+diffPrimitiveExpression l@NaturalOdd r =+    mismatch l r+diffPrimitiveExpression l r@NaturalOdd =+    mismatch l r+diffPrimitiveExpression NaturalToInteger NaturalToInteger =+    "…"+diffPrimitiveExpression l@NaturalToInteger r =+    mismatch l r+diffPrimitiveExpression l r@NaturalToInteger =+    mismatch l r+diffPrimitiveExpression NaturalShow NaturalShow =+    "…"+diffPrimitiveExpression l@NaturalShow r =+    mismatch l r+diffPrimitiveExpression l r@NaturalShow =+    mismatch l r+diffPrimitiveExpression NaturalSubtract NaturalSubtract =+    "…"+diffPrimitiveExpression l@NaturalSubtract r =+    mismatch l r+diffPrimitiveExpression l r@NaturalSubtract =+    mismatch l r+diffPrimitiveExpression Integer Integer =+    "…"+diffPrimitiveExpression l@Integer r =+    mismatch l r+diffPrimitiveExpression l r@Integer =+    mismatch l r+diffPrimitiveExpression IntegerClamp IntegerClamp =+    "…"+diffPrimitiveExpression l@IntegerClamp r =+    mismatch l r+diffPrimitiveExpression l r@IntegerClamp =+    mismatch l r+diffPrimitiveExpression IntegerNegate IntegerNegate =+    "…"+diffPrimitiveExpression l@IntegerNegate r =+    mismatch l r+diffPrimitiveExpression l r@IntegerNegate =+    mismatch l r+diffPrimitiveExpression IntegerShow IntegerShow =+    "…"+diffPrimitiveExpression l@IntegerShow r =+    mismatch l r+diffPrimitiveExpression l r@IntegerShow =+    mismatch l r+diffPrimitiveExpression IntegerToDouble IntegerToDouble =+    "…"+diffPrimitiveExpression l@IntegerToDouble r =+    mismatch l r+diffPrimitiveExpression l r@IntegerToDouble =+    mismatch l r+diffPrimitiveExpression Double Double =+    "…"+diffPrimitiveExpression l@Double r =+    mismatch l r+diffPrimitiveExpression l r@Double =+    mismatch l r+diffPrimitiveExpression DoubleShow DoubleShow =+    "…"+diffPrimitiveExpression l@DoubleShow r =+    mismatch l r+diffPrimitiveExpression l r@DoubleShow =+    mismatch l r+diffPrimitiveExpression Text Text =+    "…"+diffPrimitiveExpression l@Text r =+    mismatch l r+diffPrimitiveExpression l r@Text =+    mismatch l r+diffPrimitiveExpression TextReplace TextReplace =+    "…"+diffPrimitiveExpression l@TextReplace r =+    mismatch l r+diffPrimitiveExpression l r@TextReplace =+    mismatch l r+diffPrimitiveExpression TextShow TextShow =+    "…"+diffPrimitiveExpression l@TextShow r =+    mismatch l r+diffPrimitiveExpression l r@TextShow =+    mismatch l r+diffPrimitiveExpression Date Date =+    "…"+diffPrimitiveExpression l r@Date =+    mismatch l r+diffPrimitiveExpression l@Date r=+    mismatch l r+diffPrimitiveExpression DateShow DateShow =+    "…"+diffPrimitiveExpression l r@DateShow =+    mismatch l r+diffPrimitiveExpression l@DateShow r=+    mismatch l r+diffPrimitiveExpression Time Time =+    "…"+diffPrimitiveExpression l r@Time =+    mismatch l r+diffPrimitiveExpression l@Time r=+    mismatch l r+diffPrimitiveExpression TimeShow TimeShow =+    "…"+diffPrimitiveExpression l r@TimeShow =+    mismatch l r+diffPrimitiveExpression l@TimeShow r=+    mismatch l r+diffPrimitiveExpression TimeZone TimeZone =+    "…"+diffPrimitiveExpression l r@TimeZone =+    mismatch l r+diffPrimitiveExpression l@TimeZone r=+    mismatch l r+diffPrimitiveExpression TimeZoneShow TimeZoneShow =+    "…"+diffPrimitiveExpression l r@TimeZoneShow =+    mismatch l r+diffPrimitiveExpression l@TimeZoneShow r=+    mismatch l r+diffPrimitiveExpression List List =+    "…"+diffPrimitiveExpression l@List r =+    mismatch l r+diffPrimitiveExpression l r@List =+    mismatch l r+diffPrimitiveExpression (ListLit Nothing bL) (ListLit Nothing bR) = align doc+  where+    doc = format " " (diffList bL bR)+diffPrimitiveExpression ListBuild ListBuild =+    "…"+diffPrimitiveExpression l@ListBuild r =+    mismatch l r+diffPrimitiveExpression l r@ListBuild =+    mismatch l r+diffPrimitiveExpression ListFold ListFold =+    "…"+diffPrimitiveExpression l@ListFold r =+    mismatch l r+diffPrimitiveExpression l r@ListFold =+    mismatch l r+diffPrimitiveExpression ListLength ListLength =+    "…"+diffPrimitiveExpression l@ListLength r =+    mismatch l r+diffPrimitiveExpression l r@ListLength =+    mismatch l r+diffPrimitiveExpression ListHead ListHead =+    "…"+diffPrimitiveExpression l@ListHead r =+    mismatch l r+diffPrimitiveExpression l r@ListHead =+    mismatch l r+diffPrimitiveExpression ListLast ListLast =+    "…"+diffPrimitiveExpression l@ListLast r =+    mismatch l r+diffPrimitiveExpression l r@ListLast =+    mismatch l r+diffPrimitiveExpression ListIndexed ListIndexed =+    "…"+diffPrimitiveExpression l@ListIndexed r =+    mismatch l r+diffPrimitiveExpression l r@ListIndexed =+    mismatch l r+diffPrimitiveExpression ListReverse ListReverse =+    "…"+diffPrimitiveExpression l@ListReverse r =+    mismatch l r+diffPrimitiveExpression l r@ListReverse =+    mismatch l r+diffPrimitiveExpression Optional Optional =+    "…"+diffPrimitiveExpression l@Optional r =+    mismatch l r+diffPrimitiveExpression l r@Optional =+    mismatch l r+diffPrimitiveExpression None None =+    "…"+diffPrimitiveExpression l@None r =+    mismatch l r+diffPrimitiveExpression l r@None =+    mismatch l r+diffPrimitiveExpression (BoolLit aL) (BoolLit aR) =+    diffBool aL aR+diffPrimitiveExpression l@(BoolLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(BoolLit {}) =+    mismatch l r+diffPrimitiveExpression (IntegerLit aL) (IntegerLit aR) =+    diffInteger aL aR+diffPrimitiveExpression l@(IntegerLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(IntegerLit {}) =+    mismatch l r+diffPrimitiveExpression (NaturalLit aL) (NaturalLit aR) =+    diffNatural aL aR+diffPrimitiveExpression l@(NaturalLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(NaturalLit {}) =+    mismatch l r+diffPrimitiveExpression (DoubleLit aL) (DoubleLit aR) =+    diffDouble aL aR+diffPrimitiveExpression l@(DoubleLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(DoubleLit {}) =+    mismatch l r+diffPrimitiveExpression (TextLit l) (TextLit r) =+    diffChunks l r+diffPrimitiveExpression l@(TextLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(TextLit {}) =+    mismatch l r+diffPrimitiveExpression (DateLiteral l) (DateLiteral r) =+    diffDateLiteral l r+diffPrimitiveExpression l@(DateLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(DateLiteral {}) =+    mismatch l r+diffPrimitiveExpression (TimeLiteral tL pL) (TimeLiteral tR pR) =+    diffTimeLiteral tL pL tR pR+diffPrimitiveExpression l@(TimeLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(TimeLiteral {}) =+    mismatch l r+diffPrimitiveExpression (TimeZoneLiteral l) (TimeZoneLiteral r) =+    diffTimeZoneLiteral l r+diffPrimitiveExpression l@(TimeZoneLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(TimeZoneLiteral {}) =+    mismatch l r+diffPrimitiveExpression (Record aL) (Record aR) =+    diffRecord aL aR+diffPrimitiveExpression l@(Record {}) r =+    mismatch l r+diffPrimitiveExpression l r@(Record {}) =+    mismatch l r+diffPrimitiveExpression (RecordLit aL) (RecordLit aR) =+    diffRecordLit aL aR+diffPrimitiveExpression l@(RecordLit {}) r =+    mismatch l r+diffPrimitiveExpression l r@(RecordLit {}) =+    mismatch l r+diffPrimitiveExpression (Union aL) (Union aR) =+    diffUnion aL aR+diffPrimitiveExpression l@(Union {}) r =+    mismatch l r+diffPrimitiveExpression l r@(Union {}) =+    mismatch l r+diffPrimitiveExpression aL aR =+    if same doc+    then ignore+    else align ("( " <> doc <> hardline <> ")")+  where+    doc = diff aL aR
+ src/Dhall/DirectoryTree.hs view
@@ -0,0 +1,515 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TupleSections     #-}+{-# LANGUAGE ViewPatterns      #-}++{-# OPTIONS_GHC -Wno-orphans #-}++-- | Implementation of the @dhall to-directory-tree@ subcommand+module Dhall.DirectoryTree+    ( -- * Filesystem+      toDirectoryTree+    , FilesystemError(..)++      -- * Low-level types and functions+    , module Dhall.DirectoryTree.Types+    , decodeDirectoryTree+    , directoryTreeType+    ) where++import Control.Applicative       (empty)+import Control.Exception         (Exception)+import Control.Monad             (unless, when)+import Data.Either.Validation    (Validation (..))+import Data.Functor.Identity     (Identity (..))+import Data.Maybe                (fromMaybe, isJust)+import Data.Sequence             (Seq)+import Data.Text                 (Text)+import Data.Void                 (Void)+import Dhall.DirectoryTree.Types+import Dhall.Marshal.Decode      (Decoder (..), Expector)+import Dhall.Src                 (Src)+import Dhall.Syntax+    ( Chunks (..)+    , Const (..)+    , Expr (..)+    , RecordField (..)+    , Var (..)+    )+import System.FilePath           ((</>))+import System.PosixCompat.Types  (FileMode, GroupID, UserID)++import qualified Control.Exception           as Exception+import qualified Data.ByteString             as ByteString+import qualified Data.Foldable               as Foldable+import qualified Data.Text                   as Text+import qualified Data.Text.IO                as Text.IO+import qualified Dhall.Core                  as Core+import qualified Dhall.Map                   as Map+import qualified Dhall.Marshal.Decode        as Decode+import qualified Dhall.Pretty+import qualified Dhall.TypeCheck             as TypeCheck+import qualified Dhall.Util                  as Util+import qualified Prettyprinter               as Pretty+import qualified Prettyprinter.Render.String as Pretty+import qualified System.Directory            as Directory+import qualified System.FilePath             as FilePath+#ifdef mingw32_HOST_OS+import System.IO.Error           (illegalOperationErrorType, mkIOError)+#else+import qualified System.Posix.User           as Posix+#endif+import qualified System.PosixCompat.Files    as Posix++{-| Attempt to transform a Dhall record into a directory tree where:++    * Records are translated into directories++    * @Map@s are also translated into directories++    * @Text@ values or fields are translated into files++    * @Optional@ values are omitted if @None@++    * There is a more advanced way to construct directory trees using a fixpoint+      encoding. See the documentation below on that.++    For example, the following Dhall record:++    > { dir = { `hello.txt` = "Hello\n" }+    > , `goodbye.txt`= Some "Goodbye\n"+    > , `missing.txt` = None Text+    > }++    ... should translate to this directory tree:++    > $ tree result+    > result+    > ├── dir+    > │   └── hello.txt+    > └── goodbye.txt+    >+    > $ cat result/dir/hello.txt+    > Hello+    >+    > $ cat result/goodbye.txt+    > Goodbye++    Use this in conjunction with the Prelude's support for rendering JSON/YAML+    in "pure Dhall" so that you can generate files containing JSON. For example:++    > let JSON =+    >       https://prelude.dhall-lang.org/v12.0.0/JSON/package.dhall sha256:843783d29e60b558c2de431ce1206ce34bdfde375fcf06de8ec5bf77092fdef7+    >+    > in  { `example.json` =+    >         JSON.render (JSON.array [ JSON.number 1.0, JSON.bool True ])+    >     , `example.yaml` =+    >         JSON.renderYAML+    >           (JSON.object (toMap { foo = JSON.string "Hello", bar = JSON.null }))+    >     }++    ... which would generate:++    > $ cat result/example.json+    > [ 1.0, true ]+    >+    > $ cat result/example.yaml+    > ! "bar": null+    > ! "foo": "Hello"++    /Advanced construction of directory trees/++    In addition to the ways described above using "simple" Dhall values to+    construct the directory tree there is one based on a fixpoint encoding. It+    works by passing a value of the following type to the interpreter:++    > let User = < UserId : Natural | UserName : Text >+    >+    > let Group = < GroupId : Natural | GroupName : Text >+    >+    > let Access =+    >       { execute : Optional Bool+    >       , read : Optional Bool+    >       , write : Optional Bool+    >       }+    >+    > let Mode =+    >       { user : Optional Access+    >       , group : Optional Access+    >       , other : Optional Access+    >       }+    >+    > let Entry =+    >       \(content : Type) ->+    >         { name : Text+    >         , content : content+    >         , user : Optional User+    >         , group : Optional Group+    >         , mode : Optional Mode+    >         }+    >+    > in  forall (tree : Type) ->+    >     forall  ( make+    >             : { directory : Entry (List tree) -> tree+    >               , file : Entry Text -> tree+    >               }+    >             ) ->+    >       List tree++    The fact that the metadata for filesystem entries is modeled after the POSIX+    permission model comes with the unfortunate downside that it might not apply+    to other systems: There, changes to the metadata (user, group, permissions)+    might be a no-op and __no warning will be issued__.+    This is a leaking abstraction of the+    [unix-compat](https://hackage.haskell.org/package/unix-compat) package used+    internally.++    __NOTE__: This utility does not take care of type-checking and normalizing+    the provided expression. This will raise a `FilesystemError` exception or a+    `Dhall.Marshal.Decode.DhallErrors` exception upon encountering an expression+    that cannot be converted as-is.+-}+toDirectoryTree+    :: Bool -- ^ Whether to allow path separators in file names or not+    -> FilePath+    -> Expr Void Void+    -> IO ()+toDirectoryTree allowSeparators path expression = case expression of+    RecordLit keyValues ->+        Map.unorderedTraverseWithKey_ process $ recordFieldValue <$> keyValues++    ListLit (Just (App List (Record [ ("mapKey", recordFieldValue -> Text), ("mapValue", _) ]))) [] ->+        Directory.createDirectoryIfMissing allowSeparators path++    ListLit _ records+        | not (null records)+        , Just keyValues <- extract (Foldable.toList records) ->+            Foldable.traverse_ (uncurry process) keyValues++    TextLit (Chunks [] text) ->+        Text.IO.writeFile path text++    Some value ->+        toDirectoryTree allowSeparators path value++    App (Field (Union _) _) value -> do+        toDirectoryTree allowSeparators path value++    App None _ ->+        return ()++    -- If this pattern matches we assume the user wants to use the fixpoint+    -- approach, hence we typecheck it and output error messages like we would+    -- do for every other Dhall program.+    Lam _ _ (Lam _ _ _) -> do+        entries <- decodeDirectoryTree expression++        processFilesystemEntryList allowSeparators path entries++    _ ->+        die+  where+    extract [] =+        return []++    extract (RecordLit [ ("mapKey", recordFieldValue -> TextLit (Chunks [] key))+                       , ("mapValue", recordFieldValue -> value)] : records) =+        fmap ((key, value) :) (extract records)++    extract _ =+        empty++    process key value = do+        when (not allowSeparators && Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key) $+            die++        Directory.createDirectoryIfMissing allowSeparators path++        toDirectoryTree allowSeparators (path </> Text.unpack key) value++    die = Exception.throwIO FilesystemError{..}+      where+        unexpectedExpression = expression++-- | Decode a fixpoint directory tree from a Dhall expression.+decodeDirectoryTree :: Expr s Void -> IO (Seq FilesystemEntry)+decodeDirectoryTree (Core.alphaNormalize . Core.denote -> expression@(Lam _ _ (Lam _ _ body))) = do+    expected' <- case directoryTreeType of+        Success x -> return x+        Failure e -> Exception.throwIO e++    _ <- Core.throws $ TypeCheck.typeOf $ Annot expression expected'++    case Decode.extract decoder body of+        Success x -> return x+        Failure e -> Exception.throwIO e+    where+        decoder :: Decoder (Seq FilesystemEntry)+        decoder = Decode.auto+decodeDirectoryTree expr = Exception.throwIO $ FilesystemError $ Core.denote expr++-- | The type of a fixpoint directory tree expression.+directoryTreeType :: Expector (Expr Src Void)+directoryTreeType = Pi Nothing "tree" (Const Type)+    <$> (Pi Nothing "make" <$> makeType <*> pure (App List (Var (V "tree" 0))))++-- | The type of make part of a fixpoint directory tree expression.+makeType :: Expector (Expr Src Void)+makeType = Record . Map.fromList <$> sequenceA+    [ makeConstructor "directory" (Decode.auto :: Decoder DirectoryEntry)+    , makeConstructor "file" (Decode.auto :: Decoder TextFileEntry)+    , makeConstructor "binary-file" (Decode.auto :: Decoder BinaryFileEntry)+    ]+    where+        makeConstructor :: Text -> Decoder b -> Expector (Text, RecordField Src Void)+        makeConstructor name dec = (name,) . Core.makeRecordField+            <$> (Pi Nothing "_" <$> expected dec <*> pure (Var (V "tree" 0)))++-- | Resolve a `User` to a numerical id.+getUser :: User -> IO UserID+getUser (UserId uid) = return uid+getUser (UserName name) =+#ifdef mingw32_HOST_OS+    ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+    where x = "System.Posix.User.getUserEntryForName: not supported"+#else+    Posix.userID <$> Posix.getUserEntryForName name+#endif++-- | Resolve a `Group` to a numerical id.+getGroup :: Group -> IO GroupID+getGroup (GroupId gid) = return gid+getGroup (GroupName name) =+#ifdef mingw32_HOST_OS+    ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+    where x = "System.Posix.User.getGroupEntryForName: not supported"+#else+    Posix.groupID <$> Posix.getGroupEntryForName name+#endif++-- | Process a `FilesystemEntry`. Writes the content to disk and apply the+-- metadata to the newly created item.+processFilesystemEntry :: Bool -> FilePath -> FilesystemEntry -> IO ()+processFilesystemEntry allowSeparators path (DirectoryEntry entry) =+    processEntryWith path entry $ \path' content -> do+        Directory.createDirectoryIfMissing allowSeparators path'+        processFilesystemEntryList allowSeparators path' content+processFilesystemEntry allowSeparators path (BinaryFileEntry entry) =+    processEntryWith path entry $ \path' content -> do+        when allowSeparators $ do+            Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+        ByteString.writeFile path' content+processFilesystemEntry allowSeparators path (TextFileEntry entry) =+    processEntryWith path entry $ \path' content -> do+        when allowSeparators $ do+            Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+        Text.IO.writeFile path' content++-- | A helper function used by 'processFilesystemEntry'.+processEntryWith+    :: FilePath+    -> Entry a+    -> (FilePath -> a -> IO ())+    -> IO ()+processEntryWith path entry f = do+    let path' = path </> entryName entry+    when (hasMetadata entry && not isMetadataSupported) $+        Exception.throwIO (MetadataUnsupportedError path')+    f path' (entryContent entry)+    -- It is important that we write the metadata after we wrote the content of+    -- the file as we might lock ourself out by changing ownership or+    -- permissions.+    applyMetadata entry path'++-- | Process a list of `FilesystemEntry`s.+processFilesystemEntryList :: Bool -> FilePath -> Seq FilesystemEntry -> IO ()+processFilesystemEntryList allowSeparators path = Foldable.traverse_+    (processFilesystemEntry allowSeparators path)++-- | Does this entry have some metadata set?+hasMetadata :: Entry a -> Bool+hasMetadata entry+    =  isJust (entryUser entry)+    || isJust (entryGroup entry)+    || maybe False hasMode (entryMode entry)+    where+        hasMode :: Mode Maybe -> Bool+        hasMode mode+            =  maybe False hasAccess (modeUser mode)+            || maybe False hasAccess (modeGroup mode)+            || maybe False hasAccess (modeOther mode)++        hasAccess :: Access Maybe -> Bool+        hasAccess access+            =  isJust (accessExecute access)+            || isJust (accessRead access)+            || isJust (accessWrite access)++-- | Set the metadata of an object referenced by a path.+applyMetadata :: Entry a -> FilePath -> IO ()+applyMetadata entry fp = do+    s <- Posix.getFileStatus fp+    let user = Posix.fileOwner s+        group = Posix.fileGroup s+        mode = fileModeToMode $ Posix.fileMode s++    user' <- getUser $ fromMaybe (UserId user) (entryUser entry)+    group' <- getGroup $ fromMaybe (GroupId group) (entryGroup entry)+    unless ((user', group') == (user, group)) $+        Posix.setOwnerAndGroup fp user' group'++    let mode' = maybe mode (updateModeWith mode) (entryMode entry)+    unless (mode' == mode) $+        setFileMode fp $ modeToFileMode mode'++-- | Calculate the new `Mode` from the current mode and the changes specified by+-- the user.+updateModeWith :: Mode Identity -> Mode Maybe -> Mode Identity+updateModeWith x y = Mode+    { modeUser = combine modeUser modeUser+    , modeGroup = combine modeGroup modeGroup+    , modeOther = combine modeOther modeOther+    }+    where+        combine f g = maybe (f x) (Identity . updateAccessWith (runIdentity $ f x)) (g y)++-- | Calculate the new `Access` from the current permissions and the changes+-- specified by the user.+updateAccessWith :: Access Identity -> Access Maybe -> Access Identity+updateAccessWith x y = Access+    { accessExecute = combine accessExecute accessExecute+    , accessRead = combine accessRead accessRead+    , accessWrite = combine accessWrite accessWrite+    }+    where+        combine f g = maybe (f x) Identity (g y)++-- | Convert a filesystem mode given as a bitmask (`FileMode`) to an ADT+-- (`Mode`).+fileModeToMode :: FileMode -> Mode Identity+fileModeToMode mode = Mode+    { modeUser = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.ownerExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.ownerReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.ownerReadMode+        }+    , modeGroup = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.groupExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.groupReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.groupReadMode+        }+    , modeOther = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.otherExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.otherReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.otherReadMode+        }+    }++-- | Convert a filesystem mode given as an ADT (`Mode`) to a bitmask+-- (`FileMode`).+modeToFileMode :: Mode Identity -> FileMode+modeToFileMode mode = foldr Posix.unionFileModes Posix.nullFileMode $+    [ Posix.ownerExecuteMode | runIdentity $ accessExecute (runIdentity $ modeUser  mode) ] <>+    [ Posix.ownerReadMode    | runIdentity $ accessRead    (runIdentity $ modeUser  mode) ] <>+    [ Posix.ownerWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeUser  mode) ] <>+    [ Posix.groupExecuteMode | runIdentity $ accessExecute (runIdentity $ modeGroup mode) ] <>+    [ Posix.groupReadMode    | runIdentity $ accessRead    (runIdentity $ modeGroup mode) ] <>+    [ Posix.groupWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeGroup mode) ] <>+    [ Posix.otherExecuteMode | runIdentity $ accessExecute (runIdentity $ modeOther mode) ] <>+    [ Posix.otherReadMode    | runIdentity $ accessRead    (runIdentity $ modeOther mode) ] <>+    [ Posix.otherWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeOther mode) ]++-- | Check whether the second `FileMode` is contained in the first one.+hasFileMode :: FileMode -> FileMode -> Bool+hasFileMode mode x = (mode `Posix.intersectFileModes` x) == x++{- | This error indicates that you supplied an invalid Dhall expression to the+     `toDirectoryTree` function.  The Dhall expression could not be translated+     to a directory tree.+-}+newtype FilesystemError =+    FilesystemError { unexpectedExpression :: Expr Void Void }++instance Exception FilesystemError++instance Show FilesystemError where+    show FilesystemError{..} =+        Pretty.renderString (Dhall.Pretty.layout message)+      where+        message =+          Util._ERROR <> ": Not a valid directory tree expression                             \n\\+          \                                                                                   \n\\+          \Explanation: Only a subset of Dhall expressions can be converted to a directory    \n\\+          \tree.  Specifically, record literals or maps can be converted to directories,      \n\\+          \❰Text❱ literals can be converted to files, and ❰Optional❱ values are included if   \n\\+          \❰Some❱ and omitted if ❰None❱.  Values of union types can also be converted if      \n\\+          \they are an alternative which has a non-nullary constructor whose argument is of   \n\\+          \an otherwise convertible type.  Furthermore, there is a more advanced approach to  \n\\+          \constructing a directory tree utilizing a fixpoint encoding. Consult the upstream  \n\\+          \documentation of the `toDirectoryTree` function in the Dhall.Directory module for  \n\\+          \further information on that.                                                       \n\\+          \No other type of value can be translated to a directory tree.                      \n\\+          \                                                                                   \n\\+          \For example, this is a valid expression that can be translated to a directory      \n\\+          \tree:                                                                              \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌──────────────────────────────────┐                                           \n\\+          \    │ { `example.json` = \"[1, true]\" } │                                         \n\\+          \    └──────────────────────────────────┘                                           \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \In contrast, the following expression is not allowed due to containing a           \n\\+          \❰Natural❱ field, which cannot be translated in this way:                           \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌───────────────────────┐                                                      \n\\+          \    │ { `example.txt` = 1 } │                                                      \n\\+          \    └───────────────────────┘                                                      \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \Note that key names cannot contain path separators:                                \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌─────────────────────────────────────┐                                        \n\\+          \    │ { `directory/example.txt` = \"ABC\" } │ Invalid: Key contains a forward slash\n\\+          \    └─────────────────────────────────────┘                                        \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \Instead, you need to refactor the expression to use nested records instead:        \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌───────────────────────────────────────────┐                                  \n\\+          \    │ { directory = { `example.txt` = \"ABC\" } } │                                \n\\+          \    └───────────────────────────────────────────┘                                  \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \You tried to translate the following expression to a directory tree:               \n\\+          \                                                                                   \n\\+          \" <> Util.insert unexpectedExpression <> "\n\\+          \                                                                                   \n\\+          \... which is not an expression that can be translated to a directory tree.         \n"++{- | This error indicates that you want to set some metadata for a file or+     directory, but that operation is not supported  on your platform.+-}+newtype MetadataUnsupportedError =+    MetadataUnsupportedError { metadataForPath :: FilePath }++instance Exception MetadataUnsupportedError++instance Show MetadataUnsupportedError where+    show MetadataUnsupportedError{..} =+        Pretty.renderString (Dhall.Pretty.layout message)+      where+        message =+          Util._ERROR <> ": Setting metadata is not supported on this platform.               \n\\+          \                                                                                   \n\\+          \Explanation: Your Dhall expression indicates that you intend to set some metadata  \n\\+          \like ownership or permissions for the following file or directory:                 \n\\+          \                                                                                   \n\\+          \" <> Pretty.pretty metadataForPath <> "\n\\+          \                                                                                   \n\\+          \... which is not supported on your platform.                                       \n"
+ src/Dhall/DirectoryTree/Types.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE LambdaCase         #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE PatternSynonyms    #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications   #-}+{-# LANGUAGE ViewPatterns       #-}++{-# OPTIONS_GHC -Wno-orphans #-}++-- | Types used by the implementation of the @to-directory-tree@ subcommand+module Dhall.DirectoryTree.Types+    ( FilesystemEntry(DirectoryEntry, BinaryFileEntry, TextFileEntry, FileEntry)+    , DirectoryEntry+    , FileEntry+    , BinaryFileEntry+    , TextFileEntry+    , Entry(..)+    , User(..)+    , Group(..)+    , Mode(..)+    , Access(..)++    , setFileMode+    , prettyFileMode++    , isMetadataSupported+    ) where++import Data.ByteString          (ByteString)+import Data.Functor.Identity    (Identity (..))+import Data.Sequence            (Seq)+import Data.Text                (Text)+import Dhall.Marshal.Decode+    ( Decoder (..)+    , FromDhall (..)+    , Generic+    , InputNormalizer+    , InterpretOptions (..)+    )+import Dhall.Syntax             (Expr (..), FieldSelection (..), Var (..))+import System.PosixCompat.Types (GroupID, UserID)++import qualified Data.Text                as Text+import qualified Dhall.Marshal.Decode     as Decode+import qualified System.PosixCompat.Files as Posix++#ifdef mingw32_HOST_OS+import Control.Monad            (unless)+import Data.Word                (Word32)+import System.IO                (hPutStrLn, stderr)+import System.PosixCompat.Types (CMode)++import qualified Unsafe.Coerce++type FileMode = CMode+#else+import System.PosixCompat.Types (FileMode)++import qualified System.PosixCompat.Types as Posix+#endif++pattern Make :: Text -> Expr s a -> Expr s a+pattern Make label entry <- App (Field (Var (V "_" 0)) (fieldSelectionLabel -> label)) entry++-- | A directory in the filesystem.+type DirectoryEntry = Entry (Seq FilesystemEntry)++-- | A file in the filesystem.+{-# DEPRECATED FileEntry "`FileEntry` is deprecated and will be removed eventually. Please use `TextFileEntry` instead." #-}+type FileEntry = Entry Text++-- | A binary file in the filesystem.+type BinaryFileEntry = Entry ByteString++-- | A text file in the filesystem.+type TextFileEntry = Entry Text++-- | A filesystem entry.+data FilesystemEntry+    = DirectoryEntry (Entry (Seq FilesystemEntry))+    | BinaryFileEntry BinaryFileEntry+    | TextFileEntry TextFileEntry+    deriving (Eq, Generic, Ord, Show)++pattern FileEntry :: Entry Text -> FilesystemEntry+pattern FileEntry entry = TextFileEntry entry++instance FromDhall FilesystemEntry where+    autoWith normalizer = Decoder+        { expected = pure $ Var (V "tree" 0)+        , extract = \case+            Make "directory" entry ->+                DirectoryEntry <$> extract (autoWith normalizer) entry+            Make "file" entry ->+                TextFileEntry <$> extract (autoWith normalizer) entry+            Make "binary-file" entry ->+                BinaryFileEntry <$> extract (autoWith normalizer) entry+            expr -> Decode.typeError (expected (Decode.autoWith normalizer :: Decoder FilesystemEntry)) expr+        }++-- | A generic filesystem entry. This type holds the metadata that apply to all+-- entries. It is parametric over the content of such an entry.+data Entry a = Entry+    { entryName :: String+    , entryContent :: a+    , entryUser :: Maybe User+    , entryGroup :: Maybe Group+    , entryMode :: Maybe (Mode Maybe)+    }+    deriving (Eq, Generic, Ord, Show)++instance FromDhall a => FromDhall (Entry a) where+    autoWith = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+        { fieldModifier = Text.toLower . Text.drop (Text.length "entry")+        }++-- | A user identified either by id or name.+data User+    = UserId UserID+    | UserName String+    deriving (Eq, Generic, Ord, Show)++instance FromDhall User++#ifdef mingw32_HOST_OS+instance FromDhall UserID where+    autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CUid where+    autoWith normalizer = Posix.CUid <$> autoWith normalizer+#endif++-- | A group identified either by id or name.+data Group+    = GroupId GroupID+    | GroupName String+    deriving (Eq, Generic, Ord, Show)++instance FromDhall Group++#ifdef mingw32_HOST_OS+instance FromDhall GroupID where+    autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CGid where+    autoWith normalizer = Posix.CGid <$> autoWith normalizer+#endif++-- | A filesystem mode. See chmod(1).+-- The parameter is meant to be instantiated by either `Identity` or `Maybe`+-- depending on the completeness of the information:+--  * For data read from the filesystem it will be `Identity`.+--  * For user-supplied data it will be `Maybe` as we want to be able to set+--    only specific bits.+data Mode f = Mode+    { modeUser :: f (Access f)+    , modeGroup :: f (Access f)+    , modeOther :: f (Access f)+    }+    deriving Generic++deriving instance Eq (Mode Identity)+deriving instance Eq (Mode Maybe)+deriving instance Ord (Mode Identity)+deriving instance Ord (Mode Maybe)+deriving instance Show (Mode Identity)+deriving instance Show (Mode Maybe)++instance FromDhall (Mode Identity) where+    autoWith = modeDecoder++instance FromDhall (Mode Maybe) where+    autoWith = modeDecoder++modeDecoder :: FromDhall (f (Access f)) => InputNormalizer -> Decoder (Mode f)+modeDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+    { fieldModifier = Text.toLower . Text.drop (Text.length "mode")+    }++-- | The permissions for a subject (user/group/other).+data Access f = Access+    { accessExecute :: f Bool+    , accessRead :: f Bool+    , accessWrite :: f Bool+    }+    deriving Generic++deriving instance Eq (Access Identity)+deriving instance Eq (Access Maybe)+deriving instance Ord (Access Identity)+deriving instance Ord (Access Maybe)+deriving instance Show (Access Identity)+deriving instance Show (Access Maybe)++instance FromDhall (Access Identity) where+    autoWith = accessDecoder++instance FromDhall (Access Maybe) where+    autoWith = accessDecoder++accessDecoder :: FromDhall (f Bool) => InputNormalizer -> Decoder (Access f)+accessDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+    { fieldModifier = Text.toLower . Text.drop (Text.length "access")+    }++++-- | A wrapper around `Posix.setFileMode`. On Windows, it does check the+-- resulting file mode of the file/directory and emits a warning if it doesn't+-- match the desired file mode. On all other OS it is identical to+-- `Posix.setFileMode` as it is assumed to work correctly.+setFileMode :: FilePath -> FileMode -> IO ()+#ifdef mingw32_HOST_OS+setFileMode fp mode = do+    Posix.setFileMode fp mode+    mode' <- Posix.fileMode <$> Posix.getFileStatus fp+    unless (mode' == mode) $ hPutStrLn stderr $+        "Warning: Setting file mode did not succeed for " <> fp <> "\n" <>+        "    Expected: " <> prettyFileMode mode <> "\n" <>+        "    Actual:   " <> prettyFileMode mode'+#else+setFileMode fp mode = Posix.setFileMode fp mode+#endif++-- | Pretty-print a `FileMode`. The format is similar to the one ls(1):+-- It is display as three blocks of three characters. The first block are the+-- permissions of the user, the second one are the ones of the group and the+-- third one the ones of other subjects. A @r@ denotes that the file or+-- directory is readable by the subject, a @w@ denotes that it is writable and+-- an @x@ denotes that it is executable. Unset permissions are represented by+-- @-@.+prettyFileMode :: FileMode -> String+prettyFileMode mode = userPP <> groupPP <> otherPP+    where+        userPP :: String+        userPP =+            isBitSet 'r' Posix.ownerReadMode <>+            isBitSet 'w' Posix.ownerWriteMode <>+            isBitSet 'x' Posix.ownerExecuteMode++        groupPP :: String+        groupPP =+            isBitSet 'r' Posix.groupReadMode <>+            isBitSet 'w' Posix.groupWriteMode <>+            isBitSet 'x' Posix.groupExecuteMode++        otherPP :: String+        otherPP =+            isBitSet 'r' Posix.otherReadMode <>+            isBitSet 'w' Posix.otherWriteMode <>+            isBitSet 'x' Posix.otherExecuteMode++        isBitSet :: Char -> FileMode -> String+        isBitSet c mask = if mask `Posix.intersectFileModes` mode /= Posix.nullFileMode+            then [c]+            else "-"++-- | Is setting metadata supported on this platform or not.+isMetadataSupported :: Bool+#ifdef mingw32_HOST_OS+isMetadataSupported = False+#else+isMetadataSupported = True+#endif
+ src/Dhall/Eval.hs view
@@ -0,0 +1,1567 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE PatternSynonyms      #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE StandaloneDeriving   #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns         #-}++{-| Eval-apply environment machine with conversion checking and quoting to+    normal forms. Fairly similar to GHCI's STG machine algorithmically, but much+    simpler, with no known call optimization or environment trimming.++    Potential optimizations without changing Expr:++    * In conversion checking, get non-shadowing variables not by linear+      Env-walking, but by keeping track of Env size, and generating names which+      are known to be illegal as source-level names (to rule out shadowing).++    * Use HashMap Text chunks for large let-definitions blocks. "Large" vs+      "Small" is fairly cheap to determine at evaluation time.++    Potential optimizations with changing Expr:++    * Use actual full de Bruijn indices in Var instead of Text counting indices.+      Then, we'd switch to full de Bruijn levels in Val as well, and use proper+      constant time non-shadowing name generation.+-}++module Dhall.Eval (+    judgmentallyEqual+  , normalize+  , alphaNormalize+  , eval+  , quote+  , envNames+  , countNames+  , conv+  , toVHPi+  , Closure(..)+  , Names(..)+  , Environment(..)+  , Val(..)+  , (~>)+  , textShow+  , dateShow+  , timeShow+  , timezoneShow+  ) where++import Data.Bifunctor     (first)+import Data.ByteString    (ByteString)+import Data.Foldable      (foldr', toList)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Sequence      (Seq, ViewL (..), ViewR (..))+import Data.Text          (Text)+import Data.Time          (Day, TimeOfDay (..), TimeZone)+import Data.Void          (Void)+import Dhall.Map          (Map)+import Dhall.Set          (Set)+import GHC.Natural        (Natural)+import Prelude            hiding (succ)++import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Expr (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Char+import qualified Data.Sequence as Sequence+import qualified Data.Set+import qualified Data.Text     as Text+import qualified Data.Time     as Time+import qualified Dhall.Map     as Map+import qualified Dhall.Set+import qualified Dhall.Syntax  as Syntax+import qualified Text.Printf   as Printf++data Environment a+    = Empty+    | Skip   !(Environment a) {-# UNPACK #-} !Text+    | Extend !(Environment a) {-# UNPACK #-} !Text (Val a)++deriving instance (Show a, Show (Val a -> Val a)) => Show (Environment a)++errorMsg :: String+errorMsg = unlines+  [ _ERROR <> ": Compiler bug                                                        "+  , "                                                                                "+  , "An ill-typed expression was encountered during normalization.                   "+  , "Explanation: This error message means that there is a bug in the Dhall compiler."+  , "You didn't do anything wrong, but if you would like to see this problem fixed   "+  , "then you should report the bug at:                                              "+  , "                                                                                "+  , "https://github.com/dhall-lang/dhall-haskell/issues                              "+  ]+  where+    _ERROR :: String+    _ERROR = "\ESC[1;31mError\ESC[0m"+++data Closure a = Closure !Text !(Environment a) !(Expr Void a)++deriving instance (Show a, Show (Val a -> Val a)) => Show (Closure a)++data VChunks a = VChunks ![(Text, Val a)] !Text++deriving instance (Show a, Show (Val a -> Val a)) => Show (VChunks a)++instance Semigroup (VChunks a) where+  VChunks xys z <> VChunks [] z' = VChunks xys (z <> z')+  VChunks xys z <> VChunks ((x', y'):xys') z' = VChunks (xys ++ (z <> x', y'):xys') z'++instance Monoid (VChunks a) where+  mempty = VChunks [] mempty++{-| Some information is lost when `eval` converts a `Lam` or a built-in function+    from the `Expr` type to a `VHLam` of the `Val` type and `quote` needs that+    information in order to reconstruct an equivalent `Expr`.  This `HLamInfo`+    type holds that extra information necessary to perform that reconstruction+-}+data HLamInfo a+  = Prim+  -- ^ Don't store any information+  | Typed !Text (Val a)+  -- ^ Store the original name and type of the variable bound by the `Lam`+  | NaturalSubtractZero+  -- ^ The original function was a @Natural/subtract 0@.  We need to preserve+  --   this information in case the @Natural/subtract@ ends up not being fully+  --   saturated, in which case we need to recover the unsaturated built-in+  | TextReplaceEmpty+  -- ^ The original function was a @Text/replace ""@+  | TextReplaceEmptyArgument (Val a)+  -- ^ The original function was a @Text/replace "" replacement@++deriving instance (Show a, Show (Val a -> Val a)) => Show (HLamInfo a)++pattern VPrim :: (Val a -> Val a) -> Val a+pattern VPrim f = VHLam Prim f++toVHPi :: Eq a => Val a -> Maybe (Text, Val a, Val a -> Val a)+toVHPi (VPi a b@(Closure x _ _)) = Just (x, a, instantiate b)+toVHPi (VHPi x a b             ) = Just (x, a, b)+toVHPi  _                        = Nothing+{-# INLINABLE toVHPi #-}++data Val a+    = VConst !Const+    | VVar !Text !Int+    | VPrimVar+    | VApp !(Val a) !(Val a)++    | VLam (Val a) {-# UNPACK #-} !(Closure a)+    | VHLam !(HLamInfo a) !(Val a -> Val a)++    | VPi (Val a) {-# UNPACK #-} !(Closure a)+    | VHPi !Text (Val a) !(Val a -> Val a)++    | VBool+    | VBoolLit !Bool+    | VBoolAnd !(Val a) !(Val a)+    | VBoolOr !(Val a) !(Val a)+    | VBoolEQ !(Val a) !(Val a)+    | VBoolNE !(Val a) !(Val a)+    | VBoolIf !(Val a) !(Val a) !(Val a)++    | VBytes+    | VBytesLit ByteString++    | VNatural+    | VNaturalLit !Natural+    | VNaturalFold !(Val a) !(Val a) !(Val a) !(Val a)+    | VNaturalBuild !(Val a)+    | VNaturalIsZero !(Val a)+    | VNaturalEven !(Val a)+    | VNaturalOdd !(Val a)+    | VNaturalToInteger !(Val a)+    | VNaturalShow !(Val a)+    | VNaturalSubtract !(Val a) !(Val a)+    | VNaturalPlus !(Val a) !(Val a)+    | VNaturalTimes !(Val a) !(Val a)++    | VInteger+    | VIntegerLit !Integer+    | VIntegerClamp !(Val a)+    | VIntegerNegate !(Val a)+    | VIntegerShow !(Val a)+    | VIntegerToDouble !(Val a)++    | VDouble+    | VDoubleLit !DhallDouble+    | VDoubleShow !(Val a)++    | VText+    | VTextLit !(VChunks a)+    | VTextAppend !(Val a) !(Val a)+    | VTextShow !(Val a)+    | VTextReplace !(Val a) !(Val a) !(Val a)++    | VDate+    | VDateLiteral Time.Day+    | VDateShow !(Val a)+    | VTime+    | VTimeLiteral Time.TimeOfDay Word+    | VTimeShow !(Val a)+    | VTimeZone+    | VTimeZoneLiteral Time.TimeZone+    | VTimeZoneShow !(Val a)++    | VList !(Val a)+    | VListLit !(Maybe (Val a)) !(Seq (Val a))+    | VListAppend !(Val a) !(Val a)+    | VListBuild   (Val a) !(Val a)+    | VListFold    (Val a) !(Val a) !(Val a) !(Val a) !(Val a)+    | VListLength  (Val a) !(Val a)+    | VListHead    (Val a) !(Val a)+    | VListLast    (Val a) !(Val a)+    | VListIndexed (Val a) !(Val a)+    | VListReverse (Val a) !(Val a)++    | VOptional (Val a)+    | VSome (Val a)+    | VNone (Val a)+    | VRecord !(Map Text (Val a))+    | VRecordLit !(Map Text (Val a))+    | VUnion !(Map Text (Maybe (Val a)))+    | VCombine !(Maybe Text) !(Val a) !(Val a)+    | VCombineTypes !(Val a) !(Val a)+    | VPrefer !(Val a) !(Val a)+    | VMerge !(Val a) !(Val a) !(Maybe (Val a))+    | VToMap !(Val a) !(Maybe (Val a))+    | VShowConstructor !(Val a)+    | VField !(Val a) !Text+    | VInject !(Map Text (Maybe (Val a))) !Text !(Maybe (Val a))+    | VProject !(Val a) !(Either (Set Text) (Val a))+    | VAssert !(Val a)+    | VEquivalent !(Val a) !(Val a)+    | VWith !(Val a) (NonEmpty WithComponent) !(Val a)+    | VEmbed a++-- | For use with "Text.Show.Functions".+deriving instance (Show a, Show (Val a -> Val a)) => Show (Val a)++(~>) :: Val a -> Val a -> Val a+(~>) a b = VHPi "_" a (\_ -> b)+{-# INLINE (~>) #-}++infixr 5 ~>++countEnvironment :: Text -> Environment a -> Int+countEnvironment x = go (0 :: Int)+  where+    go !acc Empty             = acc+    go  acc (Skip env x'    ) = go (if x == x' then acc + 1 else acc) env+    go  acc (Extend env x' _) = go (if x == x' then acc + 1 else acc) env++instantiate :: Eq a => Closure a -> Val a -> Val a+instantiate (Closure x env t) !u = eval (Extend env x u) t+{-# INLINE instantiate #-}++-- Out-of-env variables have negative de Bruijn levels.+vVar :: Environment a -> Var -> Val a+vVar env0 (V x i0) = go env0 i0+  where+    go (Extend env x' v) i+        | x == x' =+            if i == 0 then v else go env (i - 1)+        | otherwise =+            go env i+    go (Skip env x') i+        | x == x' =+            if i == 0 then VVar x (countEnvironment x env) else go env (i - 1)+        | otherwise =+            go env i+    go Empty i =+        VVar x (negate i - 1)++vApp :: Eq a => Val a -> Val a -> Val a+vApp !t !u =+    case t of+        VLam _ t'  -> instantiate t' u+        VHLam _ t' -> t' u+        t'        -> VApp t' u+{-# INLINE vApp #-}++vPrefer :: Eq a => Environment a -> Val a -> Val a -> Val a+vPrefer env t u =+    case (t, u) of+        (VRecordLit m, u') | null m ->+            u'+        (t', VRecordLit m) | null m ->+            t'+        (VRecordLit m, VRecordLit m') ->+            VRecordLit (Map.union m' m)+        (t', u') | conv env t' u' ->+            t'+        (t', u') ->+            VPrefer t' u'+{-# INLINE vPrefer #-}++vCombine :: Maybe Text -> Val a -> Val a -> Val a+vCombine mk t u =+    case (t, u) of+        (VRecordLit m, u') | null m ->+            u'+        (t', VRecordLit m) | null m ->+            t'+        (VRecordLit m, VRecordLit m') ->+            VRecordLit (Map.unionWith (vCombine Nothing) m m')+        (t', u') ->+            VCombine mk t' u'++vCombineTypes :: Val a -> Val a -> Val a+vCombineTypes t u =+    case (t, u) of+        (VRecord m, u') | null m ->+            u'+        (t', VRecord m) | null m ->+            t'+        (VRecord m, VRecord m') ->+            VRecord (Map.unionWith vCombineTypes m m')+        (t', u') ->+            VCombineTypes t' u'++vListAppend :: Val a -> Val a -> Val a+vListAppend t u =+    case (t, u) of+        (VListLit _ xs, u') | null xs ->+            u'+        (t', VListLit _ ys) | null ys ->+            t'+        (VListLit t' xs, VListLit _ ys) ->+            VListLit t' (xs <> ys)+        (t', u') ->+            VListAppend t' u'+{-# INLINE vListAppend #-}++vNaturalPlus :: Val a -> Val a -> Val a+vNaturalPlus t u =+    case (t, u) of+        (VNaturalLit 0, u') ->+            u'+        (t', VNaturalLit 0) ->+            t'+        (VNaturalLit m, VNaturalLit n) ->+            VNaturalLit (m + n)+        (t', u') ->+            VNaturalPlus t' u'+{-# INLINE vNaturalPlus #-}++vField :: Val a -> Text -> Val a+vField t0 k = go t0+  where+    go = \case+        VUnion m -> case Map.lookup k m of+            Just (Just _) -> VPrim $ \ ~u -> VInject m k (Just u)+            Just Nothing  -> VInject m k Nothing+            _             -> error errorMsg+        VRecordLit m+            | Just v <- Map.lookup k m -> v+            | otherwise -> error errorMsg+        VProject t _ -> go t+        VPrefer (VRecordLit m) r -> case Map.lookup k m of+            Just v -> VField (VPrefer (singletonVRecordLit v) r) k+            Nothing -> go r+        VPrefer l (VRecordLit m) -> case Map.lookup k m of+            Just v -> v+            Nothing -> go l+        VCombine mk (VRecordLit m) r -> case Map.lookup k m of+            Just v -> VField (VCombine mk (singletonVRecordLit v) r) k+            Nothing -> go r+        VCombine mk l (VRecordLit m) -> case Map.lookup k m of+            Just v -> VField (VCombine mk l (singletonVRecordLit v)) k+            Nothing -> go l+        t -> VField t k++    singletonVRecordLit v = VRecordLit (Map.singleton k v)+{-# INLINE vField #-}++vTextReplace :: Text -> Val a -> Text -> VChunks a+vTextReplace needle replacement haystack = go haystack+  where+    go t+        | Text.null suffix = VChunks [] t+        | otherwise =+            let remainder = Text.drop (Text.length needle) suffix++                rest = go remainder++            in  case replacement of+                    VTextLit replacementChunks ->+                        VChunks [] prefix <> replacementChunks <> rest+                    _ ->+                        VChunks [(prefix, replacement)] "" <> rest+      where+        (prefix, suffix) = Text.breakOn needle t++vProjectByFields :: Eq a => Environment a -> Val a -> Set Text -> Val a+vProjectByFields env t ks =+    if null ks+        then VRecordLit mempty+        else case t of+            VRecordLit kvs ->+                let kvs' = Map.restrictKeys kvs (Dhall.Set.toSet ks)+                in  VRecordLit kvs'+            VProject t' _ ->+                vProjectByFields env t' ks+            VPrefer l (VRecordLit kvs) ->+                let ksSet = Dhall.Set.toSet ks++                    kvs' = Map.restrictKeys kvs ksSet++                    ks' =+                        Dhall.Set.fromSet+                            (Data.Set.difference ksSet (Map.keysSet kvs'))++                in  vPrefer env (vProjectByFields env l ks') (VRecordLit kvs')+            t' ->+                VProject t' (Left ks)++vWith :: Val a -> NonEmpty WithComponent -> Val a -> Val a+vWith (VRecordLit kvs) (WithLabel k  :| []     ) v = VRecordLit (Map.insert k  v  kvs)+vWith (VRecordLit kvs) (WithLabel k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs)+  where+    e₁ =+        case Map.lookup k₀ kvs of+            Nothing  -> VRecordLit mempty+            Just e₁' -> e₁'++    e₂ = vWith e₁ (k₁ :| ks) v+vWith (VNone _T) (WithQuestion :| _      ) _ = VNone _T+vWith (VSome  _) (WithQuestion :| []     ) v = VSome v+vWith (VSome  t) (WithQuestion :| k₁ : ks) v = VSome (vWith t (k₁ :| ks) v)+vWith e₀ ks v₀ = VWith e₀ ks v₀++eval :: forall a. Eq a => Environment a -> Expr Void a -> Val a+eval !env t0 =+    case t0 of+        Const k ->+            VConst k+        Var v ->+            vVar env v+        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = a }) t ->+            VLam (eval env a) (Closure x env t)+        Pi _ x a b ->+            VPi (eval env a) (Closure x env b)+        App t u ->+            vApp (eval env t) (eval env u)+        Let (Binding _ x _ _mA _ a) b ->+            let !env' = Extend env x (eval env a)+            in  eval env' b+        Annot t _ ->+            eval env t+        Bool ->+            VBool+        BoolLit b ->+            VBoolLit b+        BoolAnd t u ->+            case (eval env t, eval env u) of+                (VBoolLit True, u')       -> u'+                (VBoolLit False, _)       -> VBoolLit False+                (t', VBoolLit True)       -> t'+                (_ , VBoolLit False)      -> VBoolLit False+                (t', u') | conv env t' u' -> t'+                (t', u')                  -> VBoolAnd t' u'+        BoolOr t u ->+            case (eval env t, eval env u) of+                (VBoolLit False, u')      -> u'+                (VBoolLit True, _)        -> VBoolLit True+                (t', VBoolLit False)      -> t'+                (_ , VBoolLit True)       -> VBoolLit True+                (t', u') | conv env t' u' -> t'+                (t', u')                  -> VBoolOr t' u'+        BoolEQ t u ->+            case (eval env t, eval env u) of+                (VBoolLit True, u')       -> u'+                (t', VBoolLit True)       -> t'+                (t', u') | conv env t' u' -> VBoolLit True+                (t', u')                  -> VBoolEQ t' u'+        BoolNE t u ->+            case (eval env t, eval env u) of+                (VBoolLit False, u')      -> u'+                (t', VBoolLit False)      -> t'+                (t', u') | conv env t' u' -> VBoolLit False+                (t', u')                  -> VBoolNE t' u'+        BoolIf b t f ->+            case (eval env b, eval env t, eval env f) of+                (VBoolLit True,  t', _ )            -> t'+                (VBoolLit False, _ , f')            -> f'+                (b', VBoolLit True, VBoolLit False) -> b'+                (_, t', f') | conv env t' f'        -> t'+                (b', t', f')                        -> VBoolIf b' t' f'+        Bytes ->+            VBytes+        BytesLit b ->+            VBytesLit b+        Natural ->+            VNatural+        NaturalLit n ->+            VNaturalLit n+        NaturalFold ->+            VPrim $ \n ->+            VPrim $ \natural ->+            VPrim $ \succ ->+            VPrim $ \zero ->+            let inert = VNaturalFold n natural succ zero+            in  case zero of+                VPrimVar -> inert+                _ -> case succ of+                    VPrimVar -> inert+                    _ -> case natural of+                        VPrimVar -> inert+                        _ -> case n of+                            VNaturalLit n' ->+                                -- Use an `Integer` for the loop, due to the+                                -- following issue:+                                --+                                -- https://github.com/ghcjs/ghcjs/issues/782+                                go zero (fromIntegral n' :: Integer) where+                                  go !acc 0 = acc+                                  go acc m =+                                  -- Detect a shortcut: if succ acc == acc then return acc immediately.+                                    let next = vApp succ acc+                                    in  if conv env next acc then acc else go next (m - 1)+                            _ -> inert+        NaturalBuild ->+            VPrim $ \case+                VPrimVar ->+                    VNaturalBuild VPrimVar+                t ->       t+                    `vApp` VNatural+                    `vApp` VHLam (Typed "n" VNatural) (\n -> vNaturalPlus n (VNaturalLit 1))+                    `vApp` VNaturalLit 0++        NaturalIsZero -> VPrim $ \case+            VNaturalLit n -> VBoolLit (n == 0)+            n             -> VNaturalIsZero n+        NaturalEven -> VPrim $ \case+            VNaturalLit n -> VBoolLit (even n)+            n             -> VNaturalEven n+        NaturalOdd -> VPrim $ \case+            VNaturalLit n -> VBoolLit (odd n)+            n             -> VNaturalOdd n+        NaturalToInteger -> VPrim $ \case+            VNaturalLit n -> VIntegerLit (fromIntegral n)+            n             -> VNaturalToInteger n+        NaturalShow -> VPrim $ \case+            VNaturalLit n -> VTextLit (VChunks [] (Text.pack (show n)))+            n             -> VNaturalShow n+        NaturalSubtract -> VPrim $ \case+            VNaturalLit 0 ->+                VHLam NaturalSubtractZero id+            x@(VNaturalLit m) ->+                VPrim $ \case+                    VNaturalLit n+                        | n >= m ->+                            -- Use an `Integer` for the subtraction, due to the+                            -- following issue:+                            --+                            -- https://github.com/ghcjs/ghcjs/issues/782+                            VNaturalLit (fromIntegral (subtract (fromIntegral m :: Integer) (fromIntegral n :: Integer)))+                        | otherwise -> VNaturalLit 0+                    y -> VNaturalSubtract x y+            x ->+                VPrim $ \case+                    VNaturalLit 0    -> VNaturalLit 0+                    y | conv env x y -> VNaturalLit 0+                    y                -> VNaturalSubtract x y+        NaturalPlus t u ->+            vNaturalPlus (eval env t) (eval env u)+        NaturalTimes t u ->+            case (eval env t, eval env u) of+                (VNaturalLit 1, u'           ) -> u'+                (t'           , VNaturalLit 1) -> t'+                (VNaturalLit 0, _            ) -> VNaturalLit 0+                (_            , VNaturalLit 0) -> VNaturalLit 0+                (VNaturalLit m, VNaturalLit n) -> VNaturalLit (m * n)+                (t'           , u'           ) -> VNaturalTimes t' u'+        Integer ->+            VInteger+        IntegerLit n ->+            VIntegerLit n+        IntegerClamp ->+            VPrim $ \case+                VIntegerLit n+                    | 0 <= n    -> VNaturalLit (fromInteger n)+                    | otherwise -> VNaturalLit 0+                n -> VIntegerClamp n+        IntegerNegate ->+            VPrim $ \case+                VIntegerLit n -> VIntegerLit (negate n)+                n             -> VIntegerNegate n+        IntegerShow ->+            VPrim $ \case+                VIntegerLit n+                    | 0 <= n    -> VTextLit (VChunks [] (Text.pack ('+':show n)))+                    | otherwise -> VTextLit (VChunks [] (Text.pack (show n)))+                n -> VIntegerShow n+        IntegerToDouble ->+            VPrim $ \case+                VIntegerLit n -> VDoubleLit (DhallDouble (read (show n)))+                -- `(read . show)` is used instead of `fromInteger`+                -- because `read` uses the correct rounding rule.+                -- See https://gitlab.haskell.org/ghc/ghc/issues/17231.+                n             -> VIntegerToDouble n+        Double ->+            VDouble+        DoubleLit n ->+            VDoubleLit n+        DoubleShow ->+            VPrim $ \case+                VDoubleLit (DhallDouble n) -> VTextLit (VChunks [] (Text.pack (show n)))+                n                          -> VDoubleShow n+        Text ->+            VText+        TextLit cs ->+            case evalChunks cs of+                VChunks [("", t)] "" -> t+                vcs                  -> VTextLit vcs+        TextAppend t u ->+            eval env (TextLit (Chunks [("", t), ("", u)] ""))+        TextShow ->+            VPrim $ \case+                VTextLit (VChunks [] x) -> VTextLit (VChunks [] (textShow x))+                t                       -> VTextShow t+        TextReplace ->+            VPrim $ \needle ->+            let hLamInfo0 = case needle of+                    VTextLit (VChunks [] "") -> TextReplaceEmpty+                    _                        -> Prim++            in  VHLam hLamInfo0 $ \replacement ->+            let hLamInfo1 = case needle of+                    VTextLit (VChunks [] "") ->+                        TextReplaceEmptyArgument replacement+                    _ ->+                        Prim+            in  VHLam hLamInfo1 $ \haystack ->+                    case needle of+                        VTextLit (VChunks [] "") ->+                            haystack++                        VTextLit (VChunks [] needleText) ->+                            case haystack of+                                VTextLit (VChunks [] haystackText) ->+                                    case replacement of+                                        VTextLit (VChunks [] replacementText) ->+                                            VTextLit $ VChunks []+                                                (Text.replace+                                                    needleText+                                                    replacementText+                                                    haystackText+                                                )+                                        _ ->+                                            VTextLit+                                                (vTextReplace+                                                    needleText+                                                    replacement+                                                    haystackText+                                                )+                                _ ->+                                    VTextReplace needle replacement haystack+                        _ ->+                            VTextReplace needle replacement haystack+        Date ->+            VDate+        DateLiteral d ->+            VDateLiteral d+        DateShow ->+            VPrim $ \case+                VDateLiteral d -> VTextLit (VChunks [] (dateShow d))+                t              -> VDateShow t+        Time ->+            VTime+        TimeLiteral t p ->+            VTimeLiteral t p+        TimeShow ->+            VPrim $ \case+                VTimeLiteral d p -> VTextLit (VChunks [] (timeShow d p))+                t                -> VTimeShow t+        TimeZone ->+            VTimeZone+        TimeZoneLiteral z ->+            VTimeZoneLiteral z+        TimeZoneShow ->+            VPrim $ \case+                VTimeZoneLiteral d -> VTextLit (VChunks [] (timezoneShow d))+                t                  -> VTimeZoneShow t+        List ->+            VPrim VList+        ListLit ma ts ->+            VListLit (fmap (eval env) ma) (fmap (eval env) ts)+        ListAppend t u ->+            vListAppend (eval env t) (eval env u)+        ListBuild ->+            VPrim $ \a ->+            VPrim $ \case+                VPrimVar ->+                    VListBuild a VPrimVar+                t ->       t+                    `vApp` VList a+                    `vApp` VHLam (Typed "a" a) (\x ->+                           VHLam (Typed "as" (VList a)) (\as ->+                           vListAppend (VListLit Nothing (pure x)) as))+                    `vApp` VListLit (Just (VList a)) mempty++        ListFold ->+            VPrim $ \a ->+            VPrim $ \as ->+            VPrim $ \list ->+            VPrim $ \cons ->+            VPrim $ \nil ->+            let inert = VListFold a as list cons nil+            in  case nil of+                VPrimVar -> inert+                _ -> case cons of+                    VPrimVar -> inert+                    _ -> case list of+                        VPrimVar -> inert+                        _ -> case a of+                            VPrimVar -> inert+                            _ -> case as of+                                VListLit _ as' ->+                                    foldr' (\x b -> cons `vApp` x `vApp` b) nil as'+                                _ -> inert+        ListLength ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as -> VNaturalLit (fromIntegral (Sequence.length as))+                as            -> VListLength a as+        ListHead ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    case Sequence.viewl as of+                        y :< _ -> VSome y+                        _      -> VNone a+                as ->+                    VListHead a as+        ListLast ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    case Sequence.viewr as of+                        _ :> t -> VSome t+                        _      -> VNone a+                as -> VListLast a as+        ListIndexed ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    let a' =+                            if null as+                            then Just (VList (VRecord (Map.unorderedFromList [("index", VNatural), ("value", a)])))+                            else Nothing++                        as' =+                            Sequence.mapWithIndex+                                (\i t ->+                                    VRecordLit+                                        (Map.unorderedFromList+                                            [ ("index", VNaturalLit (fromIntegral i))+                                            , ("value", t)+                                            ]+                                        )+                                )+                                as++                        in  VListLit a' as'+                t ->+                    VListIndexed a t+        ListReverse ->+            VPrim $ \ ~a ->+            VPrim $ \case+                VListLit t as | null as ->+                    VListLit t as+                VListLit _ as ->+                    VListLit Nothing (Sequence.reverse as)+                t ->+                    VListReverse a t+        Optional ->+            VPrim VOptional+        Some t ->+            VSome (eval env t)+        None ->+            VPrim $ \ ~a -> VNone a+        Record kts ->+            VRecord (Map.sort (eval env . recordFieldValue <$> kts))+        RecordLit kts ->+            VRecordLit (Map.sort (eval env . recordFieldValue <$> kts))+        Union kts ->+            VUnion (Map.sort (fmap (fmap (eval env)) kts))+        Combine _ mk t u ->+            vCombine mk (eval env t) (eval env u)+        CombineTypes _ t u ->+            vCombineTypes (eval env t) (eval env u)+        Prefer _ _ t u ->+            vPrefer env (eval env t) (eval env u)+        RecordCompletion t u ->+            eval env (Annot (Prefer mempty PreferFromCompletion (Field t def) u) (Field t typ))+          where+            def = Syntax.makeFieldSelection "default"+            typ = Syntax.makeFieldSelection "Type"+        Merge x y ma ->+            case (eval env x, eval env y, fmap (eval env) ma) of+                (VRecordLit m, VInject _ k mt, _)+                    | Just f <- Map.lookup k m -> maybe f (vApp f) mt+                    | otherwise                -> error errorMsg+                (VRecordLit m, VSome t, _)+                    | Just f <- Map.lookup "Some" m -> vApp f t+                    | otherwise                     -> error errorMsg+                (VRecordLit m, VNone _, _)+                    | Just t <- Map.lookup "None" m -> t+                    | otherwise                     -> error errorMsg+                (x', y', ma') -> VMerge x' y' ma'+        ToMap x ma ->+            case (eval env x, fmap (eval env) ma) of+                (VRecordLit m, ma'@(Just _)) | null m ->+                    VListLit ma' Sequence.empty+                (VRecordLit m, _) ->+                    let entry (k, v) =+                            VRecordLit+                                (Map.unorderedFromList+                                    [ ("mapKey", VTextLit $ VChunks [] k)+                                    , ("mapValue", v)+                                    ]+                                )++                        s = (Sequence.fromList . map entry . Map.toAscList) m++                    in  VListLit Nothing s+                (x', ma') ->+                    VToMap x' ma'+        ShowConstructor x ->+            case eval env x of+                VInject m k _+                    | Just _ <- Map.lookup k m -> VTextLit (VChunks [] k)+                    | otherwise                -> error errorMsg+                VSome _ -> VTextLit (VChunks [] "Some")+                VNone _ -> VTextLit (VChunks [] "None")+                x' -> VShowConstructor x'+        Field t (Syntax.fieldSelectionLabel -> k) ->+            vField (eval env t) k+        Project t (Left ks) ->+            vProjectByFields env (eval env t) (Dhall.Set.sort (Dhall.Set.fromList ks))+        Project t (Right e) ->+            case eval env e of+                VRecord kts ->+                    vProjectByFields env (eval env t) (Dhall.Set.fromSet (Map.keysSet kts))+                e' ->+                    VProject (eval env t) (Right e')+        Assert t ->+            VAssert (eval env t)+        Equivalent _ t u ->+            VEquivalent (eval env t) (eval env u)+        With e₀ ks v ->+            vWith (eval env e₀) ks (eval env v)+        Note _ e ->+            eval env e+        ImportAlt t _ ->+            eval env t+        Embed a ->+            VEmbed a+  where+    evalChunks :: Chunks Void a -> VChunks a+    evalChunks (Chunks xys z) = foldr' cons nil xys+      where+        cons (x, t) vcs =+            case eval env t of+                VTextLit vcs' -> VChunks [] x <> vcs' <> vcs+                t'            -> VChunks [(x, t')] mempty <> vcs++        nil = VChunks [] z+    {-# INLINE evalChunks #-}++eqListBy :: (a -> a -> Bool) -> [a] -> [a] -> Bool+eqListBy f = go+  where+    go (x:xs) (y:ys) | f x y = go xs ys+    go [] [] = True+    go _  _  = False+{-# INLINE eqListBy #-}++eqMapsBy :: Ord k => (v -> v -> Bool) -> Map k v -> Map k v -> Bool+eqMapsBy f mL mR =+    Map.size mL == Map.size mR+    && eqListBy eq (Map.toAscList mL) (Map.toAscList mR)+  where+    eq (kL, vL) (kR, vR) = kL == kR && f vL vR+{-# INLINE eqMapsBy #-}++eqMaybeBy :: (a -> a -> Bool) -> Maybe a -> Maybe a -> Bool+eqMaybeBy f = go+  where+    go (Just x) (Just y) = f x y+    go Nothing  Nothing  = True+    go _        _        = False+{-# INLINE eqMaybeBy #-}++-- | Utility that powers the @Text/show@ built-in+textShow :: Text -> Text+textShow text = "\"" <> Text.concatMap f text <> "\""+  where+    f '"'  = "\\\""+    f '$'  = "\\u0024"+    f '\\' = "\\\\"+    f '\b' = "\\b"+    f '\n' = "\\n"+    f '\r' = "\\r"+    f '\t' = "\\t"+    f '\f' = "\\f"+    f c | c <= '\x1F' = Text.pack (Printf.printf "\\u%04x" (Data.Char.ord c))+        | otherwise   = Text.singleton c++-- | Utility that powers the @Date/show@ built-in+dateShow :: Day -> Text+dateShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%0Y-%m-%d"++-- | Utility that powers the @Time/show@ built-in+timeShow :: TimeOfDay -> Word -> Text+timeShow (TimeOfDay hh mm seconds) precision =+    Text.pack (Printf.printf "%02d:%02d:%02d" hh mm ss <> suffix)+  where+    magnitude :: Integer+    magnitude = 10 ^ precision++    (ss, fraction) =+        truncate (seconds * fromInteger magnitude) `divMod` magnitude++    suffix+        | precision == 0 = ""+        | otherwise      = Printf.printf ".%0*d" precision fraction++-- | Utility that powers the @TimeZone/show@ built-in+timezoneShow :: TimeZone -> Text+timezoneShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%Ez"++conv :: forall a. Eq a => Environment a -> Val a -> Val a -> Bool+conv !env t0 t0' =+    case (t0, t0') of+        (VConst k, VConst k') ->+            k == k'+        (VVar x i, VVar x' i') ->+            x == x' && i == i'+        (VLam _ (freshClosure -> (x, v, t)), VLam _ t' ) ->+            convSkip x (instantiate t v) (instantiate t' v)+        (VLam _ (freshClosure -> (x, v, t)), VHLam _ t') ->+            convSkip x (instantiate t v) (t' v)+        (VLam _ (freshClosure -> (x, v, t)), t'        ) ->+            convSkip x (instantiate t v) (vApp t' v)+        (VHLam _ t, VLam _ (freshClosure -> (x, v, t'))) ->+            convSkip x (t v) (instantiate t' v)+        (VHLam _ t, VHLam _ t'                    ) ->+            let (x, v) = fresh "x" in convSkip x (t v) (t' v)+        (VHLam _ t, t'                            ) ->+            let (x, v) = fresh "x" in convSkip x (t v) (vApp t' v)+        (t, VLam _ (freshClosure -> (x, v, t'))) ->+            convSkip x (vApp t v) (instantiate t' v)+        (t, VHLam _ t'  ) ->+            let (x, v) = fresh "x" in convSkip x (vApp t v) (t' v)+        (VApp t u, VApp t' u') ->+            conv env t t' && conv env u u'+        (VPi a b, VPi a' (freshClosure -> (x, v, b'))) ->+            conv env a a' && convSkip x (instantiate b v) (instantiate b' v)+        (VPi a b, VHPi (fresh -> (x, v)) a' b') ->+            conv env a a' && convSkip x (instantiate b v) (b' v)+        (VHPi _ a b, VPi a' (freshClosure -> (x, v, b'))) ->+            conv env a a' && convSkip x (b v) (instantiate b' v)+        (VHPi _ a b, VHPi (fresh -> (x, v)) a' b') ->+            conv env a a' && convSkip x (b v) (b' v)+        (VBool, VBool) ->+            True+        (VBoolLit b, VBoolLit b') ->+            b == b'+        (VBoolAnd t u, VBoolAnd t' u') ->+            conv env t t' && conv env u u'+        (VBoolOr t u, VBoolOr t' u') ->+            conv env t t' && conv env u u'+        (VBoolEQ t u, VBoolEQ t' u') ->+            conv env t t' && conv env u u'+        (VBoolNE t u, VBoolNE t' u') ->+            conv env t t' && conv env u u'+        (VBoolIf t u v, VBoolIf t' u' v') ->+            conv env t t' && conv env u u' && conv env v v'+        (VBytes, VBytes) ->+            True+        (VBytesLit l, VBytesLit r) ->+            l == r+        (VNatural, VNatural) ->+            True+        (VNaturalLit n, VNaturalLit n') ->+            n == n'+        (VNaturalFold t _ u v, VNaturalFold t' _ u' v') ->+            conv env t t' && conv env u u' && conv env v v'+        (VNaturalBuild t, VNaturalBuild t') ->+            conv env t t'+        (VNaturalIsZero t, VNaturalIsZero t') ->+            conv env t t'+        (VNaturalEven t, VNaturalEven t') ->+            conv env t t'+        (VNaturalOdd t, VNaturalOdd t') ->+            conv env t t'+        (VNaturalToInteger t, VNaturalToInteger t') ->+            conv env t t'+        (VNaturalShow t, VNaturalShow t') ->+            conv env t t'+        (VNaturalSubtract x y, VNaturalSubtract x' y') ->+            conv env x x' && conv env y y'+        (VNaturalPlus t u, VNaturalPlus t' u') ->+            conv env t t' && conv env u u'+        (VNaturalTimes t u, VNaturalTimes t' u') ->+            conv env t t' && conv env u u'+        (VInteger, VInteger) ->+            True+        (VIntegerLit t, VIntegerLit t') ->+            t == t'+        (VIntegerClamp t, VIntegerClamp t') ->+            conv env t t'+        (VIntegerNegate t, VIntegerNegate t') ->+            conv env t t'+        (VIntegerShow t, VIntegerShow t') ->+            conv env t t'+        (VIntegerToDouble t, VIntegerToDouble t') ->+            conv env t t'+        (VDouble, VDouble) ->+            True+        (VDoubleLit n, VDoubleLit n') ->+            n == n'+        (VDoubleShow t, VDoubleShow t') ->+            conv env t t'+        (VText, VText) ->+            True+        (VTextLit cs, VTextLit cs') ->+            convChunks cs cs'+        (VTextAppend t u, VTextAppend t' u') ->+            conv env t t' && conv env u u'+        (VTextShow t, VTextShow t') ->+            conv env t t'+        (VTextReplace a b c, VTextReplace a' b' c') ->+            conv env a a' && conv env b b' && conv env c c'+        (VDate, VDate) ->+            True+        (VDateLiteral l, VDateLiteral r) ->+            l == r+        (VDateShow t, VDateShow t') ->+            conv env t t'+        (VTime, VTime) ->+            True+        (VTimeLiteral tl pl, VTimeLiteral tr pr) ->+            tl == tr && pl == pr+        (VTimeShow t, VTimeShow t') ->+            conv env t t'+        (VTimeZone, VTimeZone) ->+            True+        (VTimeZoneLiteral l, VTimeZoneLiteral r) ->+            l == r+        (VTimeZoneShow t, VTimeZoneShow t') ->+            conv env t t'+        (VList a, VList a') ->+            conv env a a'+        (VListLit _ xs, VListLit _ xs') ->+            eqListBy (conv env) (toList xs) (toList xs')+        (VListAppend t u, VListAppend t' u') ->+            conv env t t' && conv env u u'+        (VListBuild _ t, VListBuild _ t') ->+            conv env t t'+        (VListLength a t, VListLength a' t') ->+            conv env a a' && conv env t t'+        (VListHead _ t, VListHead _ t') ->+            conv env t t'+        (VListLast _ t, VListLast _ t') ->+            conv env t t'+        (VListIndexed _ t, VListIndexed _ t') ->+            conv env t t'+        (VListReverse _ t, VListReverse _ t') ->+            conv env t t'+        (VListFold a l _ t u, VListFold a' l' _ t' u') ->+            conv env a a' && conv env l l' && conv env t t' && conv env u u'+        (VOptional a, VOptional a') ->+            conv env a a'+        (VSome t, VSome t') ->+            conv env t t'+        (VNone _, VNone _) ->+            True+        (VRecord m, VRecord m') ->+            eqMapsBy (conv env) m m'+        (VRecordLit m, VRecordLit m') ->+            eqMapsBy (conv env) m m'+        (VUnion m, VUnion m') ->+            eqMapsBy (eqMaybeBy (conv env)) m m'+        (VCombine _ t u, VCombine _ t' u') ->+            conv env t t' && conv env u u'+        (VCombineTypes t u, VCombineTypes t' u') ->+            conv env t t' && conv env u u'+        (VPrefer t u, VPrefer t' u') ->+            conv env t t' && conv env u u'+        (VMerge t u _, VMerge t' u' _) ->+            conv env t t' && conv env u u'+        (VToMap t _, VToMap t' _) ->+            conv env t t'+        (VShowConstructor t, VShowConstructor t') ->+            conv env t t'+        (VField t k, VField t' k') ->+            conv env t t' && k == k'+        (VProject t (Left ks), VProject t' (Left ks')) ->+            conv env t t' && ks == ks'+        (VProject t (Right e), VProject t' (Right e')) ->+            conv env t t' && conv env e e'+        (VAssert t, VAssert t') ->+            conv env t t'+        (VEquivalent t u, VEquivalent t' u') ->+            conv env t t' && conv env u u'+        (VInject m k mt, VInject m' k' mt') ->+            eqMapsBy (eqMaybeBy (conv env)) m m' && k == k' && eqMaybeBy (conv env) mt mt'+        (VEmbed a, VEmbed a') ->+            a == a'+        (_, _) ->+            False+  where+    fresh :: Text -> (Text, Val a)+    fresh x = (x, VVar x (countEnvironment x env))+    {-# INLINE fresh #-}++    freshClosure :: Closure a -> (Text, Val a, Closure a)+    freshClosure closure@(Closure x _ _) = (x, snd (fresh x), closure)+    {-# INLINE freshClosure #-}++    convChunks :: VChunks a -> VChunks a -> Bool+    convChunks (VChunks xys z) (VChunks xys' z') =+      eqListBy (\(x, y) (x', y') -> x == x' && conv env y y') xys xys' && z == z'+    {-# INLINE convChunks #-}++    convSkip :: Text -> Val a -> Val a -> Bool+    convSkip x = conv (Skip env x)+    {-# INLINE convSkip #-}++judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool+judgmentallyEqual (Syntax.denote -> t) (Syntax.denote -> u) =+    conv Empty (eval Empty t) (eval Empty u)+{-# INLINABLE judgmentallyEqual #-}++data Names+  = EmptyNames+  | Bind !Names {-# UNPACK #-} !Text+  deriving Show++envNames :: Environment a -> Names+envNames Empty = EmptyNames+envNames (Skip   env x  ) = Bind (envNames env) x+envNames (Extend env x _) = Bind (envNames env) x++countNames :: Text -> Names -> Int+countNames x = go 0+  where+    go !acc EmptyNames         = acc+    go  acc (Bind env x') = go (if x == x' then acc + 1 else acc) env++-- | Quote a value into beta-normal form.+quote :: forall a. Eq a => Names -> Val a -> Expr Void a+quote !env !t0 =+    case t0 of+        VConst k ->+            Const k+        VVar !x !i ->+            Var (V x (countNames x env - i - 1))+        VApp t u ->+            quote env t `qApp` u+        VLam a (freshClosure -> (x, v, t)) ->+            Lam+                mempty+                (Syntax.makeFunctionBinding x (quote env a))+                (quoteBind x (instantiate t v))+        VHLam i t ->+            case i of+                Typed (fresh -> (x, v)) a ->+                    Lam mempty+                        (Syntax.makeFunctionBinding x (quote env a))+                        (quoteBind x (t v))+                Prim ->+                    quote env (t VPrimVar)+                NaturalSubtractZero ->+                    App NaturalSubtract (NaturalLit 0)+                TextReplaceEmpty ->+                    App TextReplace (TextLit (Chunks [] ""))+                TextReplaceEmptyArgument replacement ->+                    App (App TextReplace (TextLit (Chunks [] "")))+                        (quote env replacement)++        VPi a (freshClosure -> (x, v, b)) ->+            Pi mempty x (quote env a) (quoteBind x (instantiate b v))+        VHPi (fresh -> (x, v)) a b ->+            Pi mempty x (quote env a) (quoteBind x (b v))+        VBool ->+            Bool+        VBoolLit b ->+            BoolLit b+        VBoolAnd t u ->+            BoolAnd (quote env t) (quote env u)+        VBoolOr t u ->+            BoolOr (quote env t) (quote env u)+        VBoolEQ t u ->+            BoolEQ (quote env t) (quote env u)+        VBoolNE t u ->+            BoolNE (quote env t) (quote env u)+        VBoolIf t u v ->+            BoolIf (quote env t) (quote env u) (quote env v)+        VBytes ->+            Bytes+        VBytesLit b ->+            BytesLit b+        VNatural ->+            Natural+        VNaturalLit n ->+            NaturalLit n+        VNaturalFold a t u v ->+            NaturalFold `qApp` a `qApp` t `qApp` u `qApp` v+        VNaturalBuild t ->+            NaturalBuild `qApp` t+        VNaturalIsZero t ->+            NaturalIsZero `qApp` t+        VNaturalEven t ->+            NaturalEven `qApp` t+        VNaturalOdd t ->+            NaturalOdd `qApp` t+        VNaturalToInteger t ->+            NaturalToInteger `qApp` t+        VNaturalShow t ->+            NaturalShow `qApp` t+        VNaturalPlus t u ->+            NaturalPlus (quote env t) (quote env u)+        VNaturalTimes t u ->+            NaturalTimes (quote env t) (quote env u)+        VNaturalSubtract x y ->+            NaturalSubtract `qApp` x `qApp` y+        VInteger ->+            Integer+        VIntegerLit n ->+            IntegerLit n+        VIntegerClamp t ->+            IntegerClamp `qApp` t+        VIntegerNegate t ->+            IntegerNegate `qApp` t+        VIntegerShow t ->+            IntegerShow `qApp` t+        VIntegerToDouble t ->+            IntegerToDouble `qApp` t+        VDouble ->+            Double+        VDoubleLit n ->+            DoubleLit n+        VDoubleShow t ->+            DoubleShow `qApp` t+        VText ->+            Text+        VTextLit (VChunks xys z) ->+            TextLit (Chunks (fmap (fmap (quote env)) xys) z)+        VTextAppend t u ->+            TextAppend (quote env t) (quote env u)+        VTextShow t ->+            TextShow `qApp` t+        VTextReplace a b c ->+            TextReplace `qApp` a `qApp` b `qApp` c+        VDate ->+            Date+        VDateLiteral d ->+            DateLiteral d+        VDateShow t ->+            DateShow `qApp` t+        VTime ->+            Time+        VTimeLiteral t p ->+            TimeLiteral t p+        VTimeShow t ->+            TimeShow `qApp` t+        VTimeZone ->+            TimeZone+        VTimeZoneLiteral z ->+            TimeZoneLiteral z+        VTimeZoneShow t ->+            TimeZoneShow `qApp` t+        VList t ->+            List `qApp` t+        VListLit ma ts ->+            ListLit (fmap (quote env) ma) (fmap (quote env) ts)+        VListAppend t u ->+            ListAppend (quote env t) (quote env u)+        VListBuild a t ->+            ListBuild `qApp` a `qApp` t+        VListFold a l t u v ->+            ListFold `qApp` a `qApp` l `qApp` t `qApp` u `qApp` v+        VListLength a t ->+            ListLength `qApp` a `qApp` t+        VListHead a t ->+            ListHead `qApp` a `qApp` t+        VListLast a t ->+            ListLast `qApp` a `qApp` t+        VListIndexed a t ->+            ListIndexed `qApp` a `qApp` t+        VListReverse a t ->+            ListReverse `qApp` a `qApp` t+        VOptional a ->+            Optional `qApp` a+        VSome t ->+            Some (quote env t)+        VNone t ->+            None `qApp` t+        VRecord m ->+            Record (fmap quoteRecordField m)+        VRecordLit m ->+            RecordLit (fmap quoteRecordField m)+        VUnion m ->+            Union (fmap (fmap (quote env)) m)+        VCombine mk t u ->+            Combine mempty mk (quote env t) (quote env u)+        VCombineTypes t u ->+            CombineTypes mempty (quote env t) (quote env u)+        VPrefer t u ->+            Prefer mempty PreferFromSource (quote env t) (quote env u)+        VMerge t u ma ->+            Merge (quote env t) (quote env u) (fmap (quote env) ma)+        VToMap t ma ->+            ToMap (quote env t) (fmap (quote env) ma)+        VShowConstructor t ->+            ShowConstructor (quote env t)+        VField t k ->+            Field (quote env t) $ Syntax.makeFieldSelection k+        VProject t p ->+            Project (quote env t) (first Dhall.Set.toList (fmap (quote env) p))+        VAssert t ->+            Assert (quote env t)+        VEquivalent t u ->+            Equivalent mempty (quote env t) (quote env u)+        VWith e ks v ->+            With (quote env e) ks (quote env v)+        VInject m k Nothing ->+            Field (Union (fmap (fmap (quote env)) m)) $ Syntax.makeFieldSelection k+        VInject m k (Just t) ->+            Field (Union (fmap (fmap (quote env)) m)) (Syntax.makeFieldSelection k) `qApp` t+        VEmbed a ->+            Embed a+        VPrimVar ->+            error errorMsg+  where+    fresh :: Text -> (Text, Val a)+    fresh x = (x, VVar x (countNames x env))+    {-# INLINE fresh #-}++    freshClosure :: Closure a -> (Text, Val a, Closure a)+    freshClosure closure@(Closure x _ _) = (x, snd (fresh x), closure)+    {-# INLINE freshClosure #-}++    quoteBind :: Text -> Val a -> Expr Void a+    quoteBind x = quote (Bind env x)+    {-# INLINE quoteBind #-}++    qApp :: Expr Void a -> Val a -> Expr Void a+    qApp t VPrimVar = t+    qApp t u        = App t (quote env u)+    {-# INLINE qApp #-}++    quoteRecordField :: Val a -> RecordField Void a+    quoteRecordField = Syntax.makeRecordField . quote env+    {-# INLINE quoteRecordField #-}++-- | Normalize an expression in an environment of values. Any variable pointing out of+--   the environment is treated as opaque free variable.+nf :: Eq a => Environment a -> Expr s a -> Expr t a+nf !env = Syntax.renote . quote (envNames env) . eval env . Syntax.denote++normalize :: Eq a => Expr s a -> Expr t a+normalize = nf Empty+{-# INLINABLE normalize #-}++alphaNormalize :: Expr s a -> Expr s a+alphaNormalize = goEnv EmptyNames+  where+    goVar :: Names -> Text -> Int -> Expr s a+    goVar e topX topI = go 0 e topI+      where+        go !acc (Bind env x) !i+          | x == topX = if i == 0 then Var (V "_" acc) else go (acc + 1) env (i - 1)+          | otherwise = go (acc + 1) env i+        go _ EmptyNames i = Var (V topX i)++    goEnv :: Names -> Expr s a -> Expr s a+    goEnv !e0 t0 =+        case t0 of+            Const k ->+                Const k+            Var (V x i) ->+                goVar e0 x i+            Lam cs (FunctionBinding src0 x src1 src2 t) u ->+                Lam cs (FunctionBinding src0 "_" src1 src2 (go t)) (goBind x u)+            Pi cs x a b ->+                Pi cs "_" (go a) (goBind x b)+            App t u ->+                App (go t) (go u)+            Let (Binding src0 x src1 mA src2 a) b ->+                Let (Binding src0 "_" src1 (fmap (fmap go) mA) src2 (go a)) (goBind x b)+            Annot t u ->+                Annot (go t) (go u)+            Bool ->+                Bool+            BoolLit b ->+                BoolLit b+            BoolAnd t u ->+                BoolAnd (go t) (go u)+            BoolOr t u ->+                BoolOr  (go t) (go u)+            BoolEQ t u ->+                BoolEQ  (go t) (go u)+            BoolNE t u ->+                BoolNE  (go t) (go u)+            BoolIf b t f ->+                BoolIf  (go b) (go t) (go f)+            Bytes ->+                Bytes+            BytesLit b ->+                BytesLit b+            Natural ->+                Natural+            NaturalLit n ->+                NaturalLit n+            NaturalFold ->+                NaturalFold+            NaturalBuild ->+                NaturalBuild+            NaturalIsZero ->+                NaturalIsZero+            NaturalEven ->+                NaturalEven+            NaturalOdd ->+                NaturalOdd+            NaturalToInteger ->+                NaturalToInteger+            NaturalShow ->+                NaturalShow+            NaturalSubtract ->+                NaturalSubtract+            NaturalPlus t u ->+                NaturalPlus (go t) (go u)+            NaturalTimes t u ->+                NaturalTimes (go t) (go u)+            Integer ->+                Integer+            IntegerLit n ->+                IntegerLit n+            IntegerClamp ->+                IntegerClamp+            IntegerNegate ->+                IntegerNegate+            IntegerShow ->+                IntegerShow+            IntegerToDouble ->+                IntegerToDouble+            Double ->+                Double+            DoubleLit n ->+                DoubleLit n+            DoubleShow ->+                DoubleShow+            Text ->+                Text+            TextLit cs ->+                TextLit (goChunks cs)+            TextAppend t u ->+                TextAppend (go t) (go u)+            TextShow ->+                TextShow+            TextReplace ->+                TextReplace+            Date ->+                Date+            DateLiteral d ->+                DateLiteral d+            DateShow ->+                DateShow+            Time ->+                Time+            TimeLiteral t p ->+                TimeLiteral t p+            TimeShow ->+                TimeShow+            TimeZone ->+                TimeZone+            TimeZoneLiteral z ->+                TimeZoneLiteral z+            TimeZoneShow ->+                TimeZoneShow+            List ->+                List+            ListLit ma ts ->+                ListLit (fmap go ma) (fmap go ts)+            ListAppend t u ->+                ListAppend (go t) (go u)+            ListBuild ->+                ListBuild+            ListFold ->+                ListFold+            ListLength ->+                ListLength+            ListHead ->+                ListHead+            ListLast ->+                ListLast+            ListIndexed ->+                ListIndexed+            ListReverse ->+                ListReverse+            Optional ->+                Optional+            Some t ->+                Some (go t)+            None ->+                None+            Record kts ->+                Record (goRecordField <$> kts)+            RecordLit kts ->+                RecordLit (goRecordField <$> kts)+            Union kts ->+                Union (fmap (fmap go) kts)+            Combine cs m t u ->+                Combine cs m (go t) (go u)+            CombineTypes cs t u ->+                CombineTypes cs (go t) (go u)+            Prefer cs b t u ->+                Prefer cs b (go t) (go u)+            RecordCompletion t u ->+                RecordCompletion (go t) (go u)+            Merge x y ma ->+                Merge (go x) (go y) (fmap go ma)+            ToMap x ma ->+                ToMap (go x) (fmap go ma)+            ShowConstructor x ->+                ShowConstructor (go x)+            Field t k ->+                Field (go t) k+            Project t ks ->+                Project (go t) (fmap go ks)+            Assert t ->+                Assert (go t)+            Equivalent cs t u ->+                Equivalent cs (go t) (go u)+            With e k v ->+                With (go e) k (go v)+            Note s e ->+                Note s (go e)+            ImportAlt t u ->+                ImportAlt (go t) (go u)+            Embed a ->+                Embed a+      where+        go                     = goEnv e0+        goBind x               = goEnv (Bind e0 x)+        goChunks (Chunks ts x) = Chunks (fmap (fmap go) ts) x+        goRecordField (RecordField s0 e s1 s2) = RecordField s0 (go e) s1 s2
+ src/Dhall/Format.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++-- | This module contains the implementation of the @dhall format@ subcommand++module Dhall.Format+    ( -- * Format+      Format(..)+    , format+    ) where++import Data.Foldable      (for_)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe         (fromMaybe)+import Dhall.Pretty       (CharacterSet, annToAnsiStyle, detectCharacterSet)+import Dhall.Util+    ( Censor+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    )++import qualified Data.Text.IO+import qualified Dhall.Import+import qualified Dhall.Pretty+import qualified Dhall.Util+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty.Terminal+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified System.Console.ANSI+import qualified System.FilePath+import qualified System.IO++-- | Arguments to the `format` subcommand+data Format = Format+    { chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor+    , transitivity       :: Transitivity+    , inputs             :: NonEmpty Input+    , outputMode         :: OutputMode+    }++-- | Implementation of the @dhall format@ subcommand+format :: Format -> IO ()+format (Format { inputs = inputs0, transitivity = transitivity0, ..}) =+    handleMultipleChecksFailed "format" "formatted" go inputs0+  where+    go input = do+        let directory = case input of+                StandardInput ->+                    "."+                InputFile file ->+                    System.FilePath.takeDirectory file++        let status = Dhall.Import.emptyStatus directory++        let layoutHeaderAndExpr (Header header, expr) =+                let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet+                in+                Dhall.Pretty.layout+                    (   Pretty.pretty header+                    <>  Dhall.Pretty.prettyCharacterSet characterSet expr+                    <>  "\n")++        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Data.Text.IO.readFile file++                return (file, text, transitivity0)+            StandardInput -> do+                text <- Data.Text.IO.getContents++                return ("(input)", text, NonTransitive)+++        headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText++        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_++                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath)++            NonTransitive ->+                return ()++        let docStream = layoutHeaderAndExpr headerAndExpr++        let formattedText = Pretty.Text.renderStrict docStream++        case outputMode of+            Write -> do+                case input of+                    InputFile file ->+                        if originalText == formattedText+                            then return ()+                            else AtomicWrite.LazyText.atomicWriteFile+                                    file+                                    (Pretty.Text.renderLazy docStream)++                    StandardInput -> do+                        supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout++                        Pretty.Terminal.renderIO+                            System.IO.stdout+                            (if supportsANSI+                                then (fmap annToAnsiStyle docStream)+                                else (Pretty.unAnnotateS docStream))++                return (Right ())++            Check ->+                return $+                    if originalText == formattedText+                        then Right ()+                        else Left CheckFailed{..}
+ src/Dhall/Freeze.hs view
@@ -0,0 +1,445 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}++-- | This module contains the implementation of the @dhall freeze@ subcommand++module Dhall.Freeze+    ( -- * Freeze+      freeze+    , freezeExpression+    , freezeImport+    , freezeRemoteImport++      -- * Freeze with custom evaluation settings+    , freezeWithSettings+    , freezeExpressionWithSettings+    , freezeImportWithSettings+    , freezeRemoteImportWithSettings++      -- * Types+    , Scope(..)+    , Intent(..)++      -- * Deprecated functions+    , freezeWithManager+    , freezeExpressionWithManager+    , freezeImportWithManager+    , freezeRemoteImportWithManager+    ) where++import Data.Foldable       (for_)+import Data.List.NonEmpty  (NonEmpty)+import Data.Maybe          (fromMaybe)+import Dhall               (EvaluateSettings)+import Dhall.Pretty        (CharacterSet, detectCharacterSet)+import Dhall.Syntax+    ( Expr (..)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    )+import Dhall.Util+    ( Censor+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    )+import Lens.Micro          (set, transformMOf, transformOf)+import Lens.Micro.Extras   (view)+import System.Console.ANSI (hSupportsANSI)++import qualified Control.Exception                  as Exception+import qualified Control.Monad.Trans.State.Strict   as State+import qualified Data.Text.IO                       as Text.IO+import qualified Dhall+import qualified Dhall.Core                         as Core+import qualified Dhall.Import+import qualified Dhall.Pretty+import qualified Dhall.TypeCheck+import qualified Dhall.Util                         as Util+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified System.FilePath+import qualified System.IO++-- | Specifies which imports to freeze+data Scope+    = OnlyRemoteImports+    -- ^ Freeze only remote imports (i.e. URLs)+    | AllImports+    -- ^ Freeze all imports (including paths and environment variables)++-- | Specifies why we are adding semantic integrity checks+data Intent+    = Secure+    -- ^ Protect imports with an integrity check without a fallback so that+    --   import resolution fails if the import changes+    | Cache+    -- ^ Protect imports with an integrity check and also add a fallback import+    --   import without an integrity check.  This is useful if you only want to+    --   cache imports when possible but still gracefully degrade to resolving+    --   them if the semantic integrity check has changed.++-- | Retrieve an `Import` and update the hash to match the latest contents+freezeImport+    :: FilePath+    -- ^ Current working directory+    -> Import+    -> IO Import+freezeImport = freezeImportWithSettings Dhall.defaultEvaluateSettings++-- | See 'freezeImport'.+freezeImportWithManager+    :: IO Dhall.Import.Manager+    -> FilePath+    -> Import+    -> IO Import+freezeImportWithManager newManager = freezeImportWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeImportWithManager "Use freezeImportWithSettings directly" #-}++-- | Freeze an import only if the import is a `Remote` import+freezeRemoteImport+    :: FilePath+    -- ^ Current working directory+    -> Import+    -> IO Import+freezeRemoteImport = freezeRemoteImportWithSettings Dhall.defaultEvaluateSettings++-- | See 'freezeRemoteImport'.+freezeRemoteImportWithManager+    :: IO Dhall.Import.Manager+    -> FilePath+    -> Import+    -> IO Import+freezeRemoteImportWithManager newManager = freezeRemoteImportWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeRemoteImportWithManager "Use freezeRemoteImportWithSettings directly" #-}++-- | Implementation of the @dhall freeze@ subcommand+freeze+    :: OutputMode+    -> Transitivity+    -> NonEmpty Input+    -> Scope+    -> Intent+    -> Maybe CharacterSet+    -> Censor+    -> IO ()+freeze = freezeWithSettings Dhall.defaultEvaluateSettings++-- | See 'freeze'.+freezeWithManager+    :: IO Dhall.Import.Manager+    -> OutputMode+    -> Transitivity+    -> NonEmpty Input+    -> Scope+    -> Intent+    -> Maybe CharacterSet+    -> Censor+    -> IO ()+freezeWithManager newManager = freezeWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeWithManager "Use freezeWithSettings directly" #-}++{-| Slightly more pure version of the `freeze` function++    This still requires `IO` to freeze the import, but now the input and output+    expression are passed in explicitly+-}+freezeExpression+    :: FilePath+    -- ^ Starting directory+    -> Scope+    -> Intent+    -> Expr s Import+    -> IO (Expr s Import)+freezeExpression = freezeExpressionWithSettings Dhall.defaultEvaluateSettings++-- | See 'freezeExpression'.+freezeExpressionWithManager+    :: IO Dhall.Import.Manager+    -> FilePath+    -> Scope+    -> Intent+    -> Expr s Import+    -> IO (Expr s Import)+freezeExpressionWithManager newManager = freezeExpressionWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeExpressionWithManager "Use freezeExpressionWithSettings directly" #-}++--------------------------------------------------------------------------------+-- Versions that take EvaluateSettings+--------------------------------------------------------------------------------++-- | See 'freezeImport'.+freezeImportWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Import+    -> IO Import+freezeImportWithSettings settings directory import_ = do+    let unprotectedImport =+            import_+                { importHashed =+                    (importHashed import_)+                        { hash = Nothing+                        }+                }++    let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory++    expression <- State.evalStateT (Dhall.Import.loadWith (Embed unprotectedImport)) status++    case Dhall.TypeCheck.typeWith (view Dhall.startingContext settings) expression of+        Left  exception -> Exception.throwIO exception+        Right _         -> return ()++    let normalizedExpression = Core.alphaNormalize (Core.normalizeWith (view Dhall.normalizer settings) expression)++    -- make sure the frozen import is present in the semantic cache+    Dhall.Import.writeExpressionToSemanticCache (Core.denote expression)++    let expressionHash = Dhall.Import.hashExpression normalizedExpression++    let newImportHashed = (importHashed import_) { hash = Just expressionHash }++    let newImport = import_ { importHashed = newImportHashed }++    return newImport++-- | See 'freezeRemoteImport'.+freezeRemoteImportWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Import+    -> IO Import+freezeRemoteImportWithSettings settings directory import_ =+    case importType (importHashed import_) of+        Remote {} -> freezeImportWithSettings settings directory import_+        _         -> return import_++-- | See 'freezeRemoteImport'.+freezeNonMissingImportWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Import+    -> IO Import+freezeNonMissingImportWithSettings settings directory import_ =+    case importType (importHashed import_) of+        Missing -> return import_+        _ -> freezeImportWithSettings settings directory import_++-- | See 'freeze'.+freezeWithSettings+    :: EvaluateSettings+    -> OutputMode+    -> Transitivity+    -> NonEmpty Input+    -> Scope+    -> Intent+    -> Maybe CharacterSet+    -> Censor+    -> IO ()+freezeWithSettings settings outputMode transitivity0 inputs scope intent chosenCharacterSet censor =+    handleMultipleChecksFailed "freeze" "frozen" go inputs+  where+    go input = do+        let directory = case input of+                StandardInput ->+                    "."+                InputFile file ->+                    System.FilePath.takeDirectory file++        let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory++        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Text.IO.readFile file++                return (file, text, transitivity0)++            StandardInput -> do+                text <- Text.IO.getContents++                return ("(input)", text, NonTransitive)++        (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText++        let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet++        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_++                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath)++            NonTransitive ->+                return ()++        frozenExpression <- freezeExpressionWithSettings settings directory scope intent parsedExpression++        let doc =  Pretty.pretty header+                <> Dhall.Pretty.prettyCharacterSet characterSet frozenExpression+                <> "\n"++        let stream = Dhall.Pretty.layout doc++        let modifiedText = Pretty.Text.renderStrict stream++        case outputMode of+            Write -> do+                let unAnnotated = Pretty.unAnnotateS stream++                case input of+                    InputFile file ->+                        if originalText == modifiedText+                            then return ()+                            else+                                AtomicWrite.LazyText.atomicWriteFile+                                    file+                                    (Pretty.Text.renderLazy unAnnotated)++                    StandardInput -> do+                        supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout+                        if supportsANSI+                           then+                             Pretty.renderIO System.IO.stdout (Dhall.Pretty.annToAnsiStyle <$> stream)+                           else+                             Pretty.renderIO System.IO.stdout unAnnotated++                return (Right ())++            Check ->+                return $+                    if originalText == modifiedText+                        then Right ()+                        else Left CheckFailed{..}++-- | See 'freezeExpression'.+freezeExpressionWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Scope+    -> Intent+    -> Expr s Import+    -> IO (Expr s Import)+freezeExpressionWithSettings settings directory scope intent expression = do+    let freezeScope =+            case scope of+                AllImports        -> freezeNonMissingImportWithSettings+                OnlyRemoteImports -> freezeRemoteImportWithSettings++    let freezeFunction = freezeScope settings directory++    let cache+            -- This case is necessary because `transformOf` is a bottom-up+            -- rewrite rule.   Without this rule, if you were to transform a+            -- file that already has a cached expression, like this:+            --+            --     someImport sha256:… ? someImport+            --+            -- ... then you would get:+            --+            --       (someImport sha256:… ? someImport)+            --     ? (someImport sha256:… ? someImport)+            --+            -- ... and this rule fixes that by collapsing that back to:+            --+            --       (someImport sha256:… ? someImport)+            (ImportAlt+                (Core.shallowDenote -> ImportAlt+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Just _expectedHash } }+                    )+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Nothing } }+                    )+                )+                import_@(Core.shallowDenote -> ImportAlt+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Just _actualHash } }+                    )+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Nothing } }+                    )+                )+            ) =+                {- Here we could actually compare the `_expectedHash` and+                   `_actualHash` to see if they differ, but we choose not to do+                   so and instead automatically accept the `_actualHash`.  This+                   is done for the same reason that the `freeze*` functions+                   ignore hash mismatches: the user intention when using `dhall+                   freeze` is to update the hash, which they expect to possibly+                   change.+                -}+                return import_+        cache+            (Embed import_@(Import { importHashed = ImportHashed { hash = Nothing } })) = do+                frozenImport <- freezeFunction import_++                let frozenMissing = toMissing frozenImport++                {- The two imports can be the same if the import is local and+                   `freezeFunction` only freezes remote imports by default+                -}+                if frozenImport /= import_+                    then return (ImportAlt (Embed frozenMissing) (Embed import_))+                    else return (Embed import_)+        cache+            (Embed import_@(Import { importHashed = ImportHashed { hash = Just _ } })) = do+                -- Regenerate the integrity check, just in case it's wrong+                frozenImport <- freezeFunction import_++                let frozenMissing = toMissing frozenImport++                -- `dhall freeze --cache` also works the other way around, adding an+                -- unprotected fallback import to imports that are already+                -- protected+                let thawedImport = import_+                        { importHashed = (importHashed import_)+                            { hash = Nothing+                            }+                        }++                return (ImportAlt (Embed frozenMissing) (Embed thawedImport))+        cache expression_ =+            return expression_++    let uncache+            (ImportAlt+                (Core.shallowDenote -> Embed+                    Import{ importHashed = ImportHashed { hash = Just expectedHash, importType = Missing } }+                )+                (Core.shallowDenote -> Embed+                    import_@Import{ importHashed = ImportHashed{ hash = Nothing } }+                )+            ) = Embed+                (import_+                    { importHashed = (importHashed import_)+                        { hash = Just expectedHash+                        }+                    }+                )+        uncache expression_ = expression_++    let simplify (ImportAlt (Core.shallowDenote -> Embed import1) (Core.shallowDenote -> Embed import2))+            | import1 == import2 = Embed import1+        simplify expression_ = expression_++    transformOf Core.subExpressions simplify <$> case intent of+        Secure ->+            traverse freezeFunction (transformOf Core.subExpressions uncache expression)+        Cache  ->+            transformMOf Core.subExpressions cache expression++-- https://github.com/dhall-lang/dhall-haskell/issues/2347+toMissing :: Import -> Import+toMissing import_ =+    import_ { importHashed = (importHashed import_) { importType = Missing } }
src/Dhall/Import.hs view
@@ -1,873 +1,1401 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE DeriveDataTypeable  #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE RecordWildCards     #-}-{-# OPTIONS_GHC -Wall #-}--{-| Dhall lets you import external expressions located either in local files or-    hosted on network endpoints.--    To import a local file as an expression, just insert the path to the file,-    prepending a @./@ if the path is relative to the current directory.  For-    example, if you create a file named @id@ with the following contents:--    > $ cat id-    > λ(a : Type) → λ(x : a) → x--    Then you can use the file directly within a @dhall@ program just by-    referencing the file's path:--    > $ dhall-    > ./id Bool True-    > <Ctrl-D>-    > Bool-    >-    > True--    Imported expressions may contain imports of their own, too, which will-    continue to be resolved.  However, Dhall will prevent cyclic imports.  For-    example, if you had these two files:--    > $ cat foo-    > ./bar--    > $ cat bar-    > ./foo--    ... Dhall would throw the following exception if you tried to import @foo@:--    > $ dhall-    > ./foo-    > ^D-    > ↳ ./foo-    >   ↳ ./bar-    >-    > Cyclic import: ./foo--    You can also import expressions hosted on network endpoints.  Just use the-    URL--    > http://host[:port]/path--    The compiler expects the downloaded expressions to be in the same format-    as local files, specifically UTF8-encoded source code text.--    For example, if our @id@ expression were hosted at @http://example.com/id@,-    then we would embed the expression within our code using:--    > http://example.com/id--    You can also reuse directory names as expressions.  If you provide a path-    to a local or remote directory then the compiler will look for a file named-    @\@@ within that directory and use that file to represent the directory.--    You can also import expressions stored within environment variables using-    @env:NAME@, where @NAME@ is the name of the environment variable.  For-    example:--    > $ export FOO=1-    > $ export BAR='"Hi"'-    > $ export BAZ='λ(x : Bool) → x == False'-    > $ dhall <<< "{ foo = env:FOO , bar = env:BAR , baz = env:BAZ }"-    > { bar : Text, baz : ∀(x : Bool) → Bool, foo : Integer }-    >-    > { bar = "Hi", baz = λ(x : Bool) → x == False, foo = 1 }--    If you wish to import the raw contents of a path as @Text@ then add-    @as Text@ to the end of the import:--    > $ dhall <<< "http://example.com as Text"-    > Text-    >-    > "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta-    >  charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html-    > ; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,-    > initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro-    > und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil-    > y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n-    >    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi-    > ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n-    >     a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;-    > \n    }\n    @media (max-width: 700px) {\n        body {\n            background-    > -color: #fff;\n        }\n        div {\n            width: auto;\n            m-    > argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n-    >   }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</-    > h1>\n    <p>This domain is established to be used for illustrative examples in d-    > ocuments. You may use this\n    domain in examples without prior coordination or-    >  asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl-    > e\">More information...</a></p>\n</div>\n</body>\n</html>\n"--}--module Dhall.Import (-    -- * Import-      exprFromPath-    , load-    , loadWith-    , loadWithContext-    , hashExpression-    , hashExpressionToCode-    , Status(..)-    , emptyStatus-    , Cycle(..)-    , ReferentiallyOpaque(..)-    , Imported(..)-    , PrettyHttpException(..)-    , MissingFile(..)-    , MissingEnvironmentVariable(..)-    ) where--import Control.Applicative (empty)-import Control.Exception-    (Exception, IOException, SomeException, onException, throwIO)-import Control.Monad (join)-import Control.Monad.Catch (throwM, MonadCatch(catch))-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad.Trans.State.Strict (StateT)-import Crypto.Hash (SHA256)-import Data.ByteString.Lazy (ByteString)-import Data.CaseInsensitive (CI)-import Data.Map (Map)-import Data.Monoid ((<>))-import Data.Text.Buildable (build)-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-#if MIN_VERSION_base(4,8,0)-#else-import Data.Traversable (traverse)-#endif-import Data.Typeable (Typeable)-import System.FilePath ((</>))-import Dhall.Core-    ( Expr(..)-    , Chunks(..)-    , HasHome(..)-    , PathHashed(..)-    , PathMode(..)-    , PathType(..)-    , Path(..)-    )-import Dhall.Parser (Parser(..), ParseError(..), Src(..))-import Dhall.TypeCheck (X(..))-import Lens.Family (LensLike')-import Lens.Family.State.Strict (zoom)-#if MIN_VERSION_http_client(0,5,0)-import Network.HTTP.Client-    (HttpException(..), HttpExceptionContent(..), Manager)-#else-import Network.HTTP.Client (HttpException(..), Manager)-#endif-import Text.Trifecta (Result(..))-import Text.Trifecta.Delta (Delta(..))--import qualified Control.Monad.Trans.State.Strict as State-import qualified Crypto.Hash-import qualified Data.ByteArray-import qualified Data.ByteString-import qualified Data.ByteString.Char8-import qualified Data.ByteString.Lazy-import qualified Data.CaseInsensitive-import qualified Data.Foldable-import qualified Data.List                        as List-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.Map.Strict                  as Map-import qualified Data.Text.Encoding-import qualified Data.Text.IO-import qualified Data.Text.Lazy                   as Text-import qualified Data.Text.Lazy.Builder           as Builder-import qualified Data.Text.Lazy.Encoding-import qualified Data.Text.Lazy.IO-import qualified Dhall.Core-import qualified Dhall.Parser-import qualified Dhall.Context-import qualified Dhall.TypeCheck-import qualified Network.HTTP.Client              as HTTP-import qualified Network.HTTP.Client.TLS          as HTTP-import qualified System.Environment-import qualified System.Directory-import qualified System.FilePath                  as FilePath-import qualified Text.Parser.Combinators-import qualified Text.Parser.Token-import qualified Text.Trifecta--builderToString :: Builder -> String-builderToString = Text.unpack . Builder.toLazyText---- | An import failed because of a cycle in the import graph-newtype Cycle = Cycle-    { cyclicImport :: Path  -- ^ The offending cyclic import-    }-  deriving (Typeable)--instance Exception Cycle--instance Show Cycle where-    show (Cycle path) = "\nCyclic import: " ++ builderToString (build path)--{-| Dhall tries to ensure that all expressions hosted on network endpoints are-    weakly referentially transparent, meaning roughly that any two clients will-    compile the exact same result given the same URL.--    To be precise, a strong interpretaton of referential transparency means that-    if you compiled a URL you could replace the expression hosted at that URL-    with the compiled result.  Let's call this \"static linking\".  Dhall (very-    intentionally) does not satisfy this stronger interpretation of referential-    transparency since \"statically linking\" an expression (i.e. permanently-    resolving all imports) means that the expression will no longer update if-    its dependencies change.--    In general, either interpretation of referential transparency is not-    enforceable in a networked context since one can easily violate referential-    transparency with a custom DNS, but Dhall can still try to guard against-    common unintentional violations.  To do this, Dhall enforces that a-    non-local import may not reference a local import.--    Local imports are defined as:--    * A file--    * A URL with a host of @localhost@ or @127.0.0.1@--    All other imports are defined to be non-local--}-newtype ReferentiallyOpaque = ReferentiallyOpaque-    { opaqueImport :: Path  -- ^ The offending opaque import-    } deriving (Typeable)--instance Exception ReferentiallyOpaque--instance Show ReferentiallyOpaque where-    show (ReferentiallyOpaque path) =-        "\nReferentially opaque import: " ++ builderToString (build path)---- | Extend another exception with the current import stack-data Imported e = Imported-    { importStack :: [Path] -- ^ Imports resolved so far, in reverse order-    , nested      :: e      -- ^ The nested exception-    } deriving (Typeable)--instance Exception e => Exception (Imported e)--instance Show e => Show (Imported e) where-    show (Imported paths e) =-            (case paths of [] -> ""; _ -> "\n")-        ++  unlines (map indent paths')-        ++  show e-      where-        indent (n, path) =-            take (2 * n) (repeat ' ') ++ "↳ " ++ builderToString (build path)-        -- Canonicalize all paths-        paths' = zip [0..] (drop 1 (reverse (canonicalizeAll paths)))---- | Newtype used to wrap `HttpException`s with a prettier `Show` instance-newtype PrettyHttpException = PrettyHttpException HttpException-    deriving (Typeable)--instance Exception PrettyHttpException--#if MIN_VERSION_http_client(0,5,0)-instance Show PrettyHttpException where-  show (PrettyHttpException (InvalidUrlException _ r)) =-    "\n"-    <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"-    <>  "\n"-    <>  "↳ " <> show r-  show (PrettyHttpException (HttpExceptionRequest _ e)) = case e of-    ConnectionFailure e' ->-      "\n"-      <>  "\ESC[1;31mError\ESC[0m: Wrong host\n"-      <>  "\n"-      <>  "↳ " <> show e'-    InvalidDestinationHost host ->-      "\n"-      <>  "\ESC[1;31mError\ESC[0m: Invalid host name\n"-      <>  "\n"-      <>  "↳ " <> show host-    ResponseTimeout ->-      "\ESC[1;31mError\ESC[0m: The host took too long to respond\n"-    e' -> "\n" <> show e'-#else-instance Show PrettyHttpException where-    show (PrettyHttpException e) = case e of-        FailedConnectionException2 _ _ _ e' ->-                "\n"-            <>  "\ESC[1;31mError\ESC[0m: Wrong host\n"-            <>  "\n"-            <>  "↳ " <> show e'-        InvalidDestinationHost host ->-                "\n"-            <>  "\ESC[1;31mError\ESC[0m: Invalid host name\n"-            <>  "\n"-            <>  "↳ " <> show host-        ResponseTimeout ->-                "\ESC[1;31mError\ESC[0m: The host took too long to respond\n"-        e' ->   "\n"-            <> show e'-#endif---- | Exception thrown when an imported file is missing-data MissingFile = MissingFile FilePath-    deriving (Typeable)--instance Exception MissingFile--instance Show MissingFile where-    show (MissingFile path) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Missing file "-        <>  path-        <>  "\n"---- | Exception thrown when an environment variable is missing-newtype MissingEnvironmentVariable = MissingEnvironmentVariable { name :: Text }-    deriving (Typeable)--instance Exception MissingEnvironmentVariable--instance Show MissingEnvironmentVariable where-    show (MissingEnvironmentVariable {..}) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Missing environment variable\n"-        <>  "\n"-        <>  "↳ " <> Text.unpack name---- | State threaded throughout the import process-data Status = Status-    { _stack   :: [Path]-    -- ^ Stack of `Path`s that we've imported along the way to get to the-    -- current point-    , _cache   :: Map Path (Expr Src X)-    -- ^ Cache of imported expressions in order to avoid importing the same-    --   expression twice with different values-    , _manager :: Maybe Manager-    -- ^ Cache for the `Manager` so that we only acquire it once-    }---- | Default starting `Status`-emptyStatus :: Status-emptyStatus = Status [] Map.empty Nothing--canonicalizeAll :: [Path] -> [Path]-canonicalizeAll = map canonicalizePath . List.tails--stack :: Functor f => LensLike' f Status [Path]-stack k s = fmap (\x -> s { _stack = x }) (k (_stack s))--cache :: Functor f => LensLike' f Status (Map Path (Expr Src X))-cache k s = fmap (\x -> s { _cache = x }) (k (_cache s))--manager :: Functor f => LensLike' f Status (Maybe Manager)-manager k s = fmap (\x -> s { _manager = x }) (k (_manager s))--needManager :: StateT Status IO Manager-needManager = do-    x <- zoom manager State.get-    case x of-        Just m  -> return m-        Nothing -> do-            let settings = HTTP.tlsManagerSettings-#if MIN_VERSION_http_client(0,5,0)-                    { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (30 * 1000 * 1000) }  -- 30 seconds-#else-                    { HTTP.managerResponseTimeout = Just (30 * 1000 * 1000) }  -- 30 seconds-#endif-            m <- liftIO (HTTP.newManager settings)-            zoom manager (State.put (Just m))-            return m--{-| This function computes the current path by taking the last absolute path-    (either an absolute `FilePath` or `URL`) and combining it with all following-    relative paths--    For example, if the file `./foo/bar` imports `./baz`, that will resolve to-    `./foo/baz`.  Relative imports are relative to a file's parent directory.-    This also works for URLs, too.--    This code is full of all sorts of edge cases so it wouldn't surprise me at-    all if you find something broken in here.  Most of the ugliness is due to:--    * Handling paths ending with @/\@@ by stripping the @/\@@ suffix if and only-      if you navigate to any downstream relative paths-    * Removing spurious @.@s and @..@s from the path--    Also, there are way too many `reverse`s in the URL-handling code For now I-    don't mind, but if were to really do this correctly we'd store the URLs as-    `Text` for O(1) access to the end of the string.  The only reason we use-    `String` at all is for consistency with the @http-client@ library.--}-canonicalize :: [PathType] -> PathType-canonicalize  []                          = File Homeless "."-canonicalize (File hasHome0 file0:paths0) =-    if FilePath.isRelative file0 && hasHome0 == Homeless-    then go file0 paths0-    else File hasHome0 (FilePath.normalise file0)-  where-    go currPath  []                       = File Homeless (FilePath.normalise currPath)-    go currPath (Env  _           :_    ) = File Homeless (FilePath.normalise currPath)-    go currPath (URL  url0 headers:rest ) = combine prefix suffix-      where-        headers' = fmap (onPathType (\h -> canonicalize (h:rest))) headers--        prefix = parentURL (removeAtFromURL url0)--        suffix = FilePath.normalise currPath--        -- `clean` will resolve internal @.@/@..@'s in @currPath@, but we still-        -- need to manually handle @.@/@..@'s at the beginning of the path-        combine url path = case List.stripPrefix "../" path of-            Just path' -> combine url' path'-              where-                url' = parentURL (removeAtFromURL url)-            Nothing    -> case List.stripPrefix "./" path of-                Just path' -> combine url path'-                Nothing    ->-                    -- This `last` is safe because the lexer constrains all-                    -- URLs to be non-empty.  I couldn't find a simple and safe-                    -- equivalent in the `text` API-                    case Text.last url of-                        '/' -> URL (url <>        path') headers'-                        _   -> URL (url <> "/" <> path') headers'-                  where-                    path' = Text.pack path-    go currPath (File hasHome file:paths) =-        if FilePath.isRelative file && hasHome == Homeless-        then go file' paths-        else File hasHome (FilePath.normalise file')-      where-        file' = FilePath.takeDirectory (removeAtFromFilename file) </> currPath-canonicalize (URL path headers:rest) = URL path headers'-  where-    headers' = fmap (onPathType (\h -> canonicalize (h:rest))) headers-canonicalize (Env env         :_   ) = Env env--onPathType :: (PathType -> PathType) -> PathHashed -> PathHashed-onPathType f (PathHashed a b) = PathHashed a (f b)--canonicalizePath :: [Path] -> Path-canonicalizePath [] =-    Path-        { pathMode   = Code-        , pathHashed = PathHashed-            { hash = Nothing-            , pathType = canonicalize []-            }-        }-canonicalizePath (path:paths) =-    Path-        { pathMode   = pathMode path-        , pathHashed = (pathHashed path)-             { hash     = hash (pathHashed path)-             , pathType =-                 canonicalize (map (pathType . pathHashed) (path:paths))-             }-        }--parentURL :: Text -> Text-parentURL = Text.dropWhileEnd (/= '/')--removeAtFromURL:: Text -> Text-removeAtFromURL url-    | Text.isSuffixOf "/@" url = Text.dropEnd 2 url-    | Text.isSuffixOf "/"  url = Text.dropEnd 1 url-    | otherwise                =                url--removeAtFromFilename :: FilePath -> FilePath-removeAtFromFilename fp =-    if FilePath.takeFileName fp == "@"-    then FilePath.takeDirectory fp-    else fp--toHeaders-  :: Expr s a-  -> Maybe [(CI Data.ByteString.ByteString, Data.ByteString.ByteString)]-toHeaders (ListLit _ hs) = do-    hs' <- mapM toHeader hs-    return (Data.Foldable.toList hs')-toHeaders  _             = do-    empty--toHeader-  :: Expr s a-  -> Maybe (CI Data.ByteString.ByteString, Data.ByteString.ByteString)-toHeader (RecordLit m) = do-    TextLit (Chunks [] keyBuilder  ) <- Data.HashMap.Strict.InsOrd.lookup "header" m-    TextLit (Chunks [] valueBuilder) <- Data.HashMap.Strict.InsOrd.lookup "value"  m-    let keyText   = Text.toStrict (Builder.toLazyText keyBuilder  )-    let valueText = Text.toStrict (Builder.toLazyText valueBuilder)-    let keyBytes   = Data.Text.Encoding.encodeUtf8 keyText-    let valueBytes = Data.Text.Encoding.encodeUtf8 valueText-    return (Data.CaseInsensitive.mk keyBytes, valueBytes)-toHeader _ = do-    empty---{-| This exception indicates that there was an internal error in Dhall's-    import-related logic-    the `expected` type then the `extract` function must succeed.  If not, then-    this exception is thrown--    This exception indicates that an invalid `Type` was provided to the `input`-    function--}-data InternalError = InternalError deriving (Typeable)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance Show InternalError where-    show InternalError = unlines-        [ _ERROR <> ": Compiler bug                                                        "-        , "                                                                                "-        , "Explanation: This error message means that there is a bug in the Dhall compiler."-        , "You didn't do anything wrong, but if you would like to see this problem fixed   "-        , "then you should report the bug at:                                              "-        , "                                                                                "-        , "https://github.com/dhall-lang/dhall-haskell/issues                              "-        , "                                                                                "-        , "Please include the following text in your bug report:                           "-        , "                                                                                "-        , "```                                                                             "-        , "Header extraction failed even though the header type-checked                    "-        , "```                                                                             "-        ]--instance Exception InternalError---- | Exception thrown when an integrity check fails-data HashMismatch = HashMismatch-    { expectedHash :: Crypto.Hash.Digest SHA256-    , actualHash   :: Crypto.Hash.Digest SHA256-    } deriving (Typeable)--instance Exception HashMismatch--instance Show HashMismatch where-    show (HashMismatch {..}) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Import integrity check failed\n"-        <>  "\n"-        <>  "Expected hash:\n"-        <>  "\n"-        <>  "↳ " <> show expectedHash <> "\n"-        <>  "\n"-        <>  "Actual hash:\n"-        <>  "\n"-        <>  "↳ " <> show actualHash <> "\n"--parseFromFileEx-    :: Text.Trifecta.Parser a-    -> FilePath-    -> IO (Text.Trifecta.Result a)-parseFromFileEx parser path = do-    text <- Data.Text.Lazy.IO.readFile path--    let lazyBytes = Data.Text.Lazy.Encoding.encodeUtf8 text--    let strictBytes = Data.ByteString.Lazy.toStrict lazyBytes--    let delta = Directed bytesPath 0 0 0 0--    return (Text.Trifecta.parseByteString parser delta strictBytes)-  where-    bytesPath = Data.ByteString.Char8.pack path---- | Parse an expression from a `Path` containing a Dhall program-exprFromPath :: Path -> StateT Status IO (Expr Src Path)-exprFromPath (Path {..}) = case pathType of-    File hasHome file -> liftIO (do-        path <- case hasHome of-            Home -> do-                home <- System.Directory.getHomeDirectory-                return (home </> file)-            Homeless -> do-                return file--        case pathMode of-            Code -> do-                exists <- System.Directory.doesFileExist path-                if exists-                    then return ()-                    else throwIO (MissingFile path)--                -- Unfortunately, GHC throws an `InappropriateType` exception-                -- when trying to read a directory, but does not export the-                -- exception, so I must resort to a more heavy-handed `catch`-                let handler :: IOException -> IO (Result (Expr Src Path))-                    handler e = do-                        -- If the fallback fails, reuse the original exception-                        -- to avoid user confusion-                        parseFromFileEx parser (path </> "@")-                            `onException` throwIO e--                x <- parseFromFileEx parser path `catch` handler-                case x of-                    Failure errInfo -> do-                        throwIO (ParseError (Text.Trifecta._errDoc errInfo))-                    Success expr -> do-                        return expr-            RawText -> do-                text <- Data.Text.IO.readFile path-                return (TextLit (Chunks [] (build text))) )-    URL url headerPath -> do-        m       <- needManager-        request <- liftIO (HTTP.parseUrlThrow (Text.unpack url))--        let handler :: HTTP.HttpException -> IO (HTTP.Response ByteString)-#if MIN_VERSION_http_client(0,5,0)-            handler err@(HttpExceptionRequest _ (StatusCodeException _ _)) = do-#else-            handler err@(StatusCodeException _ _ _) = do-#endif-                let request' = request { HTTP.path = HTTP.path request <> "/@" }-                -- If the fallback fails, reuse the original exception to avoid-                -- user confusion-                HTTP.httpLbs request' m `onException` throwIO (PrettyHttpException err)-            handler err = throwIO (PrettyHttpException err)--        requestWithHeaders <- case headerPath of-            Nothing   -> return request-            Just path -> do-                expr <- loadStaticIO Dhall.Context.empty (Path path Code)-                let expected :: Expr Src X-                    expected =-                        App List-                            ( Record-                                ( Data.HashMap.Strict.InsOrd.fromList-                                    [("header", Text), ("value", Text)]-                                )-                            )-                let suffix =-                        ( Data.ByteString.Lazy.toStrict-                        . Data.Text.Lazy.Encoding.encodeUtf8-                        . Builder.toLazyText-                        . build-                        ) expected-                let annot = case expr of-                        Note (Src begin end bytes) _ ->-                            Note (Src begin end bytes') (Annot expr expected)-                          where-                            bytes' = bytes <> " : " <> suffix-                        _ ->-                            Annot expr expected-                case Dhall.TypeCheck.typeOf annot of-                    Left err -> liftIO (throwIO err)-                    Right _  -> return ()-                let expr' = Dhall.Core.normalize expr-                headers <- case toHeaders expr' of-                    Just headers -> do-                        return headers-                    Nothing      -> do-                        liftIO (throwIO InternalError)-                let requestWithHeaders = request-                        { HTTP.requestHeaders = headers-                        }-                return requestWithHeaders-        response <- liftIO (HTTP.httpLbs requestWithHeaders m `catch` handler)--        let bytes = HTTP.responseBody response--        text <- case Data.Text.Lazy.Encoding.decodeUtf8' bytes of-            Left  err  -> liftIO (throwIO err)-            Right text -> return text--        case pathMode of-            Code -> do-                let urlBytes = Data.Text.Lazy.Encoding.encodeUtf8 url-                let delta =-                        Directed (Data.ByteString.Lazy.toStrict urlBytes) 0 0 0 0-                case Text.Trifecta.parseString parser delta (Text.unpack text) of-                    Failure err -> do-                        -- Also try the fallback in case of a parse error, since-                        -- the parse error might signify that this URL points to-                        -- a directory list-                        let err' = ParseError (Text.Trifecta._errDoc err)--                        request' <- liftIO (HTTP.parseUrlThrow (Text.unpack url))--                        let request'' =-                                request'-                                    { HTTP.path = HTTP.path request' <> "/@" }-                        response' <- liftIO (HTTP.httpLbs request'' m `onException` throwIO err' )--                        let bytes' = HTTP.responseBody response'--                        text' <- case Data.Text.Lazy.Encoding.decodeUtf8' bytes' of-                            Left  _     -> liftIO (throwIO err')-                            Right text' -> return text'--                        case Text.Trifecta.parseString parser delta (Text.unpack text') of-                            Failure _    -> liftIO (throwIO err')-                            Success expr -> return expr-                    Success expr -> return expr-            RawText -> do-                return (TextLit (Chunks [] (build text)))-    Env env -> liftIO (do-        x <- System.Environment.lookupEnv (Text.unpack env)-        case x of-            Just str -> do-                case pathMode of-                    Code -> do-                        let envBytes = Data.Text.Lazy.Encoding.encodeUtf8 env-                        let delta =-                                Directed (Data.ByteString.Lazy.toStrict envBytes) 0 0 0 0-                        case Text.Trifecta.parseString parser delta str of-                            Failure errInfo -> do-                                throwIO (ParseError (Text.Trifecta._errDoc errInfo))-                            Success expr    -> do-                                return expr-                    RawText -> return (TextLit (Chunks [] (build str)))-            Nothing  -> throwIO (MissingEnvironmentVariable env) )-  where-    PathHashed {..} = pathHashed--    parser = unParser (do-        Text.Parser.Token.whiteSpace-        r <- Dhall.Parser.expr-        Text.Parser.Combinators.eof-        return r )--{-| Load a `Path` as a \"dynamic\" expression (without resolving any imports)--    This also returns the true final path (i.e. explicit "/@" at the end for-    directories)--}-loadDynamic-    :: forall m . MonadCatch m-    => (Path -> StateT Status m (Expr Src Path))-    -> Path-    -> StateT Status m (Expr Src Path)-loadDynamic from_path p = do-    paths <- zoom stack State.get--    let handler :: SomeException -> StateT Status m (Expr Src Path)-        handler e = throwM (Imported (p:paths) e)--    from_path (canonicalizePath (p:paths)) `catch` handler--loadStaticIO-    :: Dhall.Context.Context (Expr Src X)-    -> Path-    -> StateT Status IO (Expr Src X)-loadStaticIO = loadStaticWith exprFromPath---- | Resolve all imports within an expression using a custom typing context and Path--- resolving callback in arbitrary `MonadCatch` monad.-loadWith-    :: MonadCatch m-    => (Path -> StateT Status m (Expr Src Path))-    -> Dhall.Context.Context (Expr Src X)-    -> Expr Src Path-    -> m (Expr Src X)-loadWith from_path ctx = evalStatus (loadStaticWith from_path ctx)---- | Resolve all imports within an expression using a custom typing context.------ @load = loadWithContext Dhall.Context.empty@-loadWithContext-    :: Dhall.Context.Context (Expr Src X)-    -> Expr Src Path-    -> IO (Expr Src X)-loadWithContext ctx = evalStatus (loadStaticIO ctx)--loadStaticWith-    :: MonadCatch m-    => (Path -> StateT Status m (Expr Src Path))-    -> Dhall.Context.Context (Expr Src X)-    -> Path-    -> StateT Status m (Expr Src X)-loadStaticWith from_path ctx path = do-    paths <- zoom stack State.get--    let local (Path (PathHashed _ (URL _ _ )) _) = False-        local (Path (PathHashed _ (File _ _)) _) = True-        local (Path (PathHashed _ (Env  _  )) _) = True--    let parent = canonicalizePath paths-    let here   = canonicalizePath (path:paths)--    if local here && not (local parent)-        then throwM (Imported paths (ReferentiallyOpaque path))-        else return ()--    (expr, cached) <- if here `elem` canonicalizeAll paths-        then throwM (Imported paths (Cycle path))-        else do-            m <- zoom cache State.get-            case Map.lookup here m of-                Just expr -> return (expr, True)-                Nothing   -> do-                    expr'  <- loadDynamic from_path path-                    expr'' <- case traverse (\_ -> Nothing) expr' of-                        -- No imports left-                        Just expr -> do-                            zoom cache (State.put $! Map.insert here expr m)-                            return expr-                        -- Some imports left, so recurse-                        Nothing   -> do-                            let paths' = path:paths-                            zoom stack (State.put paths')-                            expr'' <- fmap join (traverse (loadStaticWith from_path ctx)-                                                           expr')-                            zoom stack (State.put paths)-                            return expr''-                    return (expr'', False)--    -- Type-check expressions here for three separate reasons:-    ---    --  * to verify that they are closed-    --  * to catch type errors as early in the import process as possible-    --  * to avoid normalizing ill-typed expressions that need to be hashed-    ---    -- There is no need to check expressions that have been cached, since they-    -- have already been checked-    if cached-        then return ()-        else case Dhall.TypeCheck.typeWith ctx expr of-            Left  err -> throwM (Imported (path:paths) err)-            Right _   -> return ()--    case hash (pathHashed path) of-        Nothing -> do-            return ()-        Just expectedHash -> do-            let actualHash = hashExpression expr-            if expectedHash == actualHash-                then return ()-                else throwM (HashMismatch {..})--    return expr--evalStatus-    :: (Traversable f, Monad m, Monad f)-    => (a -> StateT Status m (f b)) -> f a -> m (f b)-evalStatus cb expr = State.evalStateT (fmap join (traverse cb expr)) emptyStatus---- | Resolve all imports within an expression-load :: Expr Src Path -> IO (Expr Src X)-load = loadWithContext Dhall.Context.empty---- | Hash a fully resolved expression-hashExpression :: Expr s X -> (Crypto.Hash.Digest SHA256)-hashExpression expr = Crypto.Hash.hashlazy actualBytes-  where-    text = Dhall.Core.pretty (Dhall.Core.normalize expr)-    actualBytes = Data.Text.Lazy.Encoding.encodeUtf8 text--{-| Convenience utility to hash a fully resolved expression and return the-    base-16 encoded hash with the @sha256:@ prefix--    In other words, the output of this function can be pasted into Dhall-    source code to add an integrity check to an import--}-hashExpressionToCode :: Expr s X -> Text-hashExpressionToCode expr = "sha256:" <> lazyText-  where-    bytes = hashExpression expr--    bytes16 = Data.ByteArray.convert bytes--    -- Notes that `decodeUtf8` is partial, but the base16-encoded bytestring-    -- should always successfully decode-    text = Data.Text.Encoding.decodeUtf8 bytes16--    lazyText = Text.fromStrict text+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DeriveAnyClass      #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE NamedFieldPuns      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}++{-# OPTIONS_GHC -Wall #-}++{-| Dhall lets you import external expressions located either in local files or+    hosted on network endpoints.++    To import a local file as an expression, just insert the path to the file,+    prepending a @./@ if the path is relative to the current directory.  For+    example, if you create a file named @id@ with the following contents:++    > $ cat id+    > λ(a : Type) → λ(x : a) → x++    Then you can use the file directly within a @dhall@ program just by+    referencing the file's path:++    > $ dhall+    > ./id Bool True+    > <Ctrl-D>+    > Bool+    >+    > True++    Imported expressions may contain imports of their own, too, which will+    continue to be resolved.  However, Dhall will prevent cyclic imports.  For+    example, if you had these two files:++    > $ cat foo+    > ./bar++    > $ cat bar+    > ./foo++    ... Dhall would throw the following exception if you tried to import @foo@:++    > $ dhall+    > ./foo+    > ^D+    > ↳ ./foo+    >   ↳ ./bar+    >+    > Cyclic import: ./foo++    You can also import expressions hosted on network endpoints.  Just use the+    URL++    > http://host[:port]/path++    The compiler expects the downloaded expressions to be in the same format+    as local files, specifically UTF8-encoded source code text.++    For example, if our @id@ expression were hosted at @http://example.com/id@,+    then we would embed the expression within our code using:++    > http://example.com/id++    You can also import expressions stored within environment variables using+    @env:NAME@, where @NAME@ is the name of the environment variable.  For+    example:++    > $ export FOO=1+    > $ export BAR='"Hi"'+    > $ export BAZ='λ(x : Bool) → x == False'+    > $ dhall <<< "{ foo = env:FOO , bar = env:BAR , baz = env:BAZ }"+    > { bar : Text, baz : ∀(x : Bool) → Bool, foo : Integer }+    >+    > { bar = "Hi", baz = λ(x : Bool) → x == False, foo = 1 }++    If you wish to import the raw contents of an impoert as @Text@ then add+    @as Text@ to the end of the import:++    > $ dhall <<< "http://example.com as Text"+    > Text+    >+    > "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta+    >  charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html+    > ; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,+    > initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro+    > und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil+    > y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n+    >    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi+    > ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n+    >     a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;+    > \n    }\n    @media (max-width: 700px) {\n        body {\n            background+    > -color: #fff;\n        }\n        div {\n            width: auto;\n            m+    > argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n+    >   }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</+    > h1>\n    <p>This domain is established to be used for illustrative examples in d+    > ocuments. You may use this\n    domain in examples without prior coordination or+    >  asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl+    > e\">More information...</a></p>\n</div>\n</body>\n</html>\n"+-}++module Dhall.Import (+    -- * Import+      load+    , loadWithManager+    , loadRelativeTo+    , loadWithStatus+    , loadWith+    , localToPath+    , hashExpression+    , hashExpressionToCode+    , writeExpressionToSemanticCache+    , assertNoImports+    , Manager+    , defaultNewManager+    , CacheWarning(..)+    , Status(..)+    , SemanticCacheMode(..)+    , Chained+    , chainedImport+    , chainedFromLocalHere+    , chainedChangeMode+    , emptyStatus+    , emptyStatusWithManager+    , envOriginHeaders+    , makeEmptyStatus+    , remoteStatus+    , remoteStatusWithManager+    , fetchRemote+    , stack+    , cache+    , Depends(..)+    , graph+    , remote+    , toHeaders+    , substitutions+    , normalizer+    , startingContext+    , chainImport+    , dependencyToFile+    , ImportSemantics+    , HTTPHeader+    , Cycle(..)+    , ReferentiallyOpaque(..)+    , Imported(..)+    , ImportResolutionDisabled(..)+    , PrettyHttpException(..)+    , MissingFile(..)+    , MissingEnvironmentVariable(..)+    , MissingImports(..)+    , HashMismatch(..)+    ) where++import Control.Applicative        (Alternative (..))+import Control.Exception+    ( Exception+    , IOException+    , SomeException+    , toException+    )+import Control.Monad.Catch        (MonadCatch (catch), handle, throwM)+import Control.Monad.IO.Class     (MonadIO (..))+import Control.Monad.Morph        (hoist)+import Control.Monad.State.Strict (MonadState, StateT)+import Data.ByteString            (ByteString)+import Data.List.NonEmpty         (NonEmpty (..), nonEmpty)+import Data.Maybe                 (fromMaybe)+import Data.Text                  (Text)+import Data.Typeable              (Typeable)+import Data.Void                  (Void, absurd)+import Dhall.TypeCheck            (TypeError)+import Dhall.Util                 (printWarning)++import Dhall.Syntax+    ( Chunks (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , URL (..)+    , bindingExprs+    , functionBindingExprs+    , recordFieldExprs+    )++import System.FilePath ((</>))+import Text.Megaparsec (SourcePos (SourcePos), mkPos)++#ifdef WITH_HTTP+import Dhall.Import.HTTP+#endif+import Dhall.Import.Headers+    ( normalizeHeaders+    , originHeadersTypeExpr+    , toHeaders+    , toOriginHeaders+    )+import Dhall.Import.Types++import Dhall.Parser+    ( ParseError (..)+    , Parser (..)+    , SourcedException (..)+    , Src (..)+    )+import Lens.Micro.Mtl (zoom)++import qualified Codec.CBOR.Write                            as Write+import qualified Codec.Serialise+import qualified Control.Exception                           as Exception+import qualified Control.Monad.State.Strict                  as State+import qualified Control.Monad.Trans.Maybe                   as Maybe+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.List.NonEmpty                          as NonEmpty+import qualified Data.Maybe                                  as Maybe+import qualified Data.Text                                   as Text+import qualified Data.Text.Encoding                          as Encoding+import qualified Data.Text.IO+import qualified Dhall.Binary+import qualified Dhall.Core                                  as Core+import qualified Dhall.Crypto+import qualified Dhall.Map+import qualified Dhall.Parser+import qualified Dhall.Pretty.Internal+import qualified Dhall.Substitution+import qualified Dhall.Syntax                                as Syntax+import qualified Dhall.TypeCheck+import qualified System.AtomicWrite.Writer.ByteString.Binary as AtomicWrite.Binary+import qualified System.Directory                            as Directory+import qualified System.Environment+import qualified System.FilePath                             as FilePath+import qualified System.Info+import qualified System.IO+import qualified Text.Megaparsec+import qualified Text.Parser.Combinators+import qualified Text.Parser.Token++{- $setup++    >>> import Dhall.Syntax+-}++-- | An import failed because of a cycle in the import graph+newtype Cycle = Cycle+    { cyclicImport :: Import  -- ^ The offending cyclic import+    }+  deriving (Typeable)++instance Exception Cycle++instance Show Cycle where+    show (Cycle import_) =+        "\nCyclic import: " ++ Dhall.Pretty.Internal.prettyToString import_++{-| Dhall tries to ensure that all expressions hosted on network endpoints are+    weakly referentially transparent, meaning roughly that any two clients will+    compile the exact same result given the same URL.++    To be precise, a strong interpretaton of referential transparency means that+    if you compiled a URL you could replace the expression hosted at that URL+    with the compiled result.  Let's call this \"static linking\".  Dhall (very+    intentionally) does not satisfy this stronger interpretation of referential+    transparency since \"statically linking\" an expression (i.e. permanently+    resolving all imports) means that the expression will no longer update if+    its dependencies change.++    In general, either interpretation of referential transparency is not+    enforceable in a networked context since one can easily violate referential+    transparency with a custom DNS, but Dhall can still try to guard against+    common unintentional violations.  To do this, Dhall enforces that a+    non-local import may not reference a local import.++    Local imports are defined as:++    * A file++    * A URL with a host of @localhost@ or @127.0.0.1@++    All other imports are defined to be non-local+-}+newtype ReferentiallyOpaque = ReferentiallyOpaque+    { opaqueImport :: Import  -- ^ The offending opaque import+    } deriving (Typeable)++instance Exception ReferentiallyOpaque++instance Show ReferentiallyOpaque where+    show (ReferentiallyOpaque import_) =+        "\nLocal imports are not permitted from remote imports: " ++ Dhall.Pretty.Internal.prettyToString import_++-- | Extend another exception with the current import stack+data Imported e = Imported+    { importStack :: NonEmpty Chained  -- ^ Imports resolved so far, in reverse order+    , nested      :: e                 -- ^ The nested exception+    } deriving (Typeable)++instance Exception e => Exception (Imported e)++instance Show e => Show (Imported e) where+    show (Imported canonicalizedImports e) =+           concat (zipWith indent [0..] toDisplay)+        ++ "\n"+        ++ show e+      where+        indent n import_ =+            "\n" ++ replicate (2 * n) ' ' ++ "↳ " ++ Dhall.Pretty.Internal.prettyToString import_++        canonical = NonEmpty.toList canonicalizedImports++        -- Tthe final (outermost) import is fake to establish the base+        -- directory. Also, we need outermost-first.+        toDisplay = drop 1 (reverse canonical)++-- | Exception thrown when an imported file is missing+newtype MissingFile = MissingFile FilePath+    deriving (Typeable)++instance Exception MissingFile++instance Show MissingFile where+    show (MissingFile path) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Missing file "+        <>  path++-- | Exception thrown when an environment variable is missing+newtype MissingEnvironmentVariable = MissingEnvironmentVariable { name :: Text }+    deriving (Typeable)++instance Exception MissingEnvironmentVariable++instance Show MissingEnvironmentVariable where+    show MissingEnvironmentVariable{..} =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Missing environment variable\n"+        <>  "\n"+        <>  "↳ " <> Text.unpack name++-- | List of Exceptions we encounter while resolving Import Alternatives+newtype MissingImports = MissingImports [SomeException]++instance Exception MissingImports++instance Show MissingImports where+    show (MissingImports []) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: No valid imports"+    show (MissingImports [e]) = show e+    show (MissingImports es) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Failed to resolve imports. Error list:"+        <>  "\n"+        <>  concatMap (\e -> "\n" <> show e <> "\n") es++throwMissingImport :: (MonadCatch m, Exception e) => e -> m a+throwMissingImport e = throwM (MissingImports [toException e])++-- | Exception thrown when a HTTP url is imported but dhall was built without+-- the @with-http@ Cabal flag.+data CannotImportHTTPURL =+    CannotImportHTTPURL+        String+        (Maybe [HTTPHeader])+    deriving (Typeable)++instance Exception CannotImportHTTPURL++instance Show CannotImportHTTPURL where+    show (CannotImportHTTPURL url _mheaders) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Cannot import HTTP URL.\n"+        <>  "\n"+        <>  "Dhall was compiled without the 'with-http' flag.\n"+        <>  "\n"+        <>  "The requested URL was: "+        <>  url+        <>  "\n"++{-|+> canonicalize . canonicalize = canonicalize++> canonicalize (a <> b) = canonicalize (canonicalize a <> canonicalize b)+-}+class Semigroup path => Canonicalize path where+    canonicalize :: path -> path++-- |+-- >>> canonicalize (Directory {components = ["..",".."]})+-- Directory {components = ["..",".."]}+instance Canonicalize Directory where+    canonicalize (Directory []) = Directory []++    canonicalize (Directory ("." : components₀)) =+        canonicalize (Directory components₀)++    canonicalize (Directory (".." : components₀)) =+        case canonicalize (Directory components₀) of+            Directory [] ->+                Directory [ ".." ]+            Directory (".." : components₁) ->+                Directory (".." : ".." : components₁)+            Directory (_    : components₁) ->+                Directory components₁++    canonicalize (Directory (component : components₀)) =+        Directory (component : components₁)+      where+        Directory components₁ = canonicalize (Directory components₀)++instance Canonicalize File where+    canonicalize (File { directory, .. }) =+        File { directory = canonicalize directory, .. }++instance Canonicalize ImportType where+    canonicalize (Local prefix file) =+        Local prefix (canonicalize file)++    canonicalize (Remote (URL {..})) =+        Remote (URL { path = canonicalize path, headers = fmap (fmap canonicalize) headers, ..})++    canonicalize (Env name) =+        Env name++    canonicalize Missing =+        Missing++instance Canonicalize ImportHashed where+    canonicalize (ImportHashed hash importType) =+        ImportHashed hash (canonicalize importType)++instance Canonicalize Import where+    canonicalize (Import importHashed importMode) =+        Import (canonicalize importHashed) importMode++-- | Exception thrown when an integrity check fails+data HashMismatch = HashMismatch+    { expectedHash :: Dhall.Crypto.SHA256Digest+    , actualHash   :: Dhall.Crypto.SHA256Digest+    } deriving (Typeable)++instance Exception HashMismatch++instance Show HashMismatch where+    show HashMismatch{..} =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: " <> makeHashMismatchMessage expectedHash actualHash++makeHashMismatchMessage :: Dhall.Crypto.SHA256Digest -> Dhall.Crypto.SHA256Digest -> String+makeHashMismatchMessage expectedHash actualHash =+    "Import integrity check failed\n"+        <>  "\n"+        <>  "Expected hash:\n"+        <>  "\n"+        <>  "↳ " <> show expectedHash <> "\n"+        <>  "\n"+        <>  "Actual hash:\n"+        <>  "\n"+        <>  "↳ " <> show actualHash <> "\n"++-- | Construct the file path corresponding to a local import. If the import is+--   _relative_ then the resulting path is also relative.+localToPath :: MonadIO io => FilePrefix -> File -> io FilePath+localToPath prefix file_ = liftIO $ do+    let File {..} = file_++    let Directory {..} = directory++    prefixPath <- case prefix of+        Home ->+            Directory.getHomeDirectory++        Absolute ->+            return "/"++        Parent ->+            return ".."++        Here ->+            return "."++    let cs = map Text.unpack (file : components)++    let cons component dir = dir </> component++    return (foldr cons prefixPath cs)++-- | Given a `Local` import construct the corresponding unhashed `Chained`+--   import (interpreting relative path as relative to the current directory).+chainedFromLocalHere :: FilePrefix -> File -> ImportMode -> Chained+chainedFromLocalHere prefix file mode = Chained $+     Import (ImportHashed Nothing (Local prefix (canonicalize file))) mode++-- | Adjust the import mode of a chained import+chainedChangeMode :: ImportMode -> Chained -> Chained+chainedChangeMode mode (Chained (Import importHashed _)) =+    Chained (Import importHashed mode)++-- | Chain imports, also typecheck and normalize headers if applicable.+chainImport :: Chained -> Import -> StateT Status IO Chained+chainImport (Chained parent) child@(Import importHashed@(ImportHashed _ (Remote url)) _) = do+    url' <- normalizeHeadersIn url+    let child' = child { importHashed = importHashed { importType = Remote url' } }+    return (Chained (canonicalize (parent <> child')))++chainImport (Chained parent) child =+    return (Chained (canonicalize (parent <> child)))++-- | Load an import, resulting in a fully resolved, type-checked and normalised+--   expression. @loadImport@ handles the \"hot\" cache in @Status@ and defers+--   to @loadImportWithSemanticCache@ for imports that aren't in the @Status@+--   cache already.+loadImport :: Chained -> StateT Status IO ImportSemantics+loadImport import_ = do+    Status {..} <- State.get++    case Dhall.Map.lookup import_ _cache of+        Just importSemantics -> return importSemantics+        Nothing -> do+            importSemantics <- loadImportWithSemanticCache import_+            zoom cache (State.modify (Dhall.Map.insert import_ importSemantics))+            return importSemantics++-- | Load an import from the 'semantic cache'. Defers to+--   @loadImportWithSemisemanticCache@ for imports that aren't frozen (and+--   therefore not cached semantically), as well as those that aren't cached yet.+loadImportWithSemanticCache :: Chained -> StateT Status IO ImportSemantics+loadImportWithSemanticCache+  import_@(Chained (Import (ImportHashed Nothing _) _)) =+    loadImportWithSemisemanticCache import_++loadImportWithSemanticCache+  import_@(Chained (Import _ Location)) =+    loadImportWithSemisemanticCache import_++loadImportWithSemanticCache+  import_@(Chained (Import (ImportHashed (Just semanticHash) _) _)) = do+    Status { .. } <- State.get+    mCached <-+        case _semanticCacheMode of+            UseSemanticCache ->+                zoom cacheWarning (fetchFromSemanticCache semanticHash)+            IgnoreSemanticCache ->+                pure Nothing++    case mCached of+        Just bytesStrict -> do+            let actualHash = Dhall.Crypto.sha256Hash bytesStrict++            if semanticHash == actualHash+                then do+                    let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict++                    importSemantics <- case Dhall.Binary.decodeExpression bytesLazy of+                        Left  err -> throwMissingImport (Imported _stack err)+                        Right e   -> return e++                    return (ImportSemantics {..})+                else do+                    printWarning $+                        makeHashMismatchMessage semanticHash actualHash+                        <> "\n"+                        <> "The interpreter will attempt to fix the cached import\n"+                    fetch+++        Nothing -> fetch+    where+        fetch = do+            ImportSemantics{ importSemantics } <- loadImportWithSemisemanticCache import_++            let bytes = encodeExpression (Core.alphaNormalize importSemantics)++            let actualHash = Dhall.Crypto.sha256Hash bytes++            let expectedHash = semanticHash++            if actualHash == expectedHash+                then do+                    zoom cacheWarning (writeToSemanticCache semanticHash bytes)++                else do+                    Status{ _stack } <- State.get++                    throwMissingImport (Imported _stack HashMismatch{..})++            return ImportSemantics{..}++++-- Fetch encoded normal form from "semantic cache"+fetchFromSemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> m (Maybe Data.ByteString.ByteString)+fetchFromSemanticCache expectedHash = Maybe.runMaybeT $ do+    cacheFile <- getCacheFile "dhall" expectedHash+    True <- liftIO (Directory.doesFileExist cacheFile)+    liftIO (Data.ByteString.readFile cacheFile)++-- | Ensure that the given expression is present in the semantic cache. The+--   given expression should be alpha-beta-normal.+writeExpressionToSemanticCache :: Expr Void Void -> IO ()+writeExpressionToSemanticCache expression =+    -- Defaulting to not displaying the warning is for backwards compatibility+    -- with the old behavior+    State.evalStateT (writeToSemanticCache hash bytes) CacheWarned+  where+    bytes = encodeExpression expression++    hash = Dhall.Crypto.sha256Hash bytes++writeToSemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> Data.ByteString.ByteString+    -> m ()+writeToSemanticCache hash bytes = do+    _ <- Maybe.runMaybeT $ do+        cacheFile <- getCacheFile "dhall" hash+        liftIO (AtomicWrite.Binary.atomicWriteFile cacheFile bytes)+    return ()++-- Check the "semi-semantic" disk cache, otherwise typecheck and normalise from+-- scratch.+loadImportWithSemisemanticCache+  :: Chained -> StateT Status IO ImportSemantics+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) Code)) = do+    text <- fetchFresh importType+    Status {..} <- State.get++    path <- case importType of+        Local prefix file -> liftIO $ do+            path <- localToPath prefix file+            absolutePath <- Directory.makeAbsolute path+            return absolutePath+        Remote url -> do+            let urlText = Core.pretty (url { headers = Nothing })+            return (Text.unpack urlText)+        Env env -> return $ Text.unpack env+        Missing -> throwM (MissingImports [])++    let parser = unParser $ do+            Text.Parser.Token.whiteSpace+            r <- Dhall.Parser.expr+            Text.Parser.Combinators.eof+            return r++    parsedImport <- case Text.Megaparsec.parse parser path text of+        Left  errInfo ->+            throwMissingImport (Imported _stack (ParseError errInfo text))+        Right expr    -> return expr++    resolvedExpr <- loadWith parsedImport  -- we load imports recursively here++    -- Check the semi-semantic cache. See+    -- https://github.com/dhall-lang/dhall-haskell/issues/1098 for the reasoning+    -- behind semi-semantic caching.+    let semisemanticHash = computeSemisemanticHash (Core.denote resolvedExpr)++    mCached <- zoom cacheWarning (fetchFromSemisemanticCache semisemanticHash)++    importSemantics <- case mCached of+        Just bytesStrict -> do+            let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict++            importSemantics <- case Dhall.Binary.decodeExpression bytesLazy of+                Left err  -> throwMissingImport (Imported _stack err)+                Right sem -> return sem++            return importSemantics++        Nothing -> do+            let substitutedExpr =+                  Dhall.Substitution.substitute resolvedExpr _substitutions++            case Core.shallowDenote parsedImport of+                -- If this import trivially wraps another import, we can skip+                -- the type-checking and normalization step as the transitive+                -- import was already type-checked and normalized+                Embed _ ->+                    return (Core.denote substitutedExpr)++                _ -> do+                    case Dhall.TypeCheck.typeWith _startingContext substitutedExpr of+                        Left  err -> throwMissingImport (Imported _stack err)+                        Right _   -> return ()++                    let betaNormal =+                            Core.normalizeWith _normalizer substitutedExpr++                    let bytes = encodeExpression betaNormal++                    zoom cacheWarning (writeToSemisemanticCache semisemanticHash bytes)++                    return betaNormal++    return (ImportSemantics {..})++-- `as Text` and `as Bytes` imports aren't cached since they are well-typed and+-- normal by construction+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawText)) = do+    text <- fetchFresh importType++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = TextLit (Chunks [] text)+    return (ImportSemantics {..})+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawBytes)) = do+    bytes <- fetchBytes importType++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = BytesLit bytes+    return (ImportSemantics {..})++-- `as Location` imports aren't cached since they are well-typed and normal by+-- construction+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) Location)) = do+    let locationType = Union $ Dhall.Map.fromList+            [ ("Environment", Just Text)+            , ("Remote", Just Text)+            , ("Local", Just Text)+            , ("Missing", Nothing)+            ]++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = case importType of+            Missing -> Field locationType $ Core.makeFieldSelection  "Missing"+            local@(Local _ _) ->+                App (Field locationType $ Core.makeFieldSelection "Local")+                  (TextLit (Chunks [] (Core.pretty local)))+            remote_@(Remote _) ->+                App (Field locationType $ Core.makeFieldSelection "Remote")+                  (TextLit (Chunks [] (Core.pretty remote_)))+            Env env ->+                App (Field locationType $ Core.makeFieldSelection "Environment")+                  (TextLit (Chunks [] (Core.pretty env)))++    return (ImportSemantics {..})++-- The semi-semantic hash of an expression is computed from the fully resolved+-- AST (without normalising or type-checking it first). See+-- https://github.com/dhall-lang/dhall-haskell/issues/1098 for further+-- discussion.+computeSemisemanticHash :: Expr Void Void -> Dhall.Crypto.SHA256Digest+computeSemisemanticHash resolvedExpr = hashExpression resolvedExpr++-- Fetch encoded normal form from "semi-semantic cache"+fetchFromSemisemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> m (Maybe Data.ByteString.ByteString)+fetchFromSemisemanticCache semisemanticHash = Maybe.runMaybeT $ do+    cacheFile <- getCacheFile "dhall-haskell" semisemanticHash+    True <- liftIO (Directory.doesFileExist cacheFile)+    liftIO (Data.ByteString.readFile cacheFile)++writeToSemisemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> Data.ByteString.ByteString+    -> m ()+writeToSemisemanticCache semisemanticHash bytes = do+    _ <- Maybe.runMaybeT $ do+        cacheFile <- getCacheFile "dhall-haskell" semisemanticHash+        liftIO (AtomicWrite.Binary.atomicWriteFile cacheFile bytes)+    return ()++-- | Fetch source code directly from disk/network+fetchFresh :: ImportType -> StateT Status IO Text+fetchFresh (Local prefix file) = do+    Status { _stack } <- State.get+    path <- liftIO $ localToPath prefix file+    exists <- liftIO $ Directory.doesFileExist path+    if exists+        then liftIO $ Data.Text.IO.readFile path+        else throwMissingImport (Imported _stack (MissingFile path))++fetchFresh (Remote url) = do+    Status { _remote } <- State.get+    _remote url++fetchFresh (Env env) = do+    Status { _stack } <- State.get+    x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)+    case x of+        Just string ->+            return (Text.pack string)+        Nothing ->+                throwMissingImport (Imported _stack (MissingEnvironmentVariable env))++fetchFresh Missing = throwM (MissingImports [])++-- | Like `fetchFresh`, except for `Dhall.Syntax.Expr.Bytes`+fetchBytes :: ImportType -> StateT Status IO ByteString+fetchBytes (Local prefix file) = do+    Status { _stack } <- State.get+    path <- liftIO $ localToPath prefix file+    exists <- liftIO $ Directory.doesFileExist path+    if exists+        then liftIO $ Data.ByteString.readFile path+        else throwMissingImport (Imported _stack (MissingFile path))++fetchBytes (Remote url) = do+    Status { _remoteBytes } <- State.get+    _remoteBytes url++fetchBytes (Env env) = do+    Status { _stack } <- State.get+    x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)+    case x of+        Just string ->+            return (Encoding.encodeUtf8 (Text.pack string))+        Nothing ->+            throwMissingImport (Imported _stack (MissingEnvironmentVariable env))+fetchBytes Missing = throwM (MissingImports [])++-- | Fetch the text contents of a URL+fetchRemote :: URL -> StateT Status IO Data.Text.Text+#ifndef WITH_HTTP+fetchRemote (url@URL { headers = maybeHeadersExpression }) = do+    let maybeHeaders = fmap toHeaders maybeHeadersExpression+    let urlString = Text.unpack (Core.pretty url)+    Status { _stack } <- State.get+    throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders))+#else+fetchRemote url = do+    zoom remote (State.put fetchFromHTTP)+    fetchFromHTTP url+  where+    fetchFromHTTP :: URL -> StateT Status IO Data.Text.Text+    fetchFromHTTP (url'@URL { headers = maybeHeadersExpression }) = do+        let maybeHeaders = fmap toHeaders maybeHeadersExpression+        fetchFromHttpUrl url' maybeHeaders+#endif++-- | Fetch the text contents of a URL+fetchRemoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+#ifndef WITH_HTTP+fetchRemoteBytes (url@URL { headers = maybeHeadersExpression }) = do+    let maybeHeaders = fmap toHeaders maybeHeadersExpression+    let urlString = Text.unpack (Core.pretty url)+    Status { _stack } <- State.get+    throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders))+#else+fetchRemoteBytes url = do+    zoom remoteBytes (State.put fetchFromHTTP)+    fetchFromHTTP url+  where+    fetchFromHTTP :: URL -> StateT Status IO Data.ByteString.ByteString+    fetchFromHTTP (url'@URL { headers = maybeHeadersExpression }) = do+        let maybeHeaders = fmap toHeaders maybeHeadersExpression+        fetchFromHttpUrlBytes url' maybeHeaders+#endif++getCacheFile+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath+getCacheFile cacheName hash = do+    cacheDirectory <- getOrCreateCacheDirectory cacheName++    let cacheFile = cacheDirectory </> ("1220" <> show hash)++    return cacheFile++getOrCreateCacheDirectory+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> m FilePath+getOrCreateCacheDirectory cacheName = do+    let warn message = do+            cacheWarningStatus <- State.get++            case cacheWarningStatus of+                CacheWarned    -> printWarning message+                CacheNotWarned -> return ()++            State.put CacheWarned++            empty++    let handler action dir (ioex :: IOException) = do+            let ioExMsg =+                     "When trying to " <> action <> ":\n"+                  <> "\n"+                  <> "↳ " <> dir <> "\n"+                  <> "\n"+                  <> "... the following exception was thrown:\n"+                  <> "\n"+                  <> "↳ " <> show ioex <> "\n"++            warn ioExMsg++    let setPermissions dir = do+            let private = transform Directory.emptyPermissions+                    where+                        transform =+                            Directory.setOwnerReadable   True+                          . Directory.setOwnerWritable   True+                          . Directory.setOwnerSearchable True++            catch+                (liftIO (Directory.setPermissions dir private))+                (handler "correct the permissions for" dir)++    let assertPermissions dir = do+            let accessible path =+                    Directory.readable   path+                 && Directory.writable   path+                 && Directory.searchable path++            permissions <-+                catch (liftIO (Directory.getPermissions dir))+                      (handler "get permissions of" dir)++            if accessible permissions+                then+                    return ()+                else do+                    let render f = if f permissions then "✓" else "✗"+                    let message =+                             "The directory:\n"+                          <> "\n"+                          <> "↳ " <> dir <> "\n"+                          <> "\n"+                          <> "... does not give you permission to read, write, or search files.\n\n"+                          <> "\n"+                          <> "The directory's current permissions are:\n"+                          <> "\n"+                          <> "• " <> render Directory.readable <> " readable\n"+                          <> "• " <> render Directory.writable <> " writable\n"+                          <> "• " <> render Directory.searchable <> " searchable\n"++                    warn message++    let existsDirectory dir =+            catch (liftIO (Directory.doesDirectoryExist dir))+                  (handler "check the existence of" dir)++    let existsFile path =+            catch (liftIO (Directory.doesFileExist path))+                  (handler "check the existence of" path)++    let createDirectory dir =+            catch (liftIO (Directory.createDirectory dir))+                  (handler "create" dir)++    let assertDirectory dir = do+            existsDir <- existsDirectory dir++            if existsDir+                then+                    assertPermissions dir++                else do+                    existsFile' <- existsFile dir++                    if existsFile'+                        then do+                            let message =+                                     "The given path:\n"+                                  <> "\n"+                                  <> "↳ " <> dir <> "\n"+                                  <> "\n"+                                  <> "... already exists but is not a directory.\n"++                            warn message++                        else do+                            assertDirectory (FilePath.takeDirectory dir)++                            createDirectory dir++                            setPermissions dir++    cacheBaseDirectory <- getCacheBaseDirectory++    let directory = cacheBaseDirectory </> cacheName++    let message =+             "Could not get or create the default cache directory:\n"+          <> "\n"+          <> "↳ " <> directory <> "\n"+          <> "\n"+          <> "You can enable caching by creating it if needed and setting read,\n"+          <> "write and search permissions on it or providing another cache base\n"+          <> "directory by setting the $XDG_CACHE_HOME environment variable.\n"+          <> "\n"++    assertDirectory directory <|> warn message++    return directory++getCacheBaseDirectory+    :: (MonadState CacheWarning m, Alternative m, MonadIO m) => m FilePath+getCacheBaseDirectory = alternative₀ <|> alternative₁ <|> alternative₂+  where+    alternative₀ = do+        maybeXDGCacheHome <-+          liftIO (System.Environment.lookupEnv "XDG_CACHE_HOME")++        case maybeXDGCacheHome of+            Just xdgCacheHome -> return xdgCacheHome+            Nothing           -> empty++    alternative₁+        | isWindows = do+            maybeLocalAppDirectory <-+              liftIO (System.Environment.lookupEnv "LOCALAPPDATA")++            case maybeLocalAppDirectory of+                Just localAppDirectory -> return localAppDirectory+                Nothing                -> empty++        | otherwise = do+            maybeHomeDirectory <-+              liftIO (System.Environment.lookupEnv "HOME")++            case maybeHomeDirectory of+                Just homeDirectory -> return (homeDirectory </> ".cache")+                Nothing            -> empty++        where isWindows = System.Info.os == "mingw32"++    alternative₂ = do+        cacheWarningStatus <- State.get++        let message =+                "\n"+             <> "\ESC[1;33mWarning\ESC[0m: "+             <> "Could not locate a cache base directory from the environment.\n"+             <> "\n"+             <> "You can provide a cache base directory by pointing the $XDG_CACHE_HOME\n"+             <> "environment variable to a directory with read and write permissions.\n"++        case cacheWarningStatus of+            CacheNotWarned ->+                liftIO (System.IO.hPutStrLn System.IO.stderr message)+            CacheWarned ->+                return ()++        State.put CacheWarned++        empty++-- If the URL contains headers typecheck them and replace them with their normal+-- forms.+normalizeHeadersIn :: URL -> StateT Status IO URL+normalizeHeadersIn url@URL { headers = Just headersExpression } = do+    Status { _stack } <- State.get+    loadedExpr <- loadWith headersExpression+    let handler (e :: SomeException) = throwMissingImport (Imported _stack e)+    normalized <- liftIO $ handle handler (normalizeHeaders loadedExpr)+    return url { headers = Just (fmap absurd normalized) }++normalizeHeadersIn url = return url++-- | Empty origin headers used for remote contexts+--   (and fallback when nothing is set in env or config file)+emptyOriginHeaders :: Expr Src Import+emptyOriginHeaders = ListLit (Just (fmap absurd originHeadersTypeExpr)) mempty++-- | A fake Src to annotate headers expressions with.+--   We need to wrap headers expressions in a Note for nice error reporting,+--   and because ImportAlt handling only catches SourcedExceptions+headersSrc :: Src+headersSrc = Src {+        srcStart = SourcePos {+            sourceName = fakeSrcName,+            sourceLine = mkPos 1,+            sourceColumn = mkPos 1+        },+        srcEnd = SourcePos {+            sourceName = fakeSrcName,+            sourceLine = mkPos 1,+            sourceColumn = mkPos (Text.length fakeSrcText)+        },+        srcText = fakeSrcText+    }+  where+    fakeSrcText = "«Origin Header Configuration»"+    fakeSrcName = "[builtin]"++-- | Load headers only from the environment (used in tests)+envOriginHeaders :: Expr Src Import+envOriginHeaders = Note headersSrc (Embed (Import (ImportHashed Nothing (Env "DHALL_HEADERS")) Code))++-- | Load headers in env, falling back to config file+defaultOriginHeaders :: IO (Expr Src Import)+#ifndef WITH_HTTP+defaultOriginHeaders = return emptyOriginHeaders+#else+defaultOriginHeaders = do+    fromFile <- originHeadersFileExpr+    return (Note headersSrc (ImportAlt envOriginHeaders (Note headersSrc fromFile)))+#endif++-- | Given a headers expression, return an origin headers loader+originHeadersLoader :: IO (Expr Src Import) -> StateT Status IO OriginHeaders+originHeadersLoader headersExpr = do++    -- Load the headers using the parent stack, which should always be a local+    -- import (we only load headers for the first remote import)++    status <- State.get++    let parentStack = fromMaybe abortEmptyStack (nonEmpty (NonEmpty.tail (_stack status)))++    let headerLoadStatus = status { _stack = parentStack }++    (headers, _) <- liftIO (State.runStateT doLoad headerLoadStatus)++    -- return cached headers next time+    _ <- State.modify (\state -> state { _loadOriginHeaders = return headers })++    return headers+  where+    abortEmptyStack = Core.internalError "Origin headers loaded with an empty stack"++    doLoad = do+        partialExpr <- liftIO headersExpr+        loaded <- loadWith (Note headersSrc (ImportAlt partialExpr emptyOriginHeaders))+        liftIO (toOriginHeaders loaded)++-- | Default starting `Status`, importing relative to the given directory.+emptyStatus :: FilePath -> Status+emptyStatus = makeEmptyStatus defaultNewManager defaultOriginHeaders++-- | See 'emptyStatus'+emptyStatusWithManager+    :: IO Manager+    -> FilePath+    -> Status+emptyStatusWithManager newManager = makeEmptyStatus newManager defaultOriginHeaders++-- | See 'emptyStatus'.+makeEmptyStatus+    :: IO Manager+    -> IO (Expr Src Import)+    -> FilePath+    -> Status+makeEmptyStatus newManager headersExpr rootDirectory =+    emptyStatusWith newManager (originHeadersLoader headersExpr) fetchRemote fetchRemoteBytes rootImport+  where+    prefix = if FilePath.isRelative rootDirectory+      then Here+      else Absolute++    pathComponents =+        fmap Text.pack (reverse (FilePath.splitDirectories rootDirectory))++    directoryAsFile = File (Directory pathComponents) "."++    rootImport = Import+      { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local prefix directoryAsFile+        }+      , importMode = Code+      }++{-| Default `Status` appropriate for a server interpreting Dhall code++    Using this `Status` ensures that interpreted Dhall code cannot access+    server-local resources (like files or environment variables)+-}+remoteStatus+    :: URL+    -- ^ Public address of the server+    -> Status+remoteStatus = remoteStatusWithManager defaultNewManager++-- | See `remoteStatus`+remoteStatusWithManager :: IO Manager -> URL -> Status+remoteStatusWithManager newManager url =+    emptyStatusWith newManager (originHeadersLoader (pure emptyOriginHeaders)) fetchRemote fetchRemoteBytes rootImport+  where+    rootImport = Import+      { importHashed = ImportHashed+        { hash = Nothing+        , importType = Remote url+        }+      , importMode = Code+      }++{-| Generalized version of `load`++    You can configure the desired behavior through the initial `Status` that you+    supply+-}+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith expr₀ = case expr₀ of+  Embed import₀ -> do+    Status {..} <- State.get++    let parent = NonEmpty.head _stack++    child <- chainImport parent import₀++    let local (Chained (Import (ImportHashed _ (Remote  {})) _)) = False+        local (Chained (Import (ImportHashed _ (Local   {})) _)) = True+        local (Chained (Import (ImportHashed _ (Env     {})) _)) = True+        local (Chained (Import (ImportHashed _ (Missing {})) _)) = False++    let referentiallySane = not (local child) || local parent++    if importMode import₀ == Location || referentiallySane+        then return ()+        else throwMissingImport (Imported _stack (ReferentiallyOpaque import₀))++    let _stack' = NonEmpty.cons child _stack++    if child `elem` _stack+        then throwMissingImport (Imported _stack (Cycle import₀))+        else return ()++    zoom graph . State.modify $+        -- Add the edge `parent -> child` to the import graph+        \edges -> Depends parent child : edges++    let stackWithChild = NonEmpty.cons child _stack++    zoom stack (State.put stackWithChild)+    ImportSemantics {..} <- loadImport child+    zoom stack (State.put _stack)++    return (Core.renote importSemantics)++  ImportAlt a b -> loadWith a `catch` handler₀+    where+      is :: forall e . Exception e => SomeException -> Bool+      is exception = Maybe.isJust (Exception.fromException @e exception)++      isNotResolutionError exception =+              is @(Imported (TypeError Src Void)) exception+          ||  is @(Imported  Cycle              ) exception+          ||  is @(Imported  HashMismatch       ) exception+          ||  is @(Imported  ParseError         ) exception++      handler₀ exception₀@(SourcedException (Src begin _ text₀) (MissingImports es₀))+          | any isNotResolutionError es₀ =+              throwM exception₀+          | otherwise = do+              loadWith b `catch` handler₁+        where+          handler₁ exception₁@(SourcedException (Src _ end text₁) (MissingImports es₁))+              | any isNotResolutionError es₁ =+                  throwM exception₁+              | otherwise =+                  -- Fix the source span for the error message to encompass both+                  -- alternatives, since both are equally to blame for the+                  -- failure if neither succeeds.+                  throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁)))+            where+              text₂ = text₀ <> " ? " <> text₁++  Note a b             -> do+      let handler e = throwM (SourcedException a (e :: MissingImports))++      (Note <$> pure a <*> loadWith b) `catch` handler+  Let a b              -> Let <$> bindingExprs loadWith a <*> loadWith b+  Record m             -> Record <$> traverse (recordFieldExprs loadWith) m+  RecordLit m          -> RecordLit <$> traverse (recordFieldExprs loadWith) m+  Lam cs a b           -> Lam cs <$> functionBindingExprs loadWith a <*> loadWith b+  Field a b            -> Field <$> loadWith a <*> pure b+  expression           -> Syntax.unsafeSubExpressions loadWith expression++-- | Resolve all imports within an expression+load :: Expr Src Import -> IO (Expr Src Void)+load = loadWithManager defaultNewManager++-- | See 'load'.+loadWithManager :: IO Manager -> Expr Src Import -> IO (Expr Src Void)+loadWithManager newManager =+    loadWithStatus+        (makeEmptyStatus newManager defaultOriginHeaders ".")+        UseSemanticCache++-- | Resolve all imports within an expression, importing relative to the given+-- directory.+loadRelativeTo :: FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)+loadRelativeTo parentDirectory = loadWithStatus+    (makeEmptyStatus defaultNewManager defaultOriginHeaders parentDirectory)++-- | See 'loadRelativeTo'.+loadWithStatus+    :: Status+    -> SemanticCacheMode+    -> Expr Src Import+    -> IO (Expr Src Void)+loadWithStatus status semanticCacheMode expression =+    State.evalStateT+        (loadWith expression)+        status { _semanticCacheMode = semanticCacheMode }++encodeExpression :: Expr Void Void -> Data.ByteString.ByteString+encodeExpression expression = bytesStrict+  where+    intermediateExpression :: Expr Void Import+    intermediateExpression = fmap absurd expression++    encoding = Codec.Serialise.encode intermediateExpression++    bytesStrict = Write.toStrictByteString encoding++-- | Hash a fully resolved expression+hashExpression :: Expr Void Void -> Dhall.Crypto.SHA256Digest+hashExpression = Dhall.Crypto.sha256Hash . encodeExpression++{-| Convenience utility to hash a fully resolved expression and return the+    base-16 encoded hash with the @sha256:@ prefix++    In other words, the output of this function can be pasted into Dhall+    source code to add an integrity check to an import+-}+hashExpressionToCode :: Expr Void Void -> Text+hashExpressionToCode expr =+    "sha256:" <> Text.pack (show (hashExpression expr))++-- | A call to `assertNoImports` failed because there was at least one import+data ImportResolutionDisabled = ImportResolutionDisabled deriving (Exception)++instance Show ImportResolutionDisabled where+    show _ = "\nImport resolution is disabled"++-- | Assert than an expression is import-free+assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void)+assertNoImports expression =+    Core.throws (traverse (\_ -> Left ImportResolutionDisabled) expression)+{-# INLINABLE assertNoImports #-}++{-| This function is used by the @--transitive@ option of the+    @dhall {freeze,format,lint}@ subcommands to determine which dependencies+    to descend into++#ifndef mingw32_HOST_OS+    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "foo") }, importMode = Code }+    Just "./foo"++    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "bar") }, importMode = Code }+    Just "./foo/bar"+++    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Remote (URL HTTPS "example.com" (File (Directory []) "") Nothing Nothing) }, importMode = Code }+    Nothing++    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Env "foo" }, importMode = Code }+    Nothing+#endif+-}+dependencyToFile :: Status -> Import -> IO (Maybe FilePath)+dependencyToFile status import_ = flip State.evalStateT status $ do+    parent :| _ <- zoom stack State.get++    child <- fmap chainedImport (hoist liftIO (chainImport parent import_))++    let ignore = return Nothing++    -- We only need to transitively modify code imports since other import+    -- types are not interpreted and therefore don't need to be modified+    case importMode child of+        RawText ->+            ignore++        RawBytes ->+            ignore++        Location ->+            ignore++        Code ->+            case importType (importHashed child) of+                Local filePrefix file -> do+                    let descend = liftIO $ do+                            path <- localToPath filePrefix file++                            return (Just path)++                    -- Only follow relative imports when modifying dependencies.+                    -- Carefully note that we check the file prefix of the+                    -- original import (before chaining), since the chained+                    -- import will inherit the file prefix of the parent import.+                    case importType (importHashed import_) of+                        Local Here   _ -> descend+                        Local Parent _ -> descend+                        _              -> ignore++                -- Don't transitively modify any other type of import+                Remote{} ->+                    ignore++                Missing ->+                    ignore++                Env{} ->+                    ignore
+ src/Dhall/Import/Headers.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns        #-}++module Dhall.Import.Headers+    ( normalizeHeaders+    , originHeadersTypeExpr+    , toHeaders+    , toOriginHeaders+    ) where++import Control.Applicative (Alternative (..), liftA2)+import Control.Exception   (SomeException)+import Control.Monad.Catch (handle, throwM)+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Core          (Chunks (..), Expr (..))+import Dhall.Import.Types  (HTTPHeader, OriginHeaders)+import Dhall.Parser        (Src (..))++import qualified Data.CaseInsensitive+import qualified Data.Foldable+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.Text.Encoding+import qualified Dhall.Core            as Core+import qualified Dhall.Map+import qualified Dhall.Pretty.Internal+import qualified Dhall.TypeCheck++-- | Given a well-typed (of type `List { header : Text, value Text }` or+-- `List { mapKey : Text, mapValue Text }`) headers expressions in normal form+-- construct the corresponding binary http headers; otherwise return the empty+-- list.+toHeaders :: Expr s a -> [HTTPHeader]+toHeaders (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybeHeaders)+  where+      maybeHeaders = mapM toHeader hs+toHeaders _ = []++toHeader :: Expr s a -> Maybe HTTPHeader+toHeader (RecordLit m) = do+    (Core.recordFieldValue -> TextLit (Chunks [] keyText), Core.recordFieldValue -> TextLit (Chunks [] valueText))+        <- lookupHeader <|> lookupMapKey+    let keyBytes   = Data.Text.Encoding.encodeUtf8 keyText+    let valueBytes = Data.Text.Encoding.encodeUtf8 valueText+    return (Data.CaseInsensitive.mk keyBytes, valueBytes)+      where+        lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)+        lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+toHeader _ =+    empty++-- | Normalize, typecheck and return OriginHeaders from a given expression.+toOriginHeaders :: Expr Src Void -> IO OriginHeaders+toOriginHeaders expr = fmap convert (normalizeOriginHeaders expr)+  where+    convert :: Expr s a -> OriginHeaders+    convert (ListLit _ hs) = HashMap.fromList (originPairs hs)+    convert _ = mempty++    originPairs hs = Data.Foldable.toList (Data.Foldable.fold (mapM toOriginPair hs))++    toOriginPair :: Expr s a -> Maybe (Text, [HTTPHeader])+    toOriginPair (RecordLit m) = do+      (Core.recordFieldValue -> TextLit (Chunks [] keyText), Core.recordFieldValue -> value)+          <- lookupMapKey+      return (keyText, toHeaders value)+        where+          lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+    toOriginPair _ = Nothing++makeHeadersTypeExpr :: Text -> Text -> Expr Src Void+makeHeadersTypeExpr keyKey valueKey =+  App List+      ( Record $ Core.makeRecordField <$>+          Dhall.Map.fromList+              [ (keyKey, Text)+              , (valueKey, Text)+              ]+      )++headersTypeExpr :: Expr Src Void+headersTypeExpr = makeHeadersTypeExpr "mapKey" "mapValue"++leagacyHeadersTypeExpr :: Expr Src Void+leagacyHeadersTypeExpr = makeHeadersTypeExpr "header" "value"++originHeadersTypeExpr :: Expr Src Void+originHeadersTypeExpr =+  App List+      ( Record $ Core.makeRecordField <$>+          Dhall.Map.fromList+              [ ("mapKey", Text)+              , ("mapValue", headersTypeExpr)+              ]+      )++typecheck :: Expr Src Void -> Expr Src Void -> IO (Expr Src Void)+typecheck expected expr = do+    let suffix_ = Dhall.Pretty.Internal.prettyToStrictText expected+    let annot = case expr of+            Note (Src begin end bytes) _ ->+                Note (Src begin end bytes') (Annot expr expected)+              where+                bytes' = bytes <> " : " <> suffix_+            _ ->+                Annot expr expected++    _ <- case (Dhall.TypeCheck.typeOf annot) of+        Left err -> throwM err+        Right _  -> return ()++    return (Core.normalize expr)++normalizeHeaders :: Expr Src Void -> IO (Expr Src Void)+normalizeHeaders headersExpr = do+    let handler₀ (e :: SomeException) = do+            {- Try to typecheck using the preferred @mapKey@/@mapValue@ fields+               and fall back to @header@/@value@ if that fails. However, if+               @header@/@value@ still fails then re-throw the original exception+               for @mapKey@ / @mapValue@. -}+            let handler₁ (_ :: SomeException) = throwM e+            handle handler₁ (typecheck leagacyHeadersTypeExpr headersExpr)++    handle handler₀ (typecheck headersTypeExpr headersExpr)++normalizeOriginHeaders :: Expr Src Void -> IO (Expr Src Void)+normalizeOriginHeaders = typecheck originHeadersTypeExpr
+ src/Dhall/Import/Types.hs view
@@ -0,0 +1,245 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++{-# OPTIONS_GHC -Wall #-}++module Dhall.Import.Types where++import Control.Exception                (Exception)+import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI)+import Data.Dynamic+import Data.HashMap.Strict              (HashMap)+import Data.List.NonEmpty               (NonEmpty)+import Data.Void                        (Void)+import Dhall.Context                    (Context)+import Dhall.Core+    ( Expr+    , Import (..)+    , ReifiedNormalizer (..)+    , URL+    )+import Dhall.Map                        (Map)+import Dhall.Parser                     (Src)+import Lens.Micro                       (Lens', lens)+import Prettyprinter                    (Pretty (..))++#ifdef WITH_HTTP+import qualified Dhall.Import.Manager+#endif++import qualified Data.Text+import qualified Dhall.Context+import qualified Dhall.Map          as Map+import qualified Dhall.Substitution++-- | A fully \"chained\" import, i.e. if it contains a relative path that path+--   is relative to the current directory. If it is a remote import with headers+--   those are well-typed (either of type `List { header : Text, value Text}` or+--   `List { mapKey : Text, mapValue Text})` and in normal form. These+--   invariants are preserved by the API exposed by @Dhall.Import@.+newtype Chained = Chained+    { chainedImport :: Import+      -- ^ The underlying import+    }+  deriving (Eq, Ord)++instance Pretty Chained where+    pretty (Chained import_) = pretty import_++-- | An import that has been fully interpeted+newtype ImportSemantics = ImportSemantics+    { importSemantics :: Expr Void Void+    -- ^ The fully resolved import, typechecked and beta-normal.+    }++-- | `parent` imports (i.e. depends on) `child`+data Depends = Depends { parent :: Chained, child :: Chained }++{-| This enables or disables the semantic cache for imports protected by+    integrity checks+-}+data SemanticCacheMode = IgnoreSemanticCache | UseSemanticCache deriving (Eq)++-- | Shared state for HTTP requests+type Manager =+#ifdef WITH_HTTP+    Dhall.Import.Manager.Manager+#else+    ()+#endif++-- | The default HTTP 'Manager'+defaultNewManager :: IO Manager+defaultNewManager =+#ifdef WITH_HTTP+  Dhall.Import.Manager.defaultNewManager+#else+  pure ()+#endif++-- | HTTP headers+type HTTPHeader = (CI ByteString, ByteString)++-- | A map of site origin -> HTTP headers+type OriginHeaders = HashMap Data.Text.Text [HTTPHeader]++{-| Used internally to track whether or not we've already warned the user about+    caching issues+-}+data CacheWarning = CacheNotWarned | CacheWarned++-- | State threaded throughout the import process+data Status = Status+    { _stack :: NonEmpty Chained+    -- ^ Stack of `Import`s that we've imported along the way to get to the+    -- current point++    , _graph :: [Depends]+    -- ^ Graph of all the imports visited so far, represented by a list of+    --   import dependencies.++    , _cache :: Map Chained ImportSemantics+    -- ^ Cache of imported expressions with their node id in order to avoid+    --   importing the same expression twice with different values++    , _newManager :: IO Manager+    , _manager :: Maybe Manager+    -- ^ Used to cache the `Dhall.Import.Manager.Manager` when making multiple+    -- requests++    , _loadOriginHeaders :: StateT Status IO OriginHeaders+    -- ^ Load the origin headers from environment or configuration file.+    --   After loading once, further evaluations return the cached version.++    , _remote :: URL -> StateT Status IO Data.Text.Text+    -- ^ The remote resolver, fetches the content at the given URL.++    , _remoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+    -- ^ Like `_remote`, except for `Dhall.Syntax.Expr.Bytes`++    , _substitutions :: Dhall.Substitution.Substitutions Src Void++    , _normalizer :: Maybe (ReifiedNormalizer Void)++    , _startingContext :: Context (Expr Src Void)++    , _semanticCacheMode :: SemanticCacheMode++    , _cacheWarning :: CacheWarning+    -- ^ Records whether or not we already warned the user about issues with+    --   cache directory+    }++-- | Initial `Status`, parameterised over the HTTP 'Manager',+--   the origin headers and the remote resolver,+--   importing relative to the given root import.+emptyStatusWith+    :: IO Manager+    -> StateT Status IO OriginHeaders+    -> (URL -> StateT Status IO Data.Text.Text)+    -> (URL -> StateT Status IO Data.ByteString.ByteString)+    -> Import+    -> Status+emptyStatusWith _newManager _loadOriginHeaders _remote _remoteBytes rootImport = Status {..}+  where+    _stack = pure (Chained rootImport)++    _graph = []++    _cache = Map.empty++    _manager = Nothing++    _substitutions = Dhall.Substitution.empty++    _normalizer = Nothing++    _startingContext = Dhall.Context.empty++    _semanticCacheMode = UseSemanticCache++    _cacheWarning = CacheNotWarned++-- | Lens from a `Status` to its `_stack` field+stack :: Lens' Status (NonEmpty Chained)+stack = lens _stack (\s x -> s { _stack = x })++-- | Lens from a `Status` to its `_graph` field+graph :: Lens' Status [Depends]+graph = lens _graph (\s x -> s { _graph = x })++-- | Lens from a `Status` to its `_cache` field+cache :: Lens' Status (Map Chained ImportSemantics)+cache = lens _cache (\s x -> s { _cache = x })++-- | Lens from a `Status` to its `_remote` field+remote :: Lens' Status (URL -> StateT Status IO Data.Text.Text)+remote = lens _remote (\s x -> s { _remote = x })++-- | Lens from a `Status` to its `_remote` field+remoteBytes :: Lens' Status (URL -> StateT Status IO Data.ByteString.ByteString)+remoteBytes = lens _remoteBytes (\s x -> s { _remoteBytes = x })++-- | Lens from a `Status` to its `_substitutions` field+substitutions :: Lens' Status (Dhall.Substitution.Substitutions Src Void)+substitutions = lens _substitutions (\s x -> s { _substitutions = x })++-- | Lens from a `Status` to its `_normalizer` field+normalizer :: Lens' Status (Maybe (ReifiedNormalizer Void))+normalizer = lens _normalizer (\s x -> s {_normalizer = x})++-- | Lens from a `Status` to its `_startingContext` field+startingContext :: Lens' Status (Context (Expr Src Void))+startingContext = lens _startingContext (\s x -> s { _startingContext = x })++-- | Lens from a `Status` to its `_cacheWarning` field+cacheWarning :: Lens' Status CacheWarning+cacheWarning = lens _cacheWarning (\s x -> s { _cacheWarning = x })++{-| This exception indicates that there was an internal error in Dhall's+    import-related logic++    This exception indicates that an invalid `Dhall.Syntax.Type` was provided to+    the `Dhall.input` function+-}+data InternalError = InternalError deriving (Typeable)+++instance Show InternalError where+    show InternalError = unlines+        [ _ERROR <> ": Compiler bug                                                        "+        , "                                                                                "+        , "Explanation: This error message means that there is a bug in the Dhall compiler."+        , "You didn't do anything wrong, but if you would like to see this problem fixed   "+        , "then you should report the bug at:                                              "+        , "                                                                                "+        , "https://github.com/dhall-lang/dhall-haskell/issues                              "+        , "                                                                                "+        , "Please include the following text in your bug report:                           "+        , "                                                                                "+        , "```                                                                             "+        , "Header extraction failed even though the header type-checked                    "+        , "```                                                                             "+        ]+      where+        _ERROR :: String+        _ERROR = "\ESC[1;31mError\ESC[0m"++instance Exception InternalError++-- | Wrapper around `Network.HTTP.Client.HttpException`s with a prettier `Show`+-- instance+--+-- In order to keep the library API constant even when the @with-http@ Cabal+-- flag is disabled the pretty error message is pre-rendered and the real+-- 'Network.HTTP.Client.HttpException' is stored in a 'Dynamic'+data PrettyHttpException = PrettyHttpException String Dynamic+    deriving (Typeable)++instance Exception PrettyHttpException++instance Show PrettyHttpException where+  show (PrettyHttpException msg _) = msg
+ src/Dhall/Lint.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}++-- | This module contains the implementation of the @dhall lint@ command++module Dhall.Lint+    ( -- * Lint+      lint+    , removeUnusedBindings+    , fixAssert+    , fixParentPath+    , addPreludeExtensions+    , removeLetInLet+    , useToMap+    ) where++import Control.Applicative ((<|>))++import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    , URL (..)+    , Var (..)+    , subExpressions+    )++import qualified Data.Foldable      as Foldable+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text          as Text+import qualified Dhall.Core         as Core+import qualified Dhall.Map+import qualified Lens.Micro         as Lens++{-| Automatically improve a Dhall expression++    Currently this:++    * removes unused @let@ bindings with 'removeUnusedBindings'.+    * fixes @let a = x ≡ y@ to be @let a = assert : x ≡ y@+    * consolidates nested @let@ bindings to use a multiple-@let@ binding with 'removeLetInLet'+    * fixes paths of the form @.\/..\/foo@ to @..\/foo@+-}+lint :: Eq s => Expr s Import -> Expr s Import+lint =  Lens.rewriteOf subExpressions rewrite+  where+    rewrite e =+            fixAssert                e+        <|> removeUnusedBindings     e+        <|> fixParentPath            e+        <|> removeLetInLet           e+        <|> addPreludeExtensions     e++-- | Remove unused `Let` bindings.+removeUnusedBindings :: Eq a => Expr s a -> Maybe (Expr s a)+-- Don't remove assertions!+removeUnusedBindings (Let (Binding _ _ _ _ _ e) _)+    | isOrContainsAssert e = Nothing+removeUnusedBindings (Let (Binding _ a _ _ _ _) d)+    | not (V a 0 `Core.freeIn` d) =+        Just (Core.shift (-1) (V a 0) d)+removeUnusedBindings _ = Nothing++-- | Fix `Let` bindings  that the user probably meant to be @assert@s+fixAssert :: Expr s a -> Maybe (Expr s a)+fixAssert (Let (Binding { value = v@(Core.shallowDenote -> Equivalent {}), ..}) body) =+    Just (Let (Binding { value = Assert v, .. }) body)+fixAssert (Let binding body@(Core.shallowDenote -> Equivalent {})) =+    Just (Let binding (Assert body))+fixAssert _ =+    Nothing++-- | This transforms @.\/..\/foo@ into @..\/foo@+fixParentPath :: Expr s Import -> Maybe (Expr s Import)+fixParentPath (Embed oldImport) = do+    let Import{..} = oldImport++    let ImportHashed{..} = importHashed++    case importType of+        Local Here File{ directory = Directory { components }, .. }+            | Just nonEmpty <- NonEmpty.nonEmpty components+            , NonEmpty.last nonEmpty == ".." -> do+                let newDirectory =+                        Directory { components = NonEmpty.init nonEmpty }++                let newImportType =+                        Local Parent File{ directory = newDirectory, .. }++                let newImportHashed =+                        ImportHashed { importType = newImportType, .. }++                let newImport = Import { importHashed = newImportHashed, .. }++                Just (Embed newImport)+        _ ->+            Nothing+fixParentPath _  = Nothing++{-| This transforms @https://prelude.dhall-lang.org/…/foo@ to+    @https://prelude.dhall-lang.org/…/foo.dhall@+-}+addPreludeExtensions :: Expr s Import -> Maybe (Expr s Import)+addPreludeExtensions (Embed oldImport) = do+    let Import{ importHashed = oldImportHashed, .. } = oldImport++    let ImportHashed{ importType = oldImportType, .. } = oldImportHashed++    case oldImportType of+        Remote URL{ path = oldPath, ..}+            | authority == "prelude.dhall-lang.org" ->+                case oldPath of+                    File{ file = oldFile, .. }+                        | not (Text.isSuffixOf ".dhall" oldFile) -> do+                            let newFile = oldFile <> ".dhall"++                            let newPath = File{ file = newFile, .. }++                            let newImportType = Remote URL{ path = newPath, .. }++                            let newImportHashed =+                                    ImportHashed{ importType = newImportType, .. }++                            let newImport =+                                    Import{ importHashed = newImportHashed, .. }++                            return (Embed newImport)+                    _ ->+                        Nothing+        _ -> do+            Nothing+addPreludeExtensions _ = Nothing++isOrContainsAssert :: Expr s a -> Bool+isOrContainsAssert (Assert _) = True+isOrContainsAssert e = Lens.anyOf subExpressions isOrContainsAssert e++-- | The difference between+--+-- > let x = 1 let y = 2 in x + y+--+-- and+--+-- > let x = 1 in let y = 2 in x + y+--+-- is that in the second expression, the inner 'Let' is wrapped by a 'Note'.+--+-- We remove such a 'Note' in order to consolidate nested let-blocks into a+-- single one.+removeLetInLet :: Expr s a -> Maybe (Expr s a)+removeLetInLet (Let binding (Note _ l@Let{})) = Just (Let binding l)+removeLetInLet _ = Nothing++-- | This replaces a record of key-value pairs with the equivalent use of+--   @toMap@+--+-- This is currently not used by @dhall lint@ because this would sort @Map@+-- keys, which is not necessarily a behavior-preserving change, but is still+-- made available as a convenient rewrite rule.  For example,+-- @{json,yaml}-to-dhall@ use this rewrite to simplify their output.+useToMap :: Expr s a -> Maybe (Expr s a)+useToMap+    (ListLit+        t@(Just+            (Core.shallowDenote -> App+                (Core.shallowDenote -> List)+                (Core.shallowDenote -> Record+                    (Dhall.Map.sort ->+                        [ ("mapKey", Core.shallowDenote . Core.recordFieldValue -> Text)+                        , ("mapValue", _)+                        ]+                    )+                )+            )+        )+        []+    ) =+        Just (ToMap (RecordLit []) t)+useToMap (ListLit _ keyValues)+    | not (null keyValues)+    , Just keyValues' <- traverse convert keyValues =+        Just+            (ToMap+                (RecordLit (Dhall.Map.fromList (Foldable.toList keyValues')))+                Nothing+            )+  where+    convert keyValue =+        case Core.shallowDenote keyValue of+            RecordLit+                (Dhall.Map.sort ->+                    [ ("mapKey"  , Core.shallowDenote . Core.recordFieldValue -> TextLit (Chunks [] key))+                    , ("mapValue", value)+                    ]+                ) ->+                    Just (key, value)+            _ ->+                Nothing+useToMap _ =+    Nothing
+ src/Dhall/Main.hs view
@@ -0,0 +1,1073 @@+{-| This module contains the top-level entrypoint and options parsing for the+    @dhall@ executable+-}++{-# LANGUAGE ApplicativeDo     #-}+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++module Dhall.Main+    ( -- * Options+      Options(..)+    , Mode(..)+    , ResolveMode(..)+    , parseOptions+    , parserInfoOptions++      -- * Execution+    , Dhall.Main.command+    , main+    ) where++import Control.Applicative (optional, (<|>))+import Control.Exception   (Handler (..), SomeException)+import Control.Monad       (when)+import Data.Foldable       (for_)+import Data.List.NonEmpty  (NonEmpty (..), nonEmpty)+import Data.Maybe          (fromMaybe)+import Data.Monoid         (Endo (..))+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Freeze        (Intent (..), Scope (..))+import Dhall.Import+    ( Depends (..)+    , Imported (..)+    , SemanticCacheMode (..)+    , _semanticCacheMode+    )+import Dhall.Package       (PackagingMode (..), writePackage)+import Dhall.Parser        (Src)+import Dhall.Pretty+    ( Ann+    , CharacterSet (..)+    , annToAnsiStyle+    , detectCharacterSet+    )+import Dhall.Schemas       (Schemas (..))+import Dhall.TypeCheck     (Censored (..), DetailedTypeError (..), TypeError)+import Dhall.Version       (dhallVersionString)+import Lens.Micro          (set)+import Options.Applicative (Parser, ParserInfo)+import Prettyprinter       (Doc, Pretty)+import System.Exit         (ExitCode, exitFailure)+import System.IO           (Handle)+import Text.Dot            ((.->.))++import Dhall.Core+    ( Expr (Annot)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    , URL (..)+    , pretty+    )+import Dhall.Util+    ( Censor (..)+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , Output (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    )++import qualified Codec.CBOR.JSON+import qualified Codec.CBOR.Read+import qualified Codec.CBOR.Write+import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict   as State+import qualified Data.Aeson+import qualified Data.Aeson.Encode.Pretty+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Lazy.Char8+import qualified Data.Map+import qualified Data.Text+import qualified Data.Text.IO+import qualified Dhall+import qualified Dhall.Binary+import qualified Dhall.Core+import qualified Dhall.Diff+import qualified Dhall.DirectoryTree                as DirectoryTree+import qualified Dhall.Format+import qualified Dhall.Freeze+import qualified Dhall.Import+import qualified Dhall.Import.Types+import qualified Dhall.Lint+import qualified Dhall.Map+import qualified Dhall.Package+import qualified Dhall.Pretty+import qualified Dhall.Repl+import qualified Dhall.Schemas+import qualified Dhall.Tags+import qualified Dhall.TypeCheck+import qualified Dhall.Util+import qualified GHC.IO.Encoding+import qualified Options.Applicative+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified System.Console.ANSI+import qualified System.Exit                        as Exit+import qualified System.FilePath+import qualified System.IO+import qualified Text.Dot+import qualified Text.Pretty.Simple++-- | Top-level program options+data Options = Options+    { mode               :: Mode+    , explain            :: Bool+    , plain              :: Bool+    , chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor+    }++-- | The subcommands for the @dhall@ executable+data Mode+    = Default+          { file :: Input+          , output :: Output+          , annotate :: Bool+          , alpha :: Bool+          , semanticCacheMode :: SemanticCacheMode+          , version :: Bool+          }+    | Version+    | Resolve+          { file :: Input+          , resolveMode :: Maybe ResolveMode+          , semanticCacheMode :: SemanticCacheMode+          }+    | Type+          { file :: Input+          , quiet :: Bool+          , semanticCacheMode :: SemanticCacheMode+          }+    | Normalize { file :: Input , alpha :: Bool }+    | Repl+    | Format { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }+    | Freeze { deprecatedInPlace :: Bool, transitivity :: Transitivity, all_ :: Bool, cache :: Bool, outputMode :: OutputMode, inputs :: NonEmpty Input }+    | Hash { file :: Input, cache :: Bool }+    | Diff { expr1 :: Text, expr2 :: Text }+    | Lint { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }+    | Tags+          { input :: Input+          , output :: Output+          , suffixes :: Maybe [Text]+          , followSymlinks :: Bool+          }+    | Encode { file :: Input, json :: Bool }+    | Decode { file :: Input, json :: Bool, quiet :: Bool }+    | Text { file :: Input, output :: Output }+    | DirectoryTree { allowSeparators :: Bool, file :: Input, path :: FilePath }+    | Schemas { file :: Input, outputMode :: OutputMode, schemas :: Text }+    | SyntaxTree { file :: Input, noted :: Bool }+    | Package+        { packageOptions :: Endo Dhall.Package.Options+        , packageFiles :: NonEmpty FilePath+        }++-- | This specifies how to resolve transitive dependencies+data ResolveMode+    = Dot+    -- ^ Generate a DOT file for @graphviz@+    | ListTransitiveDependencies+    -- ^ List all transitive dependencies as text, one per line+    | ListImmediateDependencies+    -- ^ List immediate dependencies as text, one per line++-- | Groups of subcommands+data Group+    = Manipulate+    | Generate+    | Interpret+    | Convert+    | Miscellaneous+    | Debugging++groupDescription :: Group -> String+groupDescription group = case group of+    Manipulate -> "Manipulate Dhall code"+    Generate -> "Generate other formats from Dhall"+    Interpret -> "Interpret Dhall"+    Convert -> "Convert Dhall to and from its binary representation"+    Miscellaneous -> "Miscellaneous"+    Debugging -> "Debugging this interpreter"++-- | `Parser` for the `Options` type+parseOptions :: Parser Options+parseOptions =+        Options+    <$> parseMode+    <*> switch "explain" "Explain error messages in more detail"+    <*> switch "plain" "Disable syntax highlighting"+    <*> parseCharacterSet+    <*> parseCensor+  where+    switch name description =+        Options.Applicative.switch+            (   Options.Applicative.long name+            <>  Options.Applicative.help description+            )++    parseCensor = fmap f (switch "censor" "Hide source code in error messages")+      where+        f True  = Censor+        f False = NoCensor++    parseCharacterSet =+            Options.Applicative.flag'+                (Just Unicode)+                (   Options.Applicative.long "unicode"+                <>  Options.Applicative.help "Format code using only Unicode syntax"+                )+        <|> Options.Applicative.flag'+                (Just ASCII)+                (   Options.Applicative.long "ascii"+                <>  Options.Applicative.help "Format code using only ASCII syntax"+                )+        <|> pure Nothing++subcommand :: Group -> String -> String -> Parser a -> Parser a+subcommand group name description parser =+    Options.Applicative.hsubparser+        (   Options.Applicative.command name parserInfo+        <>  Options.Applicative.metavar name+        <>  Options.Applicative.commandGroup (groupDescription group)+        )+  where+    parserInfo =+        Options.Applicative.info parser+            (   Options.Applicative.fullDesc+            <>  Options.Applicative.progDesc description+            )++parseMode :: Parser Mode+parseMode =+        subcommand+            Manipulate+            "format"+            "Standard code formatter for the Dhall language"+            (Format <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "formatted" <*> parseFiles)+    <|> subcommand+            Manipulate+            "freeze"+            "Add integrity checks to remote import statements of an expression"+            (Freeze <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen" <*> parseFiles)+    <|> subcommand+            Manipulate+            "lint"+            "Improve Dhall code by using newer language features and removing dead code"+            (Lint <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "linted" <*> parseFiles)+    <|> subcommand+            Manipulate+            "rewrite-with-schemas"+            "Simplify Dhall code using a schemas record"+            (Dhall.Main.Schemas <$> parseInplaceNonTransitive <*> parseCheck "rewritten" <*> parseSchemasRecord)+    <|> subcommand+            Generate+            "text"+            "Render a Dhall expression that evaluates to a Text literal"+            (Text <$> parseFile <*> parseOutput)+    <|> subcommand+            Generate+            "to-directory-tree"+            "Convert nested records of Text literals into a directory tree"+            (DirectoryTree <$> parseDirectoryTreeAllowSeparators <*> parseFile <*> parseDirectoryTreeOutput)+    <|> subcommand+            Interpret+            "resolve"+            "Resolve an expression's imports"+            (Resolve <$> parseFile <*> parseResolveMode <*> parseSemanticCacheMode)+    <|> subcommand+            Interpret+            "type"+            "Infer an expression's type"+            (Type <$> parseFile <*> parseQuiet <*> parseSemanticCacheMode)+    <|> subcommand+            Interpret+            "normalize"+            "Normalize an expression"+            (Normalize <$> parseFile <*> parseAlpha)+    <|> subcommand+            Convert+            "encode"+            "Encode a Dhall expression to binary"+            (Encode <$> parseFile <*> parseJSONFlag)+    <|> subcommand+            Convert+            "decode"+            "Decode a Dhall expression from binary"+            (Decode <$> parseFile <*> parseJSONFlag <*> parseQuiet)+    <|> subcommand+            Miscellaneous+            "repl"+            "Interpret expressions in a REPL"+            (pure Repl)+    <|> subcommand+            Miscellaneous+            "diff"+            "Render the difference between the normal form of two expressions"+            (Diff <$> argument "expr1" <*> argument "expr2")+    <|> subcommand+            Miscellaneous+            "hash"+            "Compute semantic hashes for Dhall expressions"+            (Hash <$> parseFile <*> parseCache)+    <|> subcommand+            Miscellaneous+            "package"+            "Create a package.dhall referencing the provided paths"+            (Package <$> parsePackageOptions <*> parsePackageFiles)+    <|> subcommand+            Miscellaneous+            "tags"+            "Generate etags file"+            (Tags <$> parseInput <*> parseTagsOutput <*> parseSuffixes <*> parseFollowSymlinks)+    <|> subcommand+            Miscellaneous+            "version"+            "Display version"+            (pure Version)+    <|> subcommand+            Debugging+            "haskell-syntax-tree"+            "Output the parsed syntax tree (for debugging)"+            (SyntaxTree <$> parseFile <*> parseNoted)+    <|> (   Default+        <$> parseFile+        <*> parseOutput+        <*> parseAnnotate+        <*> parseAlpha+        <*> parseSemanticCacheMode+        <*> parseVersion+        )+  where+    deprecatedInPlace =+        Options.Applicative.switch+            (   Options.Applicative.long "inplace"+            <>  Options.Applicative.internal -- completely hidden from help+            )++    argument =+            fmap Data.Text.pack+        .   Options.Applicative.strArgument+        .   Options.Applicative.metavar++    parseFile = fmap f (optional p)+      where+        f  Nothing    = StandardInput+        f (Just file) = InputFile file++        p = Options.Applicative.strOption+                (   Options.Applicative.long "file"+                <>  Options.Applicative.help "Read expression from a file instead of standard input"+                <>  Options.Applicative.metavar "FILE"+                <>  Options.Applicative.action "file"+                )++    parseFiles = fmap f (Options.Applicative.many p)+      where+        -- Parse explicit stdin in the input filepaths+        parseStdin inputs+            | InputFile "-" `elem` inputs = StandardInput : filter (/= InputFile "-") inputs+            | otherwise = inputs++        f = fromMaybe (pure StandardInput) . nonEmpty . parseStdin . fmap InputFile++        p = Options.Applicative.strArgument+                (   Options.Applicative.help "Read expression from files instead of standard input"+                <>  Options.Applicative.metavar "FILES"+                <>  Options.Applicative.action "file"+                )++    parseOutput = fmap f (optional p)+      where+        f Nothing = StandardOutput+        f (Just file) = OutputFile file++        p = Options.Applicative.strOption+                (   Options.Applicative.long "output"+                <>  Options.Applicative.help "Write result to a file instead of standard output"+                <>  Options.Applicative.metavar "FILE"+                <>  Options.Applicative.action "file"+                )++    parseAlpha =+        Options.Applicative.switch+            (   Options.Applicative.long "alpha"+            <>  Options.Applicative.help "α-normalize expression"+            )++    parseAnnotate =+        Options.Applicative.switch+            (   Options.Applicative.long "annotate"+            <>  Options.Applicative.help "Add a type annotation to the output"+            )++    parseSemanticCacheMode =+        Options.Applicative.flag+            UseSemanticCache+            IgnoreSemanticCache+            (   Options.Applicative.long "no-cache"+            <>  Options.Applicative.help+                  "Handle protected imports as if the cache was empty"+            )++    parseVersion =+        Options.Applicative.switch+            (   Options.Applicative.long "version"+            <>  Options.Applicative.help "Display version"+            )++    parseResolveMode =+          Options.Applicative.flag' (Just Dot)+              (   Options.Applicative.long "dot"+              <>  Options.Applicative.help+                    "Output import dependency graph in dot format"+              )+        <|>+          Options.Applicative.flag' (Just ListImmediateDependencies)+              (   Options.Applicative.long "immediate-dependencies"+              <>  Options.Applicative.help+                    "List immediate import dependencies"+              )+        <|>+          Options.Applicative.flag' (Just ListTransitiveDependencies)+              (   Options.Applicative.long "transitive-dependencies"+              <>  Options.Applicative.help+                    "List transitive import dependencies in post-order"+              )+        <|> pure Nothing++    parseQuiet =+        Options.Applicative.switch+            (   Options.Applicative.long "quiet"+            <>  Options.Applicative.help "Don't print the result"+            )++    parseInplace =+        Options.Applicative.strOption+            (   Options.Applicative.long "inplace"+            <>  Options.Applicative.help "Modify the specified file in-place"+            <>  Options.Applicative.metavar "FILE"+            <>  Options.Applicative.action "file"+            )++    parseTransitiveSwitch = Options.Applicative.flag NonTransitive Transitive+        (   Options.Applicative.long "transitive"+        <>  Options.Applicative.help "Modify the input and its transitive relative imports in-place"+        )++    parseInplaceNonTransitive =+            fmap InputFile parseInplace+        <|> pure StandardInput++    parseInput = fmap f (optional p)+      where+        f  Nothing    = StandardInput+        f (Just path) = InputFile path++        p = Options.Applicative.strOption+            (   Options.Applicative.long "path"+            <>  Options.Applicative.help "Index all files in path recursively. Will get list of files from STDIN if omitted."+            <>  Options.Applicative.metavar "PATH"+            <>  Options.Applicative.action "file"+            <>  Options.Applicative.action "directory"+            )++    parseTagsOutput = fmap f (optional p)+      where+        f  Nothing    = OutputFile "tags"+        f (Just file) = OutputFile file++        p = Options.Applicative.strOption+            (   Options.Applicative.long "output"+            <>  Options.Applicative.help "The name of the file that the tags are written to. Defaults to \"tags\""+            <>  Options.Applicative.metavar "FILENAME"+            <>  Options.Applicative.action "file"+            )++    parseSuffixes = fmap f (optional p)+      where+        f  Nothing    = Just [".dhall"]+        f (Just "")   = Nothing+        f (Just line) = Just (Data.Text.splitOn " " line)++        p = Options.Applicative.strOption+            (   Options.Applicative.long "suffixes"+            <>  Options.Applicative.help "Index only files with suffixes. \"\" to index all files."+            <>  Options.Applicative.metavar "SUFFIXES"+            )++    parseFollowSymlinks =+        Options.Applicative.switch+        (   Options.Applicative.long "follow-symlinks"+        <>  Options.Applicative.help "Follow symlinks when recursing directories"+        )++    parseJSONFlag =+        Options.Applicative.switch+        (   Options.Applicative.long "json"+        <>  Options.Applicative.help "Use JSON representation of CBOR"+        )++    parseAllFlag =+        Options.Applicative.switch+        (   Options.Applicative.long "all"+        <>  Options.Applicative.help "Add integrity checks to all imports (not just remote imports) except for missing imports"+        )++    parseCacheFlag =+        Options.Applicative.switch+        (   Options.Applicative.long "cache"+        <>  Options.Applicative.help "Add fallback unprotected imports when using integrity checks purely for caching purposes"+        )++    parseCheck processed = fmap adapt switch+      where+        adapt True  = Check+        adapt False = Write++        switch =+            Options.Applicative.switch+            (   Options.Applicative.long "check"+            <>  Options.Applicative.help ("Only check if the input is " <> processed)+            )++    parseSchemasRecord =+        Options.Applicative.strOption+            (   Options.Applicative.long "schemas"+            <>  Options.Applicative.help "A record of schemas"+            <>  Options.Applicative.metavar "EXPR"+            )++    parseDirectoryTreeAllowSeparators =+        Options.Applicative.switch+            (   Options.Applicative.long "allow-path-separators"+            <>  Options.Applicative.help "Whether to allow path separators in file names"+            )++    parseDirectoryTreeOutput =+        Options.Applicative.strOption+            (   Options.Applicative.long "output"+            <>  Options.Applicative.help "The destination path to create"+            <>  Options.Applicative.metavar "PATH"+            <>  Options.Applicative.action "directory"+            )++    parseNoted =+        Options.Applicative.switch+            (   Options.Applicative.long "noted"+            <>  Options.Applicative.help "Print `Note` constructors"+            )++    parseCache =+        Options.Applicative.switch+            (   Options.Applicative.long "cache"+            <>  Options.Applicative.help "Cache the hashed expression"+            )++    parsePackageOptions :: Parser (Endo Dhall.Package.Options)+    parsePackageOptions = do+        packageMode <- (optional . Options.Applicative.flag' RecursiveSubpackages)+            ( Options.Applicative.short 'r'+            <> Options.Applicative.long "recursive"+            <> Options.Applicative.help "Create packages for all subdirectories first."+            )++        packageFileName <- (optional . Options.Applicative.strOption)+                (   Options.Applicative.long "name"+                <>  Options.Applicative.help "The filename of the package"+                <>  Options.Applicative.metavar "NAME"+                <>  Options.Applicative.action "file"+                )++        pure $+            maybe mempty (Endo . set Dhall.Package.packagingMode) packageMode <>+            maybe mempty (Endo . set Dhall.Package.packageFileName) packageFileName++    parsePackageFiles = (:|) <$> p <*> Options.Applicative.many p+      where+        p = Options.Applicative.strArgument+                (   Options.Applicative.help "Paths that may either point to files or directories. If the latter is the case all *.dhall files in the directory will be included."+                <>  Options.Applicative.metavar "PATH"+                <>  Options.Applicative.action "file"+                )++-- | `ParserInfo` for the `Options` type+parserInfoOptions :: ParserInfo Options+parserInfoOptions =+    Options.Applicative.info+        (Options.Applicative.helper <*> parseOptions)+        (   Options.Applicative.progDesc "Interpreter for the Dhall language"+        <>  Options.Applicative.fullDesc+        )++noHeaders :: Import -> Import+noHeaders+    (Import { importHashed = ImportHashed { importType = Remote URL{ .. }, ..}, .. }) =+    Import { importHashed = ImportHashed { importType = Remote URL{ headers = Nothing, .. }, .. }, .. }+noHeaders i =+    i++-- | Run the command specified by the `Options` type+command :: Options -> IO ()+command (Options {..}) = do+    GHC.IO.Encoding.setLocaleEncoding System.IO.utf8++    let rootDirectory = \case+            InputFile f   -> System.FilePath.takeDirectory f+            StandardInput -> "."++    let toStatus = Dhall.Import.emptyStatus . rootDirectory++    let getExpression = Dhall.Util.getExpression censor++    -- The characterSet detection used here only works on the source+    -- expression, before any transformation is applied. This helper is there+    -- make sure the detection is done on the correct expr.+    let getExpressionAndCharacterSet file = do+            expr <- getExpression file++            let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet++            return (expr, characterSet)++    let handle io =+            Control.Exception.catches io+                [ Handler handleTypeError+                , Handler handleImported+                , Handler handleExitCode+                ]+          where+            handleAll e = do+                let string = show (e :: SomeException)++                if not (null string)+                    then System.IO.hPutStrLn System.IO.stderr string+                    else return ()++                System.Exit.exitFailure++            handleTypeError e = Control.Exception.handle handleAll $ do+                let _ = e :: TypeError Src Void+                System.IO.hPutStrLn System.IO.stderr ""+                if explain+                    then+                        case censor of+                            Censor   -> Control.Exception.throwIO (CensoredDetailed (DetailedTypeError e))+                            NoCensor -> Control.Exception.throwIO (DetailedTypeError e)++                    else do+                        Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"+                        case censor of+                            Censor   -> Control.Exception.throwIO (Censored e)+                            NoCensor -> Control.Exception.throwIO e++            handleImported (Imported ps e) = Control.Exception.handle handleAll $ do+                let _ = e :: TypeError Src Void+                System.IO.hPutStrLn System.IO.stderr ""+                if explain+                    then Control.Exception.throwIO (Imported ps (DetailedTypeError e))+                    else do+                        Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"+                        Control.Exception.throwIO (Imported ps e)++            handleExitCode e =+                Control.Exception.throwIO (e :: ExitCode)++    let renderDoc :: Handle -> Doc Ann -> IO ()+        renderDoc h doc = do+            let stream = Dhall.Pretty.layout doc++            supportsANSI <- System.Console.ANSI.hSupportsANSI h+            let ansiStream =+                    if supportsANSI && not plain+                    then fmap annToAnsiStyle stream+                    else Pretty.unAnnotateS stream++            Pretty.renderIO h ansiStream+            Data.Text.IO.hPutStrLn h ""++    let render :: Pretty a => Handle -> CharacterSet -> Expr Src a -> IO ()+        render h characterSet expression = do+            let doc = Dhall.Pretty.prettyCharacterSet characterSet expression++            renderDoc h doc++    let writeDocToFile :: FilePath -> Doc ann -> IO ()+        writeDocToFile file doc = do+            let stream = Dhall.Pretty.layout (doc <> "\n")++            AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy stream)++    handle $ case mode of+        Version ->+            putStrLn dhallVersionString++        Default {..} -> do+            if version+                then do+                    putStrLn dhallVersionString+                    Exit.exitSuccess+                else return ()++            (expression, characterSet) <- getExpressionAndCharacterSet file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression++            inferredType <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            let alphaNormalizedExpression =+                    if alpha+                    then Dhall.Core.alphaNormalize normalizedExpression+                    else normalizedExpression++            let annotatedExpression =+                    if annotate+                        then Annot alphaNormalizedExpression inferredType+                        else alphaNormalizedExpression++            case output of+                StandardOutput -> render System.IO.stdout characterSet annotatedExpression++                OutputFile file_ ->+                    writeDocToFile+                        file_+                        (Dhall.Pretty.prettyCharacterSet characterSet annotatedExpression)++        Resolve { resolveMode = Just Dot, ..} -> do+            expression <- getExpression file++            (Dhall.Import.Types.Status { _graph, _stack }) <-+                State.execStateT (Dhall.Import.loadWith expression) (toStatus file) { _semanticCacheMode = semanticCacheMode }++            let (rootImport :| _) = _stack+                imports = rootImport : map parent _graph ++ map child _graph+                importIds = Data.Map.fromList (zip imports [Text.Dot.userNodeId i | i <- [0..]])++            let dotNode (i, nodeId) =+                    Text.Dot.userNode+                        nodeId+                        [ ("label", Data.Text.unpack $ pretty (convert i))+                        , ("shape", "box")+                        , ("style", "rounded")+                        ]+                  where+                    convert = noHeaders . Dhall.Import.chainedImport++            let dotEdge (Depends parent child) =+                    case (Data.Map.lookup parent importIds, Data.Map.lookup child importIds) of+                        (Just from, Just to) -> from .->. to+                        _                    -> pure ()++            let dot = do Text.Dot.attribute ("rankdir", "LR")+                         mapM_ dotNode (Data.Map.assocs importIds)+                         mapM_ dotEdge _graph++            putStr . ("strict " <>) . Text.Dot.showDot $ dot++        Resolve { resolveMode = Just ListImmediateDependencies, ..} -> do+            expression <- getExpression file++            mapM_ (print . Pretty.pretty . noHeaders) expression++        Resolve { resolveMode = Just ListTransitiveDependencies, ..} -> do+            expression <- getExpression file++            (Dhall.Import.Types.Status { _cache }) <-+                State.execStateT (Dhall.Import.loadWith expression) (toStatus file) { _semanticCacheMode = semanticCacheMode }++            mapM_ print+                 .   fmap ( Pretty.pretty+                          . noHeaders+                          . Dhall.Import.chainedImport+                          )+                 .   reverse+                 .   Dhall.Map.keys+                 $   _cache++        Resolve { resolveMode = Nothing, ..} -> do+            (expression, characterSet) <- getExpressionAndCharacterSet file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression++            render System.IO.stdout characterSet resolvedExpression++        Normalize {..} -> do+            (expression, characterSet) <- getExpressionAndCharacterSet file++            resolvedExpression <- Dhall.Import.assertNoImports expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            let alphaNormalizedExpression =+                    if alpha+                    then Dhall.Core.alphaNormalize normalizedExpression+                    else normalizedExpression++            render System.IO.stdout characterSet alphaNormalizedExpression++        Type {..} -> do+            (expression, characterSet) <- getExpressionAndCharacterSet file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression++            inferredType <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            if quiet+                then return ()+                else render System.IO.stdout characterSet inferredType++        Repl ->+            Dhall.Repl.repl+                (fromMaybe Unicode chosenCharacterSet) -- Default to Unicode if no characterSet specified+                explain++        Diff {..} -> do+            expression1 <- Dhall.inputExpr expr1++            expression2 <- Dhall.inputExpr expr2++            let diff = Dhall.Diff.diffNormalized expression1 expression2++            renderDoc System.IO.stdout (Dhall.Diff.doc diff)++            if Dhall.Diff.same diff+                then return ()+                else Exit.exitFailure++        Format {..} -> do+            when deprecatedInPlace $+                System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"++            Dhall.Format.format Dhall.Format.Format{..}++        Freeze {..} -> do+            when deprecatedInPlace $+                System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"++            let scope = if all_ then AllImports else OnlyRemoteImports++            let intent = if cache then Cache else Secure++            Dhall.Freeze.freeze outputMode transitivity inputs scope intent chosenCharacterSet censor++        Hash {..} -> do+            expression <- getExpression file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            let normalizedExpression =+                    Dhall.Core.alphaNormalize (Dhall.Core.normalize resolvedExpression)++            if cache+                then Dhall.Import.writeExpressionToSemanticCache normalizedExpression+                else return ()++            Data.Text.IO.putStrLn (Dhall.Import.hashExpressionToCode normalizedExpression)++        Lint { transitivity = transitivity0, ..} -> do+            when deprecatedInPlace $+                System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"++            handleMultipleChecksFailed "lint" "linted" go inputs+          where+            go input = do+                let directory = case input of+                        StandardInput  -> "."+                        InputFile file -> System.FilePath.takeDirectory file++                let status = Dhall.Import.emptyStatus directory++                (inputName, originalText, transitivity) <- case input of+                    InputFile file -> do+                        text <- Data.Text.IO.readFile file++                        return (file, text, transitivity0)+                    StandardInput -> do+                        text <- Data.Text.IO.getContents++                        return ("(input)", text, NonTransitive)++                (Header header, parsedExpression) <-+                    Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText++                let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet++                case transitivity of+                    Transitive ->+                        for_ parsedExpression $ \import_ -> do+                            maybeFilepath <- Dhall.Import.dependencyToFile status import_++                            for_ maybeFilepath $ \filepath ->+                                go (InputFile filepath)++                    NonTransitive ->+                        return ()++                let lintedExpression = Dhall.Lint.lint parsedExpression++                let doc =   Pretty.pretty header+                        <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression++                let stream = Dhall.Pretty.layout doc++                let modifiedText = Pretty.Text.renderStrict stream <> "\n"++                case outputMode of+                    Write -> do+                        case input of+                            InputFile file ->+                                if originalText == modifiedText+                                    then return ()+                                    else writeDocToFile file doc++                            StandardInput ->+                                renderDoc System.IO.stdout doc++                        return (Right ())++                    Check ->+                        return $+                            if originalText == modifiedText+                                then Right ()+                                else Left CheckFailed{..}++        Encode {..} -> do+            expression <- getExpression file++            let bytes = Dhall.Binary.encodeExpression (Dhall.Core.denote expression)++            if json+                then do+                    let decoder = Codec.CBOR.JSON.decodeValue False++                    (_, value) <- Dhall.Core.throws (Codec.CBOR.Read.deserialiseFromBytes decoder bytes)++                    let jsonBytes = Data.Aeson.Encode.Pretty.encodePretty value++                    Data.ByteString.Lazy.Char8.putStrLn jsonBytes++                else+                    Data.ByteString.Lazy.putStr bytes++        Decode {..} -> do+            bytes <-+                case file of+                    InputFile f   -> Data.ByteString.Lazy.readFile f+                    StandardInput -> Data.ByteString.Lazy.getContents++            expression <-+                if json+                    then do+                        value <- case Data.Aeson.eitherDecode' bytes of+                            Left  string -> fail string+                            Right value  -> return value++                        let encoding = Codec.CBOR.JSON.encodeValue value++                        let cborgBytes = Codec.CBOR.Write.toLazyByteString encoding++                        Dhall.Core.throws (Dhall.Binary.decodeExpression cborgBytes)+                    else+                        Dhall.Core.throws (Dhall.Binary.decodeExpression bytes)+++            if quiet+                then return ()+                else do+                    let doc =+                            Dhall.Pretty.prettyCharacterSet+                                (fromMaybe Unicode chosenCharacterSet) -- default to Unicode+                                (Dhall.Core.renote expression :: Expr Src Import)++                    renderDoc System.IO.stdout doc++        Text {..} -> do+            expression <- getExpression file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf (Annot resolvedExpression Dhall.Core.Text))++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            case normalizedExpression of+                Dhall.Core.TextLit (Dhall.Core.Chunks [] text) ->+                    let write = case output of+                          StandardOutput -> Data.Text.IO.putStr+                          OutputFile file_ -> Data.Text.IO.writeFile file_+                    in write text+                _ -> do+                    let invalidDecoderExpected :: Expr Void Void+                        invalidDecoderExpected = Dhall.Core.Text++                    let invalidDecoderExpression :: Expr Void Void+                        invalidDecoderExpression = normalizedExpression++                    Control.Exception.throwIO (Dhall.InvalidDecoder {..})++        Tags {..} -> do+            tags <- Dhall.Tags.generate input suffixes followSymlinks++            case output of+                OutputFile file ->+                    System.IO.withFile file System.IO.WriteMode (`Data.Text.IO.hPutStr` tags)++                StandardOutput -> Data.Text.IO.putStrLn tags++        DirectoryTree {..} -> do+            expression <- getExpression file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            DirectoryTree.toDirectoryTree allowSeparators path normalizedExpression++        Dhall.Main.Schemas{..} ->+            Dhall.Schemas.schemasCommand Dhall.Schemas.Schemas{ input = file, ..}++        SyntaxTree {..} -> do+            expression <- getExpression file++            if noted then+                Text.Pretty.Simple.pPrintNoColor expression+            else+                let denoted :: Expr Void Import+                    denoted = Dhall.Core.denote expression+                in Text.Pretty.Simple.pPrintNoColor denoted++        Package {..} -> do+            let options = appEndo+                    (maybe mempty (Endo . set Dhall.Package.characterSet) chosenCharacterSet+                    <> packageOptions+                    ) Dhall.Package.defaultOptions+            writePackage options packageFiles++-- | Entry point for the @dhall@ executable+main :: IO ()+main = do+    options <- Options.Applicative.execParser parserInfoOptions++    Dhall.Main.command options
+ src/Dhall/Map.hs view
@@ -0,0 +1,742 @@+{-# LANGUAGE DeriveAnyClass        #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE DeriveLift            #-}+{-# LANGUAGE ExplicitForAll        #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}++-- | `Map` type used to represent records and unions++module Dhall.Map+    ( -- * Type+      Map++      -- * Construction+    , empty+    , singleton+    , fromList+    , fromListWithKey+    , fromMap++      -- * Constructing unordered 'Map's+    , unorderedSingleton+    , unorderedFromList++      -- * Sorting+    , sort+    , isSorted++      -- * Insertion+    , insert+    , insertWith++      -- * Deletion/Update+    , delete+    , filter+    , partition+    , restrictKeys+    , withoutKeys+    , mapMaybe++      -- * Query+    , lookup+    , member+    , uncons+    , size++      -- * Combine+    , union+    , unionWith+    , outerJoin+    , intersection+    , intersectionWith+    , difference++      -- * Traversals+    , mapWithKey+    , traverseWithKey+    , unorderedTraverseWithKey+    , unorderedTraverseWithKey_+    , foldMapWithKey++      -- * Conversions+    , toList+    , toAscList+    , toMap+    , keys+    , keysSet+    , elems+    ) where++import Control.Applicative        ((<|>))+import Control.DeepSeq            (NFData)+import Data.Data                  (Data)+import GHC.Generics               (Generic)+import Instances.TH.Lift          ()+import Language.Haskell.TH.Syntax (Lift)+import Prelude                    hiding (filter, lookup)++import qualified Data.Foldable.WithIndex    as Foldable.WithIndex+import qualified Data.Functor.WithIndex     as Functor.WithIndex+import qualified Data.List+import qualified Data.Map.Strict+import qualified Data.Set+import qualified Data.Traversable.WithIndex as Traversable.WithIndex+import qualified GHC.Exts+import qualified Prelude++{-| A `Map` that remembers the original ordering of keys++    This is primarily used so that formatting preserves field order++    This is done primarily to avoid a dependency on @insert-ordered-containers@+    and also to improve performance+-}+data Map k v = Map (Data.Map.Strict.Map k v) (Keys k)+    deriving (Data, Generic, Lift, NFData)++data Keys a+    = Sorted+    | Original [a]+    deriving (Data, Generic, Lift, NFData)++instance (Ord k, Eq v) => Eq (Map k v) where+  m1 == m2 =+      Data.Map.Strict.size (toMap m1) == Data.Map.Strict.size (toMap m2)+      && toList m1 == toList m2+  {-# INLINABLE (==) #-}++{-|+>>> fromList [("A",1),("B",2)] < fromList [("B",1),("A",0)]+True+-}+instance (Ord k, Ord v) => Ord (Map k v) where+  compare m1 m2 = compare (toList m1) (toList m2)+  {-# INLINABLE compare #-}++instance Functor (Map k) where+  fmap f (Map m ks) = Map (fmap f m) ks+  {-# INLINABLE fmap #-}++instance Ord k => Foldable (Map k) where+  foldr f z (Map m Sorted) = foldr f z m+  foldr f z m              = foldr f z (elems m)+  {-# INLINABLE foldr #-}++  length m = size m+  {-# INLINABLE length #-}++  null (Map m _) = null m+  {-# INLINABLE null #-}++instance Ord k => Traversable (Map k) where+  traverse f m = traverseWithKey (\_ v -> f v) m+  {-# INLINABLE traverse #-}++{-|+prop> \x y z -> x <> (y <> z) == (x <> y) <> (z :: Map Int Int)+-}+instance Ord k => Semigroup (Map k v) where+    (<>) = union+    {-# INLINABLE (<>) #-}++{-|+prop> \x -> x <> mempty == (x :: Map Int Int)+prop> \x -> mempty <> x == (x :: Map Int Int)+-}+instance Ord k => Monoid (Map k v) where+    mempty = Map Data.Map.Strict.empty (Original [])+    {-# INLINABLE mempty #-}++instance (Show k, Show v, Ord k) => Show (Map k v) where+    showsPrec d m =+        showParen (d > 10) (showString "fromList " . showsPrec 11 kvs)+      where+        kvs = toList m++instance Ord k => GHC.Exts.IsList (Map k v) where+    type Item (Map k v) = (k, v)++    fromList = Dhall.Map.fromList++    toList = Dhall.Map.toList++instance Ord k => Foldable.WithIndex.FoldableWithIndex k (Map k) where+    ifoldMap = foldMapWithKey+    {-# INLINABLE ifoldMap #-}++instance Functor.WithIndex.FunctorWithIndex k (Map k) where+    imap = mapWithKey+    {-# INLINABLE imap #-}++instance Ord k => Traversable.WithIndex.TraversableWithIndex k (Map k) where+    itraverse = traverseWithKey+    {-# INLINABLE itraverse #-}++-- | Create an empty `Map`+empty :: Ord k => Map k v+empty = mempty++{-| Create a `Map` from a single key-value pair++>>> singleton "A" 1+fromList [("A",1)]+-}+singleton :: k -> v -> Map k v+singleton k v = Map m ks+  where+    m = Data.Map.Strict.singleton k v++    ks = Original [k]+{-# INLINABLE singleton #-}++{-| Create a `Map` from a list of key-value pairs++>>> fromList [("B",1),("A",2)]  -- The map preserves order+fromList [("B",1),("A",2)]+>>> fromList [("A",1),("A",2)]  -- For duplicates, later values take precedence+fromList [("A",2)]++Note that this handling of duplicates means that 'fromList' is /not/ a monoid+homomorphism:++>>> fromList [(1, True)] <> fromList [(1, False)]+fromList [(1,True)]+>>> fromList ([(1, True)] <> [(1, False)])+fromList [(1,False)]++-}+fromList :: Ord k => [(k, v)] -> Map k v+fromList kvs = Map m ks+  where+    m = Data.Map.Strict.fromList kvs++    ks = Original (nubOrd (map fst kvs))+{-# INLINABLE fromList #-}++{-| Create a `Map` from a list of key-value pairs with a combining function.++>>> fromListWithKey (\k v1 v2 -> k ++ v1 ++ v2) [("B","v1"),("A","v2"),("B","v3")]+fromList [("B","Bv3v1"),("A","v2")]+-}+fromListWithKey :: Ord k => (k -> v -> v -> v) -> [(k, v)] -> Map k v+fromListWithKey f kvs = Map m ks+  where+    m = Data.Map.Strict.fromListWithKey f kvs++    ks = Original (nubOrd (map fst kvs))+{-# INLINABLE fromListWithKey #-}++-- | Create a `Map` from a @"Data.Map.Strict".`Data.Map.Strict.Map`@+fromMap :: Data.Map.Strict.Map k v -> Map k v+fromMap m = Map m Sorted++{-| Remove duplicates from a  list++>>> nubOrd [1,2,3]+[1,2,3]+>>> nubOrd [1,1,3]+[1,3]+-}+nubOrd :: Ord k => [k] -> [k]+nubOrd = go Data.Set.empty+  where+    go _      []  = []+    go set (k:ks)+        | Data.Set.member k set =     go                    set  ks+        | otherwise             = k : go (Data.Set.insert k set) ks+{-# INLINABLE nubOrd #-}++{-| Create a `Map` from a single key-value pair.++    Any further operations on this map will not retain the order of the keys.++>>> unorderedSingleton "A" 1+fromList [("A",1)]+-}+unorderedSingleton :: k -> v -> Map k v+unorderedSingleton k v = Map m Sorted+  where+    m = Data.Map.Strict.singleton k v+{-# INLINABLE unorderedSingleton #-}++{-| Create a `Map` from a list of key-value pairs++    Any further operations on this map will not retain the order of the keys.++>>> unorderedFromList []+fromList []+>>> unorderedFromList [("B",1),("A",2)]  -- The map /doesn't/ preserve order+fromList [("A",2),("B",1)]+>>> unorderedFromList [("A",1),("A",2)]  -- For duplicates, later values take precedence+fromList [("A",2)]+-}+unorderedFromList :: Ord k => [(k, v)] -> Map k v+unorderedFromList kvs = Map m Sorted+  where+    m = Data.Map.Strict.fromList kvs+{-# INLINABLE unorderedFromList #-}++{-| Sort the keys of a `Map`, forgetting the original ordering++> sort (sort x) = sort x++>>> sort (fromList [("B",1),("A",2)])+fromList [("A",2),("B",1)]+-}+sort :: Map k v -> Map k v+sort (Map m _) = Map m Sorted+{-# INLINABLE sort #-}++{-| Check if the keys of a `Map` are already sorted++> isSorted (sort m) = True++>>> isSorted (fromList [("B",1),("A",2)])  -- Sortedness is based only on keys+False+>>> isSorted (fromList [("A",2),("B",1)])+True+-}+isSorted :: Eq k => Map k v -> Bool+isSorted (Map _ Sorted)        = True+isSorted (Map m (Original ks)) = Data.Map.Strict.keys m == ks -- Or shortcut to False here?+{-# INLINABLE isSorted #-}++{-| Insert a key-value pair into a `Map`, overriding any previous value stored+    underneath the same key, if present++> insert = insertWith (\v _ -> v)++>>> insert "C" 1 (fromList [("B",2),("A",3)])  -- Values are inserted on left+fromList [("C",1),("B",2),("A",3)]+>>> insert "C" 1 (fromList [("C",2),("A",3)])  -- New value takes precedence+fromList [("C",1),("A",3)]+-}+insert :: Ord k => k -> v -> Map k v -> Map k v+insert k v (Map m Sorted)        = Map (Data.Map.Strict.insert k v m) Sorted+insert k v (Map m (Original ks)) = Map m' (Original ks')+  where+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new _old -> new) k v m++    ks' | Just _ <- mayOldV = ks+        | otherwise         = k : ks+{-# INLINABLE insert #-}++{-| Insert a key-value pair into a `Map`, using the supplied function to combine+    the new value with any old value underneath the same key, if present++>>> insertWith (+) "C" 1 (fromList [("B",2),("A",3)])  -- No collision+fromList [("C",1),("B",2),("A",3)]+>>> insertWith (+) "C" 1 (fromList [("C",2),("A",3)])  -- Collision+fromList [("C",3),("A",3)]+-}+insertWith :: Ord k => (v -> v -> v) -> k -> v -> Map k v -> Map k v+insertWith f k v (Map m Sorted)        = Map (Data.Map.Strict.insertWith f k v m) Sorted+insertWith f k v (Map m (Original ks)) = Map m' (Original ks')+  where+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new old -> f new old) k v m++    ks' | Just _ <- mayOldV = ks+        | otherwise         = k : ks+{-# INLINABLE insertWith #-}++{-| Delete a key from a `Map` if present, otherwise return the original `Map`++>>> delete "B" (fromList [("C",1),("B",2),("A",3)])+fromList [("C",1),("A",3)]+>>> delete "D" (fromList [("C",1),("B",2),("A",3)])+fromList [("C",1),("B",2),("A",3)]+-}+delete :: Ord k => k -> Map k v -> Map k v+delete k (Map m ks) = Map m' ks'+  where+    m' = Data.Map.Strict.delete k m++    ks' = case ks of+        Sorted        -> Sorted+        Original ks'' -> Original (Data.List.delete k ks'')+{-# INLINABLE delete #-}++{-| Keep all values that satisfy the given predicate++>>> filter even (fromList [("C",3),("B",2),("A",1)])+fromList [("B",2)]+>>> filter odd (fromList [("C",3),("B",2),("A",1)])+fromList [("C",3),("A",1)]+-}+filter :: Ord k => (a -> Bool) -> Map k a -> Map k a+filter predicate (Map m ks) = Map m' ks'+  where+    m' = Data.Map.Strict.filter predicate m++    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks+{-# INLINABLE filter #-}++{-| Split the map into values that do and don't satisfy the predicate++>>> partition even (fromList [("C",3),("B",2),("A",1)])+(fromList [("B",2)],fromList [("C",3),("A",1)])+>>> partition odd (fromList [("C",3),("B",2),("A",1)])+(fromList [("C",3),("A",1)],fromList [("B",2)])+-}+partition :: Ord k => (a -> Bool) -> Map k a -> (Map k a, Map k a)+partition predicate (Map m ks) = (Map mpass kpass, Map mfail kfail)+  where+    (mpass, mfail) = Data.Map.Strict.partition predicate m++    (kpass, kfail) = partitionKeys (\k -> Data.Map.Strict.member k mpass) ks+{-# INLINABLE partition #-}++{-| Restrict a 'Map' to only those keys found in a @"Data.Set".'Data.Set.Set'@.++>>> restrictKeys (fromList [("A",1),("B",2)]) (Data.Set.fromList ["A"])+fromList [("A",1)]+-}+restrictKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a+restrictKeys (Map m ks) s = Map m' ks'+  where+    m' = Data.Map.Strict.restrictKeys m s++    ks' = filterKeys (\k -> Data.Set.member k s) ks+{-# INLINABLE restrictKeys #-}++{-| Remove all keys in a @"Data.Set".'Data.Set.Set'@ from a 'Map'++>>> withoutKeys (fromList [("A",1),("B",2)]) (Data.Set.fromList ["A"])+fromList [("B",2)]+-}+withoutKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a+withoutKeys (Map m ks) s = Map m' ks'+  where+    m' = Data.Map.Strict.withoutKeys m s++    ks' = filterKeys (\k -> Data.Set.notMember k s) ks+{-# INLINABLE withoutKeys #-}++{-| Transform all values in a `Map` using the supplied function, deleting the+    key if the function returns `Nothing`++>>> mapMaybe Data.Maybe.listToMaybe (fromList [("C",[1]),("B",[]),("A",[3])])+fromList [("C",1),("A",3)]+-}+mapMaybe :: Ord k => (a -> Maybe b) -> Map k a -> Map k b+mapMaybe f (Map m ks) = Map m' ks'+  where+    m' = Data.Map.Strict.mapMaybe f m++    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks+{-# INLINABLE mapMaybe #-}++{-| Retrieve a key from a `Map`++> lookup k mempty = empty+>+> lookup k (x <> y) = lookup k y <|> lookup k x++>>> lookup "A" (fromList [("B",1),("A",2)])+Just 2+>>> lookup "C" (fromList [("B",1),("A",2)])+Nothing+-}+lookup :: Ord k => k -> Map k v -> Maybe v+lookup k (Map m _) = Data.Map.Strict.lookup k m+{-# INLINABLE lookup #-}++{-| Retrieve the first key, value of the 'Map', if present,+    and also returning the rest of the 'Map'.++> uncons mempty = empty+>+> uncons (singleton k v) = (k, v, mempty)++>>> uncons (fromList [("C",1),("B",2),("A",3)])+Just ("C",1,fromList [("B",2),("A",3)])+>>> uncons (fromList [])+Nothing+-}+uncons :: Ord k => Map k v -> Maybe (k, v, Map k v)+uncons (Map _ (Original []))     = Nothing+uncons (Map m (Original (k:ks))) =+    Just (k, m Data.Map.Strict.! k, Map (Data.Map.Strict.delete k m) (Original ks))+uncons (Map m Sorted)+  | Just ((k, v), m') <- Data.Map.Strict.minViewWithKey m = Just (k, v, Map m' Sorted)+  | otherwise                                      = Nothing+{-# INLINABLE uncons #-}++{-| Check if a key belongs to a `Map`++> member k mempty = False+>+> member k (x <> y) = member k x || member k y++>>> member "A" (fromList [("B",1),("A",2)])+True+>>> member "C" (fromList [("B",1),("A",2)])+False+-}+member :: Ord k => k -> Map k v -> Bool+member k (Map m _) = Data.Map.Strict.member k m+{-# INLINABLE member #-}++{-|+>>> size (fromList [("A",1)])+1+-}+size :: Map k v -> Int+size (Map m _) = Data.Map.Strict.size m+{-# INLINABLE size #-}++{-| Combine two `Map`s, preferring keys from the first `Map`++> union = unionWith (\v _ -> v)++>>> union (fromList [("D",1),("C",2)]) (fromList [("B",3),("A",4)])+fromList [("D",1),("C",2),("B",3),("A",4)]+>>> union (fromList [("D",1),("C",2)]) (fromList [("C",3),("A",4)])+fromList [("D",1),("C",2),("A",4)]+-}+union :: Ord k => Map k v -> Map k v -> Map k v+union (Map mL ksL) (Map mR ksR) = Map m ks+  where+    m = Data.Map.Strict.union mL mR++    ks = case (ksL, ksR) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r+        _                        -> Sorted+{-# INLINABLE union #-}++{-| Combine two `Map`s using a combining function for colliding keys++>>> unionWith (+) (fromList [("D",1),("C",2)]) (fromList [("B",3),("A",4)])+fromList [("D",1),("C",2),("B",3),("A",4)]+>>> unionWith (+) (fromList [("D",1),("C",2)]) (fromList [("C",3),("A",4)])+fromList [("D",1),("C",5),("A",4)]+-}+unionWith :: Ord k => (v -> v -> v) -> Map k v -> Map k v -> Map k v+unionWith combine (Map mL ksL) (Map mR ksR) = Map m ks+  where+    m = Data.Map.Strict.unionWith combine mL mR++    ks = case (ksL, ksR) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r+        _                        -> Sorted+{-# INLINABLE unionWith #-}++{-| A generalised 'unionWith'.++>>> outerJoin Left Left (\k a b -> Right (k, a, b)) (fromList [("A",1),("B",2)]) (singleton "A" 3)+fromList [("A",Right ("A",1,3)),("B",Left 2)]++This function is much inspired by the "Data.Semialign.Semialign" class.+-}+outerJoin+    :: Ord k+    => (a -> c)+    -> (b -> c)+    -> (k -> a -> b -> c)+    -> Map k a+    -> Map k b+    -> Map k c+outerJoin fa fb fab (Map ma ksA) (Map mb ksB) = Map m ks+  where+    m = Data.Map.Strict.mergeWithKey+            (\k a b -> Just (fab k a b))+            (fmap fa)+            (fmap fb)+            ma+            mb++    ks = case (ksA, ksB) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k ma) r+        _                        -> Sorted+{-# INLINABLE outerJoin #-}++{-| Combine two `Map` on their shared keys, keeping the value from the first+    `Map`++> intersection = intersectionWith (\v _ -> v)++>>> intersection (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)])+fromList [("B",2)]+-}+intersection :: Ord k => Map k a -> Map k b -> Map k a+intersection (Map mL ksL) (Map mR _) = Map m ks+  where+    m = Data.Map.Strict.intersection mL mR++    -- Or forget order unless both maps are ordered?!+    ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL+{-# INLINABLE intersection #-}++{-| Combine two `Map`s on their shared keys, using the supplied function to+    combine values from the first and second `Map`++>>> intersectionWith (+) (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)])+fromList [("B",5)]+-}+intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c+intersectionWith combine (Map mL ksL) (Map mR _) = Map m ks+  where+    m = Data.Map.Strict.intersectionWith combine mL mR++    -- Or forget order unless both maps are ordered?!+    ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL+{-# INLINABLE intersectionWith #-}++{-| Compute the difference of two `Map`s by subtracting all keys from the+    second `Map` from the first `Map`++>>> difference (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)])+fromList [("C",1)]+-}+difference :: Ord k => Map k a -> Map k b -> Map k a+difference (Map mL ksL) (Map mR _) = Map m ks+  where+    m = Data.Map.Strict.difference mL mR++    ks = filterKeys (\k -> Data.Map.Strict.notMember k mR) ksL+{-# INLINABLE difference #-}++{-| Fold all of the key-value pairs in a `Map`, in their original order++>>> foldMapWithKey (,) (fromList [("B",[1]),("A",[2])])+("BA",[1,2])+-}+foldMapWithKey :: (Monoid m, Ord k) => (k -> a -> m) -> Map k a -> m+foldMapWithKey f (Map m Sorted) = Data.Map.Strict.foldMapWithKey f m+foldMapWithKey f m              = foldMap (uncurry f) (toList m)+{-# INLINABLE foldMapWithKey #-}++{-| Transform the values of a `Map` using their corresponding key++> mapWithKey (pure id) = id+>+> mapWithKey (liftA2 (.) f g) = mapWithKey f . mapWithKey g++> mapWithKey f mempty = mempty+>+> mapWithKey f (x <> y) = mapWithKey f x <> mapWithKey f y++>>> mapWithKey (,) (fromList [("B",1),("A",2)])+fromList [("B",("B",1)),("A",("A",2))]+-}+mapWithKey :: (k -> a -> b) -> Map k a -> Map k b+mapWithKey f (Map m ks) = Map m' ks+  where+    m' = Data.Map.Strict.mapWithKey f m+{-# INLINABLE mapWithKey #-}++{-| Traverse all of the key-value pairs in a `Map`, in their original order++>>> traverseWithKey (,) (fromList [("B",1),("A",2)])+("BA",fromList [("B",1),("A",2)])+-}+traverseWithKey+    :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b)+traverseWithKey f (Map m Sorted) =+    fmap (\m' -> Map m' Sorted) (Data.Map.Strict.traverseWithKey f m)+traverseWithKey f m@(Map _ ks) =+    flip Map ks . Data.Map.Strict.fromList <$> traverse f' (toList m)+  where+    f' (k, a) = fmap ((,) k) (f k a)+{-# INLINABLE traverseWithKey #-}++{-| Same as `traverseWithKey`, except that the order of effects is not+    necessarily the same as the order of the keys+-}+unorderedTraverseWithKey+    :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b)+unorderedTraverseWithKey f (Map m ks) =+    fmap (\m' -> Map m' ks) (Data.Map.Strict.traverseWithKey f m)+{-# INLINABLE unorderedTraverseWithKey #-}++{-| Traverse all of the key-value pairs in a 'Map', not preserving their+    original order, where the result of the computation can be forgotten.++    Note that this is a strict traversal, fully traversing the map even+    when the Applicative is lazy in the remaining elements.+-}+unorderedTraverseWithKey_+    :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f ()+unorderedTraverseWithKey_ f (Map m _) =+    Data.Map.Strict.foldlWithKey' (\acc k v -> acc *> f k v) (pure ()) m+{-# INLINABLE unorderedTraverseWithKey_ #-}++{-| Convert a `Map` to a list of key-value pairs in the original order of keys++>>> toList (fromList [("B",1),("A",2)])+[("B",1),("A",2)]+-}+toList :: Ord k => Map k v -> [(k, v)]+toList (Map m Sorted)        = Data.Map.Strict.toList m+toList (Map m (Original ks)) = fmap (\k -> (k, m Data.Map.Strict.! k)) ks+{-# INLINABLE toList #-}++{-| Convert a `Map` to a list of key-value pairs in ascending order of keys+-}+toAscList :: Map k v -> [(k, v)]+toAscList (Map m _) = Data.Map.Strict.toAscList m+{-# INLINABLE toAscList #-}++{-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map.Strict".`Data.Map.Strict.Map`@++>>> toMap (fromList [("B",1),("A",2)]) -- Order is lost upon conversion+fromList [("A",2),("B",1)]+-}+toMap :: Map k v -> Data.Map.Strict.Map k v+toMap (Map m _) = m+{-# INLINABLE toMap #-}++{-| Return the keys from a `Map` in their original order++>>> keys (fromList [("B",1),("A",2)])+["B","A"]+-}+keys :: Map k v -> [k]+keys (Map m Sorted)        = Data.Map.Strict.keys m+keys (Map _ (Original ks)) = ks+{-# INLINABLE keys #-}++{-| Return the values from a `Map` in their original order.++>>> elems (fromList [("B",1),("A",2)])+[1,2]+-}+elems :: Ord k => Map k v -> [v]+elems (Map m Sorted)        = Data.Map.Strict.elems m+elems (Map m (Original ks)) = fmap (\k -> m Data.Map.Strict.! k) ks+{-# INLINABLE elems #-}++{-| Return the @"Data.Set".'Data.Set.Set'@ of the keys++>>> keysSet (fromList [("B",1),("A",2)])+fromList ["A","B"]+-}+keysSet :: Map k v -> Data.Set.Set k+keysSet (Map m _) = Data.Map.Strict.keysSet m+{-# INLINABLE keysSet #-}++filterKeys :: (a -> Bool) -> Keys a -> Keys a+filterKeys _ Sorted        = Sorted+filterKeys f (Original ks) = Original (Prelude.filter f ks)+{-# INLINABLE filterKeys #-}++partitionKeys :: (a -> Bool) -> Keys a -> (Keys a, Keys a)+partitionKeys _ Sorted        = (Sorted, Sorted)+partitionKeys f (Original ks) =+    let (kpass, kfail) = Data.List.partition f ks+    in (Original kpass, Original kfail)+{-# INLINABLE partitionKeys #-}++{- $setup+>>> import Test.QuickCheck (Arbitrary(..), oneof)+>>> :{+  instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where+    arbitrary = oneof [fromList <$> arbitrary, unorderedFromList <$> arbitrary]+:}+-}
+ src/Dhall/Marshal/Decode.hs view
@@ -0,0 +1,1712 @@+{-# LANGUAGE ApplicativeDo              #-}+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DerivingStrategies         #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE NamedFieldPuns             #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE PolyKinds                  #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ViewPatterns               #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Decode+    ( -- * General+      Decoder (..)+    , FromDhall(..)+    , Interpret+    , auto++      -- * Building decoders+      -- ** Simple decoders+    , bool+    , unit+    , void+      -- ** Numbers+    , natural+    , word+    , word8+    , word16+    , word32+    , word64+    , integer+    , int+    , int8+    , int16+    , int32+    , int64+    , scientific+    , double+      -- ** Bytes+    , lazyBytes+    , strictBytes+    , shortBytes+      -- ** Textual+    , string+    , lazyText+    , strictText+    , shortText+      -- ** Time+    , timeOfDay+    , day+    , timeZone+    , localTime+    , zonedTime+    , utcTime+    , dayOfWeek+      -- ** Containers+    , maybe+    , pair+    , sequence+    , list+    , vector+    , setFromDistinctList+    , setIgnoringDuplicates+    , hashSetFromDistinctList+    , hashSetIgnoringDuplicates+    , Dhall.Marshal.Decode.map+    , hashMap+    , pairFromMapEntry+      -- ** Functions+    , function+    , functionWith+      -- ** Records+    , RecordDecoder(..)+    , record+    , field+      -- ** Unions+    , UnionDecoder(..)+    , union+    , constructor++      -- * Generic decoding+    , GenericFromDhall(..)+    , GenericFromDhallUnion(..)+    , genericAuto+    , genericAutoWith+    , genericAutoWithInputNormalizer++    -- * Decoding errors+    , DhallErrors(..)+    , showDhallErrors+    , InvalidDecoder(..)+    -- ** Extraction errors+    , ExtractErrors+    , ExtractError(..)+    , Extractor+    , typeError+    , extractError+    , MonadicExtractor+    , toMonadic+    , fromMonadic+    -- ** Typing errors+    , ExpectedTypeErrors+    , ExpectedTypeError(..)+    , Expector++    -- * Miscellaneous+    , InputNormalizer(..)+    , defaultInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions+    , Result++    -- * Re-exports+    , Natural+    , Seq+    , Text+    , Vector+    , Generic+    ) where+++import Control.Applicative              (empty, liftA2)+import Control.Exception                (Exception)+import Control.Monad                    (guard)+import Control.Monad.Trans.State.Strict+import Data.Coerce                      (coerce)+import Data.Either.Validation+    ( Validation (..)+    , eitherToValidation+    , validationToEither+    )+import Data.Functor.Contravariant+    ( Equivalence (..)+    , Op (..)+    , Predicate (..)+    )+import Data.Functor.Identity            (Identity (..))+import Data.Hashable                    (Hashable)+import Data.List.NonEmpty               (NonEmpty (..))+import Data.Typeable                    (Proxy (..), Typeable)+import Dhall.Parser                     (Src (..))+import Dhall.Syntax+    ( Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    , FieldSelection (..)+    , FunctionBinding (..)+    , Var (..)+    )+import GHC.Generics+import Prelude                          hiding (maybe, sequence)+import Prettyprinter                    (Pretty)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Foldable+import qualified Data.Functor.Compose+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.HashSet+import qualified Data.List             as List+import qualified Data.List.NonEmpty+import qualified Data.Map+import qualified Data.Maybe+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time             as Time+import qualified Data.Vector+import qualified Dhall.Core            as Core+import qualified Dhall.Map+import qualified Dhall.Util++import Dhall.Marshal.Encode+import Dhall.Marshal.Internal++-- $setup+-- >>> import Dhall (input)++{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall+    into Haskell.++    You can produce `Decoder`s either explicitly:++> example :: Decoder (Vector Text)+> example = vector text++    ... or implicitly using `auto`:++> example :: Decoder (Vector Text)+> example = auto++    You can consume `Decoder`s using the `Dhall.input` function:++> input :: Decoder a -> Text -> IO a+-}+data Decoder a = Decoder+    { extract  :: Expr Src Void -> Extractor Src Void a+    -- ^ Extracts Haskell value from the Dhall expression+    , expected :: Expector (Expr Src Void)+    -- ^ Dhall type of the Haskell value+    }+    deriving (Functor)++{-| Any value that implements `FromDhall` can be automatically decoded based on+    the inferred return type of `Dhall.input`.++>>> input auto "[1, 2, 3]" :: IO (Vector Natural)+[1,2,3]+>>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)+fromList [("a",False),("b",True)]++    This class auto-generates a default implementation for types that+    implement `Generic`.  This does not auto-generate an instance for recursive+    types.++    The default instance can be tweaked using 'genericAutoWith'/'genericAutoWithInputNormalizer'+    and custom 'InterpretOptions', or using+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class FromDhall a where+    autoWith :: InputNormalizer -> Decoder a+    default autoWith+        :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a+    autoWith _ = genericAuto++-- | A compatibility alias for `FromDhall`.+type Interpret = FromDhall+{-# DEPRECATED Interpret "Use FromDhall instead" #-}++{-| Use the default input normalizer for interpreting an input.++> auto = autoWith defaultInputNormalizer+-}+auto :: FromDhall a => Decoder a+auto = autoWith defaultInputNormalizer++++instance FromDhall Void where+    autoWith _ = void++instance FromDhall () where+    autoWith _ = unit++instance FromDhall Bool where+    autoWith _ = bool++instance FromDhall Natural where+    autoWith _ = natural++instance FromDhall Word where+    autoWith _ = word++instance FromDhall Word8 where+    autoWith _ = word8++instance FromDhall Word16 where+    autoWith _ = word16++instance FromDhall Word32 where+    autoWith _ = word32++instance FromDhall Word64 where+    autoWith _ = word64++instance FromDhall Integer where+    autoWith _ = integer++instance FromDhall Int where+    autoWith _ = int++instance FromDhall Int8 where+    autoWith _ = int8++instance FromDhall Int16 where+    autoWith _ = int16++instance FromDhall Int32 where+    autoWith _ = int32++instance FromDhall Int64 where+    autoWith _ = int64++instance FromDhall Scientific where+    autoWith _ = scientific++instance FromDhall Double where+    autoWith _ = double++instance FromDhall Data.ByteString.Short.ShortByteString where+    autoWith _ = shortBytes++instance FromDhall Data.ByteString.Lazy.ByteString where+    autoWith _ = lazyBytes++instance FromDhall Data.ByteString.ByteString where+    autoWith _ = strictBytes++instance {-# OVERLAPS #-} FromDhall [Char] where+    autoWith _ = string++instance FromDhall Data.Text.Short.ShortText where+    autoWith _ = shortText++instance FromDhall Data.Text.Lazy.Text where+    autoWith _ = lazyText++instance FromDhall Text where+    autoWith _ = strictText++instance FromDhall a => FromDhall (Identity a) where+    autoWith opts = Identity <$> autoWith opts++instance FromDhall a => FromDhall (Maybe a) where+    autoWith opts = maybe (autoWith opts)++instance FromDhall a => FromDhall (Seq a) where+    autoWith opts = sequence (autoWith opts)++instance FromDhall a => FromDhall [a] where+    autoWith opts = list (autoWith opts)++instance FromDhall a => FromDhall (Vector a) where+    autoWith opts = vector (autoWith opts)++instance FromDhall Time.TimeOfDay where+    autoWith _ = timeOfDay++instance FromDhall Time.Day where+    autoWith _ = day++instance FromDhall Time.TimeZone where+    autoWith _ = timeZone++instance FromDhall Time.LocalTime where+    autoWith _ = localTime++instance FromDhall Time.ZonedTime where+    autoWith _ = zonedTime++instance FromDhall Time.UTCTime where+    autoWith _ = utcTime++instance FromDhall Time.DayOfWeek where+    autoWith _ = dayOfWeek++{-| Note that this instance will throw errors in the presence of duplicates in+    the list. To ignore duplicates, use `setIgnoringDuplicates`.+-}+instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where+    autoWith opts = setFromDistinctList (autoWith opts)++{-| Note that this instance will throw errors in the presence of duplicates in+    the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.+-}+instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where+    autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)++instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where+    autoWith inputNormalizer = Dhall.Marshal.Decode.map (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where+    autoWith inputNormalizer = Dhall.Marshal.Decode.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where+    autoWith inputNormalizer =+        functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)++instance (FromDhall a, FromDhall b) => FromDhall (a, b)++instance FromDhall (f (Result f)) => FromDhall (Result f) where+    autoWith inputNormalizer = Decoder {..}+      where+        extract (App _ expr) =+            fmap Result (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)+        extract expr = typeError expected expr++        expected = pure "result"++deriving newtype instance (ToDhall x) => FromDhall (Predicate x)++deriving newtype instance (ToDhall x) => FromDhall (Equivalence x)++deriving newtype instance (FromDhall b, ToDhall x) => FromDhall (Op b x)++-- | You can use this instance to marshal recursive types from Dhall to Haskell.+--+-- Here is an example use of this instance:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveFoldable     #-}+-- > {-# LANGUAGE DeriveFunctor      #-}+-- > {-# LANGUAGE DeriveTraversable  #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE KindSignatures     #-}+-- > {-# LANGUAGE QuasiQuotes        #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TypeFamilies       #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > import Data.Fix (Fix(..))+-- > import Data.Text (Text)+-- > import Dhall (FromDhall)+-- > import GHC.Generics (Generic)+-- > import Numeric.Natural (Natural)+-- >+-- > import qualified Data.Fix                 as Fix+-- > import qualified Data.Functor.Foldable    as Foldable+-- > import qualified Data.Functor.Foldable.TH as TH+-- > import qualified Dhall+-- > import qualified NeatInterpolation+-- >+-- > data Expr+-- >     = Lit Natural+-- >     | Add Expr Expr+-- >     | Mul Expr Expr+-- >     deriving (Show)+-- >+-- > TH.makeBaseFunctor ''Expr+-- >+-- > deriving instance Generic (ExprF a)+-- > deriving instance FromDhall a => FromDhall (ExprF a)+-- >+-- > example :: Text+-- > example = [NeatInterpolation.text|+-- >     \(Expr : Type)+-- > ->  let ExprF =+-- >           < LitF :+-- >               Natural+-- >           | AddF :+-- >               { _1 : Expr, _2 : Expr }+-- >           | MulF :+-- >               { _1 : Expr, _2 : Expr }+-- >           >+-- >+-- >     in      \(Fix : ExprF -> Expr)+-- >         ->  let Lit = \(x : Natural) -> Fix (ExprF.LitF x)+-- >+-- >             let Add =+-- >                       \(x : Expr)+-- >                   ->  \(y : Expr)+-- >                   ->  Fix (ExprF.AddF { _1 = x, _2 = y })+-- >+-- >             let Mul =+-- >                       \(x : Expr)+-- >                   ->  \(y : Expr)+-- >                   ->  Fix (ExprF.MulF { _1 = x, _2 = y })+-- >+-- >             in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))+-- > |]+-- >+-- > convert :: Fix ExprF -> Expr+-- > convert = Fix.foldFix Foldable.embed+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)+-- >+-- >     print (convert x :: Expr)+instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where+    autoWith inputNormalizer = Decoder {..}+      where+        extract expr0 = extract0 expr0+          where+            die = typeError expected expr0++            extract0 (Lam _ (FunctionBinding { functionBindingVariable = x }) expr) =+                extract1 (rename x "result" expr)+            extract0  _             = die++            extract1 (Lam _ (FunctionBinding { functionBindingVariable = y }) expr) =+                extract2 (rename y "Make" expr)+            extract1  _             = die++            extract2 expr = fmap resultToFix (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)++            rename a b expr+                | a /= b    = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)+                | otherwise = expr++        expected = (\x -> Pi mempty "result" (Const Core.Type) (Pi mempty "Make" (Pi mempty "_" x "result") "result"))+            <$> Dhall.Marshal.Decode.expected (autoWith inputNormalizer :: Decoder (f (Result f)))++resultToFix :: Functor f => Result f -> Fix f+resultToFix (Result x) = Fix (fmap resultToFix x)++++{-| This is the underlying class that powers the `FromDhall` class's support+    for automatically deriving a generic implementation.+-}+class GenericFromDhall t f where+    genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))++instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where+    genericAutoWithNormalizer p inputNormalizer options = do+        res <- genericAutoWithNormalizer p inputNormalizer options+        pure (fmap M1 res)++instance GenericFromDhall t V1 where+    genericAutoWithNormalizer _ _ _ = pure Decoder {..}+      where+        extract expr = typeError expected expr++        expected = pure $ Union mempty++instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where+  genericAutoWithNormalizer p inputNormalizer options =+    pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))++instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where+    genericAutoWithNormalizer p inputNormalizer options = do+        res <- genericAutoWithNormalizer p inputNormalizer options+        pure (fmap M1 res)++instance GenericFromDhall t U1 where+    genericAutoWithNormalizer _ _ _ = pure (Decoder {..})+      where+        extract _ = pure U1++        expected = pure expected'++        expected' = Record (Dhall.Map.fromList [])++instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where+    genericAutoWithNormalizer p inputNormalizer options = do+        Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options+        Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++        let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL+        let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++        let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)++        let extract expression =+                liftA2 (:*:) (extractL expression) (extractR expression)++        return (Decoder {..})++instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where+    genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+        let nR :: M1 S s (K1 i a) r+            nR = undefined++        nameR <- fmap fieldModifier (getSelName nR)++        Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options++        let Decoder extractR expectedR = autoWith inputNormalizer++        let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL++        let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of+                            Just expressionR ->+                                liftA2 (:*:)+                                    (extractL expression)+                                    (fmap (M1 . K1) (extractR expressionR))+                            _ -> die+                    _ -> die++        return (Decoder {..})++instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where+    genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+        let nL :: M1 S s (K1 i a) r+            nL = undefined++        nameL <- fmap fieldModifier (getSelName nL)++        let Decoder extractL expectedL = autoWith inputNormalizer++        Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++        let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++        let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                            Just expressionL ->+                                liftA2 (:*:)+                                    (fmap (M1 . K1) (extractL expressionL))+                                    (extractR expression)+                            _ -> die+                    _ -> die++        return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+        let nL :: M1 S s1 (K1 i1 a1) r+            nL = undefined++        let nR :: M1 S s2 (K1 i2 a2) r+            nR = undefined++        nameL <- fmap fieldModifier (getSelName nL)+        nameR <- fmap fieldModifier (getSelName nR)++        let Decoder extractL expectedL = autoWith inputNormalizer+        let Decoder extractR expectedR = autoWith inputNormalizer++        let expected = do+                l <- Core.makeRecordField <$> expectedL+                r <- Core.makeRecordField <$> expectedR+                pure $ Record+                    (Dhall.Map.fromList+                        [ (nameL, l)+                        , (nameR, r)+                        ]+                    )++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of+                            Just (expressionL, expressionR) ->+                                liftA2 (:*:)+                                    (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))+                                    (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))+                            Nothing -> die+                    _ -> die++        return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where+    genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+        let n :: M1 S s (K1 i a) r+            n = undefined++        name <- fmap fieldModifier (getSelName n)++        let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer++        let expected =+                case singletonConstructors of+                    Bare ->+                        expected'+                    Smart | selName n == "" ->+                        expected'+                    _ ->+                        Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'++        let extract0 expression = fmap (M1 . K1) (extract' expression)++        let extract1 expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of+                            Just subExpression ->+                                fmap (M1 . K1) (extract' subExpression)+                            Nothing ->+                                die+                    _ -> die++        let extract =+                case singletonConstructors of+                    Bare                    -> extract0+                    Smart | selName n == "" -> extract0+                    _                       -> extract1++        return (Decoder {..})++{-| `genericAuto` is the default implementation for `auto` if you derive+    `FromDhall`.  The difference is that you can use `genericAuto` without+    having to explicitly provide a `FromDhall` instance for a type as long as+    the type derives `Generic`.+-}+genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a+genericAuto = genericAutoWith defaultInterpretOptions++{-| `genericAutoWith` is a configurable version of `genericAuto`.+-}+genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a+genericAutoWith options = genericAutoWithInputNormalizer options defaultInputNormalizer++{-| `genericAutoWithInputNormalizer` is like `genericAutoWith`, but instead of+    using the `defaultInputNormalizer` it expects an custom `InputNormalizer`.+-}+genericAutoWithInputNormalizer :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> InputNormalizer -> Decoder a+genericAutoWithInputNormalizer options inputNormalizer = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p inputNormalizer options) 1))+    where+        withProxy :: (Proxy a -> Decoder a) -> Decoder a+        withProxy f = f Proxy++extractUnionConstructor+    :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))+extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =+  return (fld, e, Dhall.Map.delete fld kts)+extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =+  return (fld, RecordLit mempty, Dhall.Map.delete fld kts)+extractUnionConstructor _ =+  empty++{-| This is the underlying class that powers the `FromDhall` class's support+    for automatically deriving a generic implementation for a union type.+-}+class GenericFromDhallUnion t f where+    genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)++instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where+  genericUnionAutoWithNormalizer p inputNormalizer options =+    (<>)+      (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)+      (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)++instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where+  genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =+    constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)+    where+      n :: M1 C c1 f1 a+      n = undefined++      name = constructorModifier (Data.Text.pack (conName n))++++{-| Decode a `Prelude.Bool`.++>>> input bool "True"+True+-}+bool :: Decoder Bool+bool = Decoder {..}+  where+    extract (BoolLit b) = pure b+    extract expr        = typeError expected expr++    expected = pure Bool++{-| Decode a `Prelude.Natural`.++>>> input natural "42"+42+-}+natural :: Decoder Natural+natural = Decoder {..}+  where+    extract (NaturalLit n) = pure n+    extract  expr          = typeError expected expr++    expected = pure Natural++{-| Decode an `Prelude.Integer`.++>>> input integer "+42"+42+-}+integer :: Decoder Integer+integer = Decoder {..}+  where+    extract (IntegerLit n) = pure n+    extract  expr          = typeError expected expr++    expected = pure Integer++wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+wordHelper name = Decoder {..}+  where+    extract (NaturalLit n)+        | toInteger n <= toInteger (maxBound @a) =+            pure (fromIntegral n)+        | otherwise =+            extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+    extract expr =+        typeError expected expr++    expected = pure Natural++{-| Decode a `Word` from a Dhall @Natural@.++>>> input word "42"+42+-}+word :: Decoder Word+word = wordHelper "Word"++{-| Decode a `Word8` from a Dhall @Natural@.++>>> input word8 "42"+42+-}+word8 :: Decoder Word8+word8 = wordHelper "Word8"++{-| Decode a `Word16` from a Dhall @Natural@.++>>> input word16 "42"+42+-}+word16 :: Decoder Word16+word16 = wordHelper "Word16"++{-| Decode a `Word32` from a Dhall @Natural@.++>>> input word32 "42"+42+-}+word32 :: Decoder Word32+word32 = wordHelper "Word32"++{-| Decode a `Word64` from a Dhall @Natural@.++>>> input word64 "42"+42+-}+word64 :: Decoder Word64+word64 = wordHelper "Word64"++intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+intHelper name = Decoder {..}+  where+    extract (IntegerLit n)+        | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =+            pure (fromIntegral n)+        | otherwise =+            extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+    extract expr =+        typeError expected expr++    expected = pure Integer++{-| Decode an `Int` from a Dhall @Integer@.++>>> input int "-42"+-42+-}+int :: Decoder Int+int = intHelper "Int"++{-| Decode an `Int8` from a Dhall @Integer@.++>>> input int8 "-42"+-42+-}+int8 :: Decoder Int8+int8 = intHelper "Int8"++{-| Decode an `Int16` from a Dhall @Integer@.++>>> input int16 "-42"+-42+-}+int16 :: Decoder Int16+int16 = intHelper "Int16"++{-| Decode an `Int32` from a Dhall @Integer@.++>>> input int32 "-42"+-42+-}+int32 :: Decoder Int32+int32 = intHelper "Int32"++{-| Decode an `Int64` from a Dhall @Integer@.++>>> input int64 "-42"+-42+-}+int64 :: Decoder Int64+int64 = intHelper "Int64"++{-| Decode a `Scientific`.++>>> input scientific "1e100"+1.0e100+-}+scientific :: Decoder Scientific+scientific = fmap Data.Scientific.fromFloatDigits double++{-| Decode a `Prelude.Double`.++>>> input double "42.0"+42.0+-}+double :: Decoder Double+double = Decoder {..}+  where+    extract (DoubleLit (DhallDouble n)) = pure n+    extract  expr                       = typeError expected expr++    expected = pure Double++{-| Decode a `Data.ByteString.Short.ShortByteString`++>>> input shortBytes "0x\"00FF\""+"\NUL\255"+-}+shortBytes :: Decoder Data.ByteString.Short.ShortByteString+shortBytes = fmap Data.ByteString.Short.toShort strictBytes++{-| Decode a lazy `Data.ByteString.Lazy.ByteString`.++>>> input lazyBytes "0x\"00FF\""+"\NUL\255"+-}+lazyBytes :: Decoder Data.ByteString.Lazy.ByteString+lazyBytes = fmap Data.ByteString.Lazy.fromStrict strictBytes++{-| Decode a strict `Data.ByteString.ByteString`++>>> input strictBytes "0x\"00FF\""+"\NUL\255"+-}+strictBytes :: Decoder Data.ByteString.ByteString+strictBytes = Decoder {..}+  where+    extract (BytesLit b) = pure b+    extract  expr        = typeError expected expr++    expected = pure Bytes++{-| Decode `Data.Text.Short.ShortText`.++>>> input shortText "\"Test\""+"Test"+-}+shortText :: Decoder Data.Text.Short.ShortText+shortText = fmap Data.Text.Short.fromText strictText++{-| Decode lazy `Data.Text.Lazy.Text`.++>>> input lazyText "\"Test\""+"Test"+-}+lazyText :: Decoder Data.Text.Lazy.Text+lazyText = fmap Data.Text.Lazy.fromStrict strictText++{-| Decode strict `Data.Text.Text`.++>>> input strictText "\"Test\""+"Test"+-}+strictText :: Decoder Text+strictText = Decoder {..}+  where+    extract (TextLit (Chunks [] t)) = pure t+    extract  expr                   = typeError expected expr++    expected = pure Text++{-| Decode `Time.TimeOfDay`++>>> input timeOfDay "00:00:00"+00:00:00+-}+timeOfDay :: Decoder Time.TimeOfDay+timeOfDay = Decoder {..}+  where+    extract (TimeLiteral t _) = pure t+    extract  expr             = typeError expected expr++    expected = pure Time++{-| Decode `Time.Day`++>>> input day "2000-01-01"+2000-01-01+-}+day :: Decoder Time.Day+day = Decoder {..}+  where+    extract (DateLiteral d) = pure d+    extract  expr           = typeError expected expr++    expected = pure Date++{-| Decode `Time.TimeZone`++>>> input timeZone "+00:00"++0000+-}+timeZone :: Decoder Time.TimeZone+timeZone = Decoder {..}+  where+    extract (TimeZoneLiteral z) = pure z+    extract  expr               = typeError expected expr++    expected = pure TimeZone++{-| Decode `Time.LocalTime`++>>> input localTime "2020-01-01T12:34:56"+2020-01-01 12:34:56+-}+localTime :: Decoder Time.LocalTime+localTime = record $+  Time.LocalTime+    <$> field "date" day+    <*> field "time" timeOfDay++{-| Decode `Time.ZonedTime`++>>> input zonedTime "2020-01-01T12:34:56+02:00"+2020-01-01 12:34:56 +0200+-}+zonedTime :: Decoder Time.ZonedTime+zonedTime = record $+  adapt+    <$> field "date" day+    <*> field "time" timeOfDay+    <*> field "timeZone" timeZone+  where+    adapt date time = Time.ZonedTime (Time.LocalTime date time)++{-| Decode `Time.UTCTime`++>>> input utcTime "2020-01-01T12:34:56+02:00"+2020-01-01 10:34:56 UTC+-}+utcTime :: Decoder Time.UTCTime+utcTime = Time.zonedTimeToUTC <$> zonedTime++{-| Decode `Time.DayOfWeek`++>>> input dayOfWeek "< Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday >.Monday"+Monday+-}+dayOfWeek :: Decoder Time.DayOfWeek+dayOfWeek = Decoder{..}+  where+    extract expr@(Field _ FieldSelection{ fieldSelectionLabel }) =+        case fieldSelectionLabel of+            "Sunday"    -> pure Time.Sunday+            "Monday"    -> pure Time.Monday+            "Tuesday"   -> pure Time.Tuesday+            "Wednesday" -> pure Time.Wednesday+            "Thursday"  -> pure Time.Thursday+            "Friday"    -> pure Time.Friday+            "Saturday"  -> pure Time.Saturday+            _           -> typeError expected expr+    extract expr =+        typeError expected expr++    expected =+        pure+            (Union+                (Dhall.Map.fromList+                    [ ("Sunday", Nothing)+                    , ("Monday", Nothing)+                    , ("Tuesday", Nothing)+                    , ("Wednesday", Nothing)+                    , ("Thursday", Nothing)+                    , ("Friday", Nothing)+                    , ("Saturday", Nothing)+                    ]+                )+            )++{-| Decode a `Maybe`.++>>> input (maybe natural) "Some 1"+Just 1+-}+maybe :: Decoder a -> Decoder (Maybe a)+maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (Some e    ) = fmap Just (extractIn e)+    extractOut (App None _) = pure Nothing+    extractOut expr         = typeError expectedOut expr++    expectedOut = App Optional <$> expectedIn++{-| Decode a `Seq`.++>>> input (sequence natural) "[1, 2, 3]"+fromList [1,2,3]+-}+sequence :: Decoder a -> Decoder (Seq a)+sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (ListLit _ es) = traverse extractIn es+    extractOut expr           = typeError expectedOut expr++    expectedOut = App List <$> expectedIn++{-| Decode a list.++>>> input (list natural) "[1, 2, 3]"+[1,2,3]+-}+list :: Decoder a -> Decoder [a]+list = fmap Data.Foldable.toList . sequence++{-| Decode a `Vector`.++>>> input (vector natural) "[1, 2, 3]"+[1,2,3]+-}+vector :: Decoder a -> Decoder (Vector a)+vector = fmap Data.Vector.fromList . list++{-| Decode a Dhall function into a Haskell function.++>>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+function+    :: Encoder a+    -> Decoder b+    -> Decoder (a -> b)+function = functionWith defaultInputNormalizer++{-| Decode a Dhall function into a Haskell function using the specified normalizer.++>>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+functionWith+    :: InputNormalizer+    -> Encoder a+    -> Decoder b+    -> Decoder (a -> b)+functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =+    Decoder extractOut expectedOut+  where+    normalizer_ = Just (getInputNormalizer inputNormalizer)++    extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of+        Success o  -> o+        Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )++    expectedOut = Pi mempty "_" declared <$> expectedIn++{-| Decode a `Data.Set.Set` from a `List`.++>>> input (setIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (setIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)+setIgnoringDuplicates = fmap Data.Set.fromList . list++{-| Decode a `Data.HashSet.HashSet` from a `List`.++>>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+hashSetIgnoringDuplicates :: (Hashable a, Ord a)+                          => Decoder a+                          -> Decoder (Data.HashSet.HashSet a)+hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list++{-| Decode a `Data.Set.Set` from a `List` with distinct elements.++>>> input (setFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (setFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)+setFromDistinctList = setHelper Data.Set.size Data.Set.fromList++{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements.++>>> input (hashSetFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+hashSetFromDistinctList :: (Hashable a, Ord a, Show a)+                        => Decoder a+                        -> Decoder (Data.HashSet.HashSet a)+hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList+++setHelper :: (Eq a, Foldable t, Show a)+          => (t a -> Int)+          -> ([a] -> t a)+          -> Decoder a+          -> Decoder (t a)+setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (ListLit _ es) = case traverse extractIn es of+        Success vSeq+            | sameSize               -> Success vSet+            | otherwise              -> extractError err+          where+            vList = Data.Foldable.toList vSeq+            vSet = toSet vList+            sameSize = size vSet == Data.Sequence.length vSeq+            duplicates = vList List.\\ Data.Foldable.toList vSet+            err | length duplicates == 1 =+                     "One duplicate element in the list: "+                     <> (Data.Text.pack $ show $ head duplicates)+                | otherwise              = Data.Text.pack $ unwords+                     [ show $ length duplicates+                     , "duplicates were found in the list, including"+                     , show $ head duplicates+                     ]+        Failure f -> Failure f+    extractOut expr = typeError expectedOut expr++    expectedOut = App List <$> expectedIn++{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"+fromList [("a",True),("b",False)]+>>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"+fromList [("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.map natural bool) expr+fromList [(1,False)]++-}+map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)+map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))++{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }")+[("a",True),("b",False)]+>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]")+[("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.hashMap natural bool) expr+fromList [(1,False)]++-}+hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)+hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))++{-| Decode a tuple from a @Prelude.Map.Entry@ record.++>>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"+("foo",3)+-}+pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)+pairFromMapEntry k v = Decoder extractOut expectedOut+  where+    extractOut (RecordLit kvs)+        | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs+        , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs+            = liftA2 (,) (extract k key) (extract v value)+    extractOut expr = typeError expectedOut expr++    expectedOut = do+        k' <- Core.makeRecordField <$> expected k+        v' <- Core.makeRecordField <$> expected v+        pure $ Record $ Dhall.Map.fromList+            [ ("mapKey", k')+            , ("mapValue", v')]++{-| Decode @()@ from an empty record.++>>> input unit "{=}"  -- GHC doesn't print the result if it is ()++-}+unit :: Decoder ()+unit = Decoder {..}+  where+    extract (RecordLit fields)+        | Data.Foldable.null fields = pure ()+    extract expr = typeError expected expr++    expected = pure $ Record mempty++{-| Decode 'Void' from an empty union.++Since @<>@ is uninhabited, @'Dhall.input' 'void'@ will always fail.+-}+void :: Decoder Void+void = union mempty++{-| Decode a `String`++>>> input string "\"ABC\""+"ABC"++-}+string :: Decoder String+string = Data.Text.Lazy.unpack <$> lazyText++{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.++>>> input (pair natural bool) "{ _1 = 42, _2 = False }"+(42,False)+-}+pair :: Decoder a -> Decoder b -> Decoder (a, b)+pair l r = Decoder extractOut expectedOut+  where+    extractOut expr@(RecordLit fields) =+      (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)+                (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)+          <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)+                (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)+    extractOut expr = typeError expectedOut expr++    expectedOut = do+        l' <- Core.makeRecordField <$> expected l+        r' <- Core.makeRecordField <$> expected r+        pure $ Record $ Dhall.Map.fromList+            [ ("_1", l')+            , ("_2", r')]++++{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'+    from a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Project = Project+  { projectName :: Text+  , projectDescription :: Text+  , projectStars :: Natural+  }+:}++    And assume that we have the following Dhall record that we would like to+    parse as a @Project@:++> { name =+>     "dhall-haskell"+> , description =+>     "A configuration language guaranteed to terminate"+> , stars =+>     289+> }++    Our decoder has type 'Decoder' @Project@, but we can't build that out of any+    smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+    However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:++>>> :{+project :: Decoder Project+project =+  record+    ( Project <$> field "name" strictText+              <*> field "description" strictText+              <*> field "stars" natural+    )+:}+-}+newtype RecordDecoder a =+  RecordDecoder+    ( Data.Functor.Product.Product+        ( Control.Applicative.Const+            (Dhall.Map.Map Text (Expector (Expr Src Void)))+        )+        ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)+        )+        a+    )+  deriving (Functor, Applicative)++-- | Run a 'RecordDecoder' to build a 'Decoder'.+record :: RecordDecoder a -> Dhall.Marshal.Decode.Decoder a+record+    (RecordDecoder+        (Data.Functor.Product.Pair+            (Control.Applicative.Const fields)+            (Data.Functor.Compose.Compose extract)+        )+    ) = Decoder {..}+  where+    expected = Record <$> traverse (fmap Core.makeRecordField) fields++-- | Parse a single field of a record.+field :: Text -> Decoder a -> RecordDecoder a+field key (Decoder {..}) =+  RecordDecoder+    ( Data.Functor.Product.Pair+        ( Control.Applicative.Const+            (Dhall.Map.singleton key expected)+        )+        ( Data.Functor.Compose.Compose extractBody )+    )+  where+    extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of+      Just v -> extract v+      _      -> typeError expected expr+    extractBody expr = typeError expected expr++++{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union.++    For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+            | Result Text+            | Errored Text+:}++    And assume that we have the following Dhall union that we would like to+    parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++    Our decoder has type 'Decoder' @Status@, but we can't build that out of any+    smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+    However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:++>>> :{+status :: Decoder Status+status = union+  (  ( Queued  <$> constructor "Queued"  natural )+  <> ( Result  <$> constructor "Result"  strictText )+  <> ( Errored <$> constructor "Errored" strictText )+  )+:}++-}+newtype UnionDecoder a =+    UnionDecoder+      ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )+  deriving (Functor)++instance Semigroup (UnionDecoder a) where+    (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))++instance Monoid (UnionDecoder a) where+    mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))++-- | Run a 'UnionDecoder' to build a 'Decoder'.+union :: UnionDecoder a -> Decoder a+union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}+  where+    extract expr = case expected' of+        Failure e -> Failure $ fmap ExpectedTypeError e+        Success x -> extract' expr x++    extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.Marshal.Decode.extract) $ do+        (fld, e1, rest) <- extractUnionConstructor e0++        t <- Dhall.Map.lookup fld mp++        guard $+            Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')++        pure (t, e1)++    expected = Union <$> expected'++    expected' = traverse (fmap notEmptyRecord . Dhall.Marshal.Decode.expected) mp++-- | Parse a single constructor of a union.+constructor :: Text -> Decoder a -> UnionDecoder a+constructor key valueDecoder = UnionDecoder+    ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )++++{-| A newtype suitable for collecting one or more errors.+-}+newtype DhallErrors e = DhallErrors+   { getErrors :: NonEmpty e+   } deriving (Eq, Functor, Semigroup)++instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)++{-| Render a given prefix and some errors to a string.+-}+showDhallErrors :: Show e => String -> DhallErrors e -> String+showDhallErrors _   (DhallErrors (e :| [])) = show e+showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)+  where+    prefix =+        "Multiple errors were encountered" ++ ctx ++ ": \n\+        \                                               \n"++{-| One or more errors returned from extracting a Dhall expression to a+    Haskell expression.+-}+type ExtractErrors s a = DhallErrors (ExtractError s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where+    show = showDhallErrors " during extraction"++{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,+    as expressions are type-checked against the expected type before being passed to @extract@), or+    a term-level error, described with a freeform text value.+-}+data ExtractError s a =+    TypeMismatch (InvalidDecoder s a)+  | ExpectedTypeError ExpectedTypeError+  | ExtractError Text+  deriving (Eq)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where+  show (TypeMismatch e)      = show e+  show (ExpectedTypeError e) = show e+  show (ExtractError es)     = unlines+      [ _ERROR <> ": Failed extraction                                                   "+      , "                                                                                "+      , "The expression type-checked successfully but the transformation to the target   "+      , "type failed with the following error:                                           "+      , "                                                                                "+      , Data.Text.unpack es+      , "                                                                                "+      ]++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)++{-| Useful synonym for the `Validation` type used when marshalling Dhall+    expressions.+-}+type Extractor s a = Validation (ExtractErrors s a)++{-| Generate a type error during extraction by specifying the expected type+    and the actual type.+    The expected type is not yet determined.+-}+typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b+typeError expected actual = Failure $ case expected of+    Failure e         -> fmap ExpectedTypeError e+    Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual++-- | Turn a `Data.Text.Text` message into an extraction failure.+extractError :: Text -> Extractor s a b+extractError = Failure . DhallErrors . pure . ExtractError++{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall+    code.+-}+type MonadicExtractor s a = Either (ExtractErrors s a)++-- | Switches from an @Applicative@ extraction result, able to accumulate errors,+-- to a @Monad@ extraction result, able to chain sequential operations.+toMonadic :: Extractor s a b -> MonadicExtractor s a b+toMonadic = validationToEither++-- | Switches from a @Monad@ extraction result, able to chain sequential errors,+-- to an @Applicative@ extraction result, able to accumulate errors.+fromMonadic :: MonadicExtractor s a b -> Extractor s a b+fromMonadic = eitherToValidation++{-| Every `Decoder` must obey the contract that if an expression's type matches+    the `expected` type then the `extract` function must not fail with a type+    error.  However, decoding may still fail for other reasons (such as the+    decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate+    elements).++    This error type is used to indicate an internal error in the implementation+    of a `Decoder` where the expected type matched the Dhall expression, but the+    expression supplied to the extraction function did not match the expected+    type.  If this happens that means that the `Decoder` itself needs to be+    fixed.+-}+data InvalidDecoder s a = InvalidDecoder+  { invalidDecoderExpected   :: Expr s a+  , invalidDecoderExpression :: Expr s a+  }+  deriving (Eq, Typeable)++instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where+    show InvalidDecoder { .. } = unlines+        [ _ERROR <> ": Invalid Dhall.Decoder                                               "+        , "                                                                                "+        , "Every Decoder must provide an extract function that does not fail with a type   "+        , "error if an expression matches the expected type.  You provided a Decoder that  "+        , "disobeys this contract                                                          "+        , "                                                                                "+        , "The Decoder provided has the expected dhall type:                               "+        , "                                                                                "+        , show (Dhall.Util.insert invalidDecoderExpected)+        , "                                                                                "+        , "and it threw a type error during extraction from the well-typed expression:     "+        , "                                                                                "+        , show (Dhall.Util.insert invalidDecoderExpression)+        , "                                                                                "+        ]++{-| Useful synonym for the `Validation` type used when marshalling Dhall+    expressions.+-}+type Expector = Validation ExpectedTypeErrors++{-| One or more errors returned when determining the Dhall type of a+    Haskell expression.+-}+type ExpectedTypeErrors = DhallErrors ExpectedTypeError++{-| Error type used when determining the Dhall type of a Haskell expression.+-}+data ExpectedTypeError = RecursiveTypeError+    deriving (Eq, Show)++instance Exception ExpectedTypeError++instance Show ExpectedTypeErrors where+    show = showDhallErrors " while determining the expected type"++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"
+ src/Dhall/Marshal/Encode.hs view
@@ -0,0 +1,1068 @@+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE UndecidableInstances       #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Encode+    ( -- * General+      Encoder(..)+    , ToDhall(..)+    , Inject+    , inject++      -- * Building encoders++      -- ** Records+    , RecordEncoder(..)+    , recordEncoder+    , encodeField+    , encodeFieldWith+      -- ** Unions+    , UnionEncoder(..)+    , unionEncoder+    , encodeConstructor+    , encodeConstructorWith+    , (>|<)++      -- * Generic encoding+    , GenericToDhall(..)+    , genericToDhall+    , genericToDhallWith+    , genericToDhallWithInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions++      -- * Miscellaneous+    , InputNormalizer(..)+    , defaultInputNormalizer+    , Result+    , (>$<)+    , (>*<)++    -- * Re-exports+    , Natural+    , Seq+    , Text+    , Vector+    , Generic+    ) where++import Control.Monad.Trans.State.Strict+import Data.Functor.Contravariant           (Contravariant (..), Op (..), (>$<))+import Data.Functor.Contravariant.Divisible (Divisible (..), divided)+import Dhall.Parser                         (Src (..))+import Dhall.Syntax+    ( Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    )+import GHC.Generics+import Prelude                              hiding (maybe, sequence)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.HashSet+import qualified Data.Map+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time             as Time+import qualified Data.Vector+import qualified Data.Void+import qualified Dhall.Core            as Core+import qualified Dhall.Map++import Dhall.Marshal.Internal++-- $setup+-- >>> :set -XRecordWildCards+-- >>> import Dhall.Pretty.Internal (prettyExpr)++{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from+    Haskell into Dhall.+-}+data Encoder a = Encoder+    { embed    :: a -> Expr Src Void+    -- ^ Embeds a Haskell value as a Dhall expression+    , declared :: Expr Src Void+    -- ^ Dhall type of the Haskell value+    }++instance Contravariant Encoder where+    contramap f (Encoder embed declared) = Encoder embed' declared+      where+        embed' x = embed (f x)++{-| This class is used by `Dhall.Marshal.Decode.FromDhall` instance for functions:++> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)++    You can convert Dhall functions with "simple" inputs (i.e. instances of this+    class) into Haskell functions.  This works by:++    * Marshaling the input to the Haskell function into a Dhall expression (i.e.+      @x :: Expr Src Void@)+    * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input+      (i.e. @App f x@)+    * Normalizing the syntax tree (i.e. @normalize (App f x)@)+    * Marshaling the resulting Dhall expression back into a Haskell value++    This class auto-generates a default implementation for types that+    implement `Generic`.  This does not auto-generate an instance for recursive+    types.++    The default instance can be tweaked using 'genericToDhallWith'/'genericToDhallWithInputNormalizer'+    and custom 'InterpretOptions', or using+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class ToDhall a where+    injectWith :: InputNormalizer -> Encoder a+    default injectWith+        :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a+    injectWith _ = genericToDhall++-- | A compatibility alias for `ToDhall`+type Inject = ToDhall+{-# DEPRECATED Inject "Use ToDhall instead" #-}++{-| Use the default input normalizer for injecting a value.++> inject = injectWith defaultInputNormalizer+-}+inject :: ToDhall a => Encoder a+inject = injectWith defaultInputNormalizer++++instance ToDhall Void where+    injectWith _ = Encoder {..}+      where+        embed = Data.Void.absurd++        declared = Union mempty++instance ToDhall Bool where+    injectWith _ = Encoder {..}+      where+        embed = BoolLit++        declared = Bool++instance ToDhall Data.ByteString.Short.ShortByteString where+    injectWith options =+        contramap Data.ByteString.Short.fromShort (injectWith options)++instance ToDhall Data.ByteString.Lazy.ByteString where+    injectWith options =+        contramap Data.ByteString.Lazy.toStrict (injectWith options)++instance ToDhall Data.ByteString.ByteString where+    injectWith _ = Encoder {..}+      where+        embed bytes = BytesLit bytes++        declared = Bytes++instance ToDhall Data.Text.Short.ShortText where+    injectWith _ = Encoder {..}+      where+        embed text =+            TextLit (Chunks [] (Data.Text.Short.toText text))++        declared = Text++instance ToDhall Data.Text.Lazy.Text where+    injectWith _ = Encoder {..}+      where+        embed text =+            TextLit (Chunks [] (Data.Text.Lazy.toStrict text))++        declared = Text++instance ToDhall Text where+    injectWith _ = Encoder {..}+      where+        embed text = TextLit (Chunks [] text)++        declared = Text++instance {-# OVERLAPS #-} ToDhall String where+    injectWith inputNormalizer =+        contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)++instance ToDhall Natural where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit++        declared = Natural++instance ToDhall Integer where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit++        declared = Integer++instance ToDhall Int where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int8 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int16 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int32 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int64 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++{-| Encode a 'Word' to a Dhall @Natural@.++>>> embed inject (12 :: Word)+NaturalLit 12+-}+instance ToDhall Word where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word8' to a Dhall @Natural@.++>>> embed inject (12 :: Word8)+NaturalLit 12+-}+instance ToDhall Word8 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word16' to a Dhall @Natural@.++>>> embed inject (12 :: Word16)+NaturalLit 12+-}+instance ToDhall Word16 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word32' to a Dhall @Natural@.++>>> embed inject (12 :: Word32)+NaturalLit 12+-}+instance ToDhall Word32 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word64' to a Dhall @Natural@.++>>> embed inject (12 :: Word64)+NaturalLit 12+-}+instance ToDhall Word64 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++instance ToDhall Double where+    injectWith _ = Encoder {..}+      where+        embed = DoubleLit . DhallDouble++        declared = Double++instance ToDhall Scientific where+    injectWith inputNormalizer =+        contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)++instance ToDhall () where+    injectWith _ = Encoder {..}+      where+        embed = const (RecordLit mempty)++        declared = Record mempty++instance ToDhall a => ToDhall (Maybe a) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut (Just x ) = Some (embedIn x)+        embedOut  Nothing  = App None declaredIn++        Encoder embedIn declaredIn = injectWith inputNormalizer++        declaredOut = App Optional declaredIn++instance ToDhall a => ToDhall (Seq a) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut xs = ListLit listType (fmap embedIn xs)+          where+            listType+                | null xs   = Just (App List declaredIn)+                | otherwise = Nothing++        declaredOut = App List declaredIn++        Encoder embedIn declaredIn = injectWith inputNormalizer++instance ToDhall a => ToDhall [a] where+    injectWith = fmap (contramap Data.Sequence.fromList) injectWith++instance ToDhall a => ToDhall (Vector a) where+    injectWith = fmap (contramap Data.Vector.toList) injectWith++instance ToDhall Time.TimeOfDay where+    injectWith _ = Encoder {..}+      where+        embed timeOfDay = TimeLiteral timeOfDay 12++        declared = Time++instance ToDhall Time.Day where+    injectWith _ = Encoder {..}+      where+        embed = DateLiteral++        declared = Date++instance ToDhall Time.TimeZone where+    injectWith _ = Encoder {..}+      where+        embed = TimeZoneLiteral++        declared = TimeZone++instance ToDhall Time.LocalTime where+    injectWith _ = recordEncoder $+      adapt+        >$< encodeField "date"+        >*< encodeField "time"+      where+        adapt (Time.LocalTime date time) = (date, time)++instance ToDhall Time.ZonedTime where+    injectWith _ = recordEncoder $+      adapt+        >$< encodeField "date"+        >*< encodeField "time"+        >*< encodeField "timeZone"+      where+        adapt (Time.ZonedTime (Time.LocalTime date time) timeZone) = (date, (time, timeZone))++instance ToDhall Time.UTCTime where+    injectWith = contramap (Time.utcToZonedTime Time.utc) . injectWith++instance ToDhall Time.DayOfWeek where+    injectWith _ = Encoder{..}+      where+        embed Time.Sunday =+            Field declared (Core.makeFieldSelection "Sunday")+        embed Time.Monday =+            Field declared (Core.makeFieldSelection "Monday" )+        embed Time.Tuesday =+            Field declared (Core.makeFieldSelection "Tuesday")+        embed Time.Wednesday =+            Field declared (Core.makeFieldSelection "Wednesday")+        embed Time.Thursday =+            Field declared (Core.makeFieldSelection "Thursday")+        embed Time.Friday =+            Field declared (Core.makeFieldSelection "Friday")+        embed Time.Saturday =+            Field declared (Core.makeFieldSelection "Saturday")++        declared =+            Union+                (Dhall.Map.fromList+                    [ ("Sunday", Nothing)+                    , ("Monday", Nothing)+                    , ("Tuesday", Nothing)+                    , ("Wednesday", Nothing)+                    , ("Thursday", Nothing)+                    , ("Friday", Nothing)+                    , ("Saturday", Nothing)+                    ]+                )++{-| Note that the output list will be sorted.++>>> let x = Data.Set.fromList ["mom", "hi" :: Text]+>>> prettyExpr $ embed inject x+[ "hi", "mom" ]++-}+instance ToDhall a => ToDhall (Data.Set.Set a) where+    injectWith = fmap (contramap Data.Set.toAscList) injectWith++-- | Note that the output list may not be sorted+instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where+    injectWith = fmap (contramap Data.HashSet.toList) injectWith++instance (ToDhall a, ToDhall b) => ToDhall (a, b)++{-| Embed a `Data.Map` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut m = ListLit listType (mapEntries m)+          where+            listType+                | Data.Map.null m = Just declaredOut+                | otherwise       = Nothing++        declaredOut = App List (Record $ Dhall.Map.fromList+                          [ ("mapKey", Core.makeRecordField declaredK)+                          , ("mapValue", Core.makeRecordField declaredV)+                          ])++        mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList+        recordPair (k, v) = RecordLit $ Dhall.Map.fromList+                                [ ("mapKey", Core.makeRecordField $ embedK k)+                                , ("mapValue", Core.makeRecordField $ embedV v)+                                ]++        Encoder embedK declaredK = injectWith inputNormalizer+        Encoder embedV declaredV = injectWith inputNormalizer++{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut m = ListLit listType (mapEntries m)+          where+            listType+                | HashMap.null m = Just declaredOut+                | otherwise       = Nothing++        declaredOut = App List (Record $ Dhall.Map.fromList+                          [ ("mapKey", Core.makeRecordField declaredK)+                          , ("mapValue", Core.makeRecordField declaredV)+                          ])++        mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList+        recordPair (k, v) = RecordLit $ Dhall.Map.fromList+                                [ ("mapKey", Core.makeRecordField $ embedK k)+                                , ("mapValue", Core.makeRecordField $ embedV v)+                                ]++        Encoder embedK declaredK = injectWith inputNormalizer+        Encoder embedV declaredV = injectWith inputNormalizer++instance ToDhall (f (Result f)) => ToDhall (Result f) where+    injectWith inputNormalizer = Encoder {..}+      where+        embed = App "Make" . Dhall.Marshal.Encode.embed (injectWith inputNormalizer) . _unResult+        declared = "result"++instance forall f. (Functor f, ToDhall (f (Result f))) => ToDhall (Fix f) where+    injectWith inputNormalizer = Encoder {..}+      where+        embed fixf =+          Lam Nothing (Core.makeFunctionBinding "result" (Const Core.Type)) $+            Lam Nothing (Core.makeFunctionBinding "Make" makeType) $+              embed' . fixToResult $ fixf++        declared = Pi Nothing "result" (Const Core.Type) $ Pi Nothing "_" makeType "result"++        makeType = Pi Nothing "_" declared' "result"+        Encoder embed' _ = injectWith @(Dhall.Marshal.Internal.Result f) inputNormalizer+        Encoder _ declared' = injectWith @(f (Dhall.Marshal.Internal.Result f)) inputNormalizer++fixToResult :: Functor f => Fix f -> Result f+fixToResult (Fix x) = Result (fmap fixToResult x)++++{-| This is the underlying class that powers the `Dhall.Marshal.Decode.FromDhall` class's support+    for automatically deriving a generic implementation.+-}+class GenericToDhall f where+    genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))++instance GenericToDhall f => GenericToDhall (M1 D d f) where+    genericToDhallWithNormalizer inputNormalizer options = do+        res <- genericToDhallWithNormalizer inputNormalizer options+        pure (contramap unM1 res)++instance GenericToDhall f => GenericToDhall (M1 C c f) where+    genericToDhallWithNormalizer inputNormalizer options = do+        res <- genericToDhallWithNormalizer inputNormalizer options+        pure (contramap unM1 res)++instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where+    genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+        let Encoder { embed = embed', declared = declared' } =+                injectWith inputNormalizer++        let n :: M1 S s (K1 i a) r+            n = undefined++        name <- fieldModifier <$> getSelName n++        let embed0 (M1 (K1 x)) = embed' x++        let embed1 (M1 (K1 x)) =+                RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))++        let embed =+                case singletonConstructors of+                    Bare                    -> embed0+                    Smart | selName n == "" -> embed0+                    _                       -> embed1++        let declared =+                case singletonConstructors of+                    Bare ->+                        declared'+                    Smart | selName n == "" ->+                        declared'+                    _ ->+                        Record (Dhall.Map.singleton name $ Core.makeRecordField declared')++        return (Encoder {..})++instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 (M1 l)) =+            case notEmptyRecordLit (embedL l) of+                Nothing ->+                    Field declared $ Core.makeFieldSelection keyL+                Just valL ->+                    App (Field declared $ Core.makeFieldSelection keyL) valL++        embed (R1 (M1 r)) =+            case notEmptyRecordLit (embedR r) of+                Nothing ->+                    Field declared $ Core.makeFieldSelection keyR+                Just valR ->+                    App (Field declared $ Core.makeFieldSelection keyR) valR++        declared =+            Union+                (Dhall.Map.fromList+                    [ (keyL, notEmptyRecord declaredL)+                    , (keyR, notEmptyRecord declaredR)+                    ]+                )++        nL :: M1 i c1 f1 a+        nL = undefined++        nR :: M1 i c2 f2 a+        nR = undefined++        keyL = constructorModifier (Data.Text.pack (conName nL))+        keyR = constructorModifier (Data.Text.pack (conName nR))++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 l) =+            case maybeValL of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+          where+            (keyL, maybeValL) =+              unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+        embed (R1 (M1 r)) =+            case notEmptyRecordLit (embedR r) of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR++        nR :: M1 i c h a+        nR = undefined++        keyR = constructorModifier (Data.Text.pack (conName nR))++        declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL++instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 (M1 l)) =+            case notEmptyRecordLit (embedL l) of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+        embed (R1 r) =+            case maybeValR of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+          where+            (keyR, maybeValR) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++        nL :: M1 i c f a+        nL = undefined++        keyL = constructorModifier (Data.Text.pack (conName nL))++        declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where+    genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})+      where+        embed (L1 l) =+            case maybeValL of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+          where+            (keyL, maybeValL) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+        embed (R1 r) =+            case maybeValR of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+          where+            (keyR, maybeValR) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++        declared = Union (Dhall.Map.union ktsL ktsR)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL+        ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where+    genericToDhallWithNormalizer inputNormalizer options = do+        Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options+        Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++        let embed (l :*: r) =+                RecordLit (Dhall.Map.union mapL mapR)+              where+                mapL =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++                mapR =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++        let declared = Record (Dhall.Map.union mapL mapR)+              where+                mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL+                mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++        pure (Encoder {..})++instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where+    genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+        let nR :: M1 S s (K1 i a) r+            nR = undefined++        nameR <- fmap fieldModifier (getSelName nR)++        Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options++        let Encoder embedR declaredR = injectWith inputNormalizer++        let embed (l :*: M1 (K1 r)) =+                RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)+              where+                mapL =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++        let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)+              where+                mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL++        return (Encoder {..})++instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where+    genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+        let nL :: M1 S s (K1 i a) r+            nL = undefined++        nameL <- fmap fieldModifier (getSelName nL)++        let Encoder embedL declaredL = injectWith inputNormalizer++        Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++        let embed (M1 (K1 l) :*: r) =+                RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)+              where+                mapR =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++        let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)+              where+                mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++        return (Encoder {..})++instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+        let nL :: M1 S s1 (K1 i1 a1) r+            nL = undefined++        let nR :: M1 S s2 (K1 i2 a2) r+            nR = undefined++        nameL <- fmap fieldModifier (getSelName nL)+        nameR <- fmap fieldModifier (getSelName nR)++        let Encoder embedL declaredL = injectWith inputNormalizer+        let Encoder embedR declaredR = injectWith inputNormalizer++        let embed (M1 (K1 l) :*: M1 (K1 r)) =+                RecordLit $+                    Dhall.Map.fromList+                        [ (nameL, Core.makeRecordField $ embedL l)+                        , (nameR, Core.makeRecordField $ embedR r) ]+++        let declared =+                Record $ Dhall.Map.fromList+                    [ (nameL, Core.makeRecordField declaredL)+                    , (nameR, Core.makeRecordField declaredR) ]+++        return (Encoder {..})++instance GenericToDhall U1 where+    genericToDhallWithNormalizer _ _ = pure (Encoder {..})+      where+        embed _ = RecordLit mempty++        declared = Record mempty++{-| Use the default options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhall+  :: (Generic a, GenericToDhall (Rep a)) => Encoder a+genericToDhall+    = genericToDhallWith defaultInterpretOptions++{-| Use custom options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhallWith+  :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a+genericToDhallWith options = genericToDhallWithInputNormalizer options defaultInputNormalizer++{-| `genericToDhallWithInputNormalizer` is like `genericToDhallWith`, but+    instead of using the `defaultInputNormalizer` it expects an custom+    `InputNormalizer`.+-}+genericToDhallWithInputNormalizer+  :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> InputNormalizer -> Encoder a+genericToDhallWithInputNormalizer options inputNormalizer+    = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer inputNormalizer options) 1)++++{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build+    an 'Encoder' for a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Project = Project+  { projectName :: Text+  , projectDescription :: Text+  , projectStars :: Natural+  }+:}++    And assume that we have the following Dhall record that we would like to+    parse as a @Project@:++> { name =+>     "dhall-haskell"+> , description =+>     "A configuration language guaranteed to terminate"+> , stars =+>     289+> }++    Our encoder has type 'Encoder' @Project@, but we can't build that out of any+    smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).+    However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:++>>> :{+injectProject :: Encoder Project+injectProject =+  recordEncoder+    ( adapt >$< encodeFieldWith "name" inject+            >*< encodeFieldWith "description" inject+            >*< encodeFieldWith "stars" inject+    )+  where+    adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++    Or, since we are simply using the `ToDhall` instance to inject each field, we could write++>>> :{+injectProject :: Encoder Project+injectProject =+  recordEncoder+    ( adapt >$< encodeField "name"+            >*< encodeField "description"+            >*< encodeField "stars"+    )+  where+    adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++-}+newtype RecordEncoder a+  = RecordEncoder (Dhall.Map.Map Text (Encoder a))++instance Contravariant RecordEncoder where+  contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord++instance Divisible RecordEncoder where+  divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =+      RecordEncoder+    $ Dhall.Map.union+      ((contramap $ fst . f) <$> bEncoderRecord)+      ((contramap $ snd . f) <$> cEncoderRecord)+  conquer = RecordEncoder mempty++-- | Convert a `RecordEncoder` into the equivalent `Encoder`.+recordEncoder :: RecordEncoder a -> Encoder a+recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType+  where+    recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord+    makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord++{-| Specify how to encode one field of a record using the default `ToDhall`+    instance for that type.+-}+encodeField :: ToDhall a => Text -> RecordEncoder a+encodeField name = encodeFieldWith name inject++{-| Specify how to encode one field of a record by supplying an explicit+    `Encoder` for that field.+-}+encodeFieldWith :: Text -> Encoder a -> RecordEncoder a+encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType++++{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+            | Result Text+            | Errored Text+:}++    And assume that we have the following Dhall union that we would like to+    parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++    Our encoder has type 'Encoder' @Status@, but we can't build that out of any+    smaller encoders, as 'Encoder's cannot be combined.+    However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+  (   encodeConstructorWith "Queued"  inject+  >|< encodeConstructorWith "Result"  inject+  >|< encodeConstructorWith "Errored" inject+  )+  where+    adapt (Queued  n) = Left n+    adapt (Result  t) = Right (Left t)+    adapt (Errored e) = Right (Right e)+:}++    Or, since we are simply using the `ToDhall` instance to inject each branch, we could write++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+  (   encodeConstructor "Queued"+  >|< encodeConstructor "Result"+  >|< encodeConstructor "Errored"+  )+  where+    adapt (Queued  n) = Left n+    adapt (Result  t) = Right (Left t)+    adapt (Errored e) = Right (Right e)+:}++-}+newtype UnionEncoder a =+  UnionEncoder+    ( Data.Functor.Product.Product+        ( Control.Applicative.Const+            ( Dhall.Map.Map+                Text+                ( Expr Src Void )+            )+        )+        ( Op (Text, Expr Src Void) )+        a+    )+  deriving (Contravariant)++-- | Convert a `UnionEncoder` into the equivalent `Encoder`.+unionEncoder :: UnionEncoder a -> Encoder a+unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =+    Encoder+      { embed = \x ->+          let (name, y) = embedF x+          in  case notEmptyRecordLit y of+                  Nothing  -> Field (Union fields') $ Core.makeFieldSelection name+                  Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val+      , declared =+          Union fields'+      }+  where+    fields' = fmap notEmptyRecord fields++{-| Specify how to encode an alternative by using the default `ToDhall` instance+    for that type.+-}+encodeConstructor+    :: ToDhall a+    => Text+    -> UnionEncoder a+encodeConstructor name = encodeConstructorWith name inject++{-| Specify how to encode an alternative by providing an explicit `Encoder`+    for that alternative.+-}+encodeConstructorWith+    :: Text+    -> Encoder a+    -> UnionEncoder a+encodeConstructorWith name encodeType = UnionEncoder $+    Data.Functor.Product.Pair+      ( Control.Applicative.Const+          ( Dhall.Map.singleton+              name+              ( declared encodeType )+          )+      )+      ( Op ( (name,) . embed encodeType )+      )++-- | Combines two 'UnionEncoder' values.  See 'UnionEncoder' for usage+-- notes.+--+-- Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';+-- however, this allows 'UnionEncoder' to not need a 'Divisible' instance+-- itself (since no instance is possible).+(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)+UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))+    >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =+    UnionEncoder+      ( Data.Functor.Product.Pair+          ( Control.Applicative.Const (mx <> my) )+          ( Op (either fx fy) )+      )++infixr 5 >|<++++-- | Infix 'divided'+(>*<) :: Divisible f => f a -> f b -> f (a, b)+(>*<) = divided++infixr 5 >*<
+ src/Dhall/Marshal/Internal.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns      #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Internal+    ( InputNormalizer(..)+    , defaultInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions++    -- * Miscellaneous+    , Result(..)++    -- * Helpers for the generic deriving machinery+    , getSelName+    , notEmptyRecord+    , notEmptyRecordLit+    , unsafeExpectRecord+    , unsafeExpectRecordLit+    , unsafeExpectUnion+    , unsafeExpectUnionLit++    -- * Re-exports+    , Fix(..)+    , HashMap+    , Int8+    , Int16+    , Int32+    , Int64+    , Map+    , Natural+    , Scientific+    , Seq+    , Text+    , Vector+    , Void+    , Word8+    , Word16+    , Word32+    , Word64+    , Generic+    ) where++import Control.Monad.Trans.State.Strict+import Data.Fix                         (Fix (..))+import Data.HashMap.Strict              (HashMap)+import Data.Int                         (Int16, Int32, Int64, Int8)+import Data.Map                         (Map)+import Data.Scientific                  (Scientific)+import Data.Sequence                    (Seq)+import Data.Text                        (Text)+import Data.Vector                      (Vector)+import Data.Void                        (Void)+import Data.Word                        (Word16, Word32, Word64, Word8)+import Dhall.Parser                     (Src (..))+import Dhall.Syntax                     (Expr (..), RecordField (..))+import GHC.Generics+import Numeric.Natural                  (Natural)+import Prelude                          hiding (maybe, sequence)++import qualified Data.Text+import qualified Dhall.Core as Core+import qualified Dhall.Map++{-| This type is exactly the same as `Data.Fix.Fix` except with a different+    `Dhall.Marshal.Decode.FromDhall` instance.  This intermediate type+    simplifies the implementation of the inner loop for the+    `Dhall.Marshal.Decode.FromDhall` instance for `Fix`.+-}+newtype Result f = Result { _unResult :: f (Result f) }++{-| Use these options to tweak how Dhall derives a generic implementation of+    `Dhall.Marshal.Decode.FromDhall`.+-}+data InterpretOptions = InterpretOptions+    { fieldModifier       :: Text -> Text+    -- ^ Function used to transform Haskell field names into their corresponding+    --   Dhall field names+    , constructorModifier :: Text -> Text+    -- ^ Function used to transform Haskell constructor names into their+    --   corresponding Dhall alternative names+    , singletonConstructors :: SingletonConstructors+    -- ^ Specify how to handle constructors with only one field.  The default is+    --   `Smart`+    }++{-| This is only used by the `Dhall.Marshal.Decode.FromDhall` instance for+    functions in order to normalize the function input before marshaling the+    input into a Dhall expression.+-}+newtype InputNormalizer = InputNormalizer+  { getInputNormalizer :: Core.ReifiedNormalizer Void }++-- | Default normalization-related settings (no custom normalization)+defaultInputNormalizer :: InputNormalizer+defaultInputNormalizer = InputNormalizer+ { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }++{-| This type specifies how to model a Haskell constructor with 1 field in+    Dhall++    For example, consider the following Haskell datatype definition:++    > data Example = Foo { x :: Double } | Bar Double++    Depending on which option you pick, the corresponding Dhall type could be:++    > < Foo : Double | Bar : Double >                   -- Bare++    > < Foo : { x : Double } | Bar : { _1 : Double } >  -- Wrapped++    > < Foo : { x : Double } | Bar : Double >           -- Smart+-}+data SingletonConstructors+    = Bare+    -- ^ Never wrap the field in a record+    | Wrapped+    -- ^ Always wrap the field in a record+    | Smart+    -- ^ Only fields in a record if they are named++{-| Default interpret options for generics-based instances,+    which you can tweak or override, like this:++> genericAutoWith+>     (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })+-}+defaultInterpretOptions :: InterpretOptions+defaultInterpretOptions = InterpretOptions+    { fieldModifier =+          id+    , constructorModifier =+          id+    , singletonConstructors =+          Smart+    }++unsafeExpectUnion+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))+unsafeExpectUnion _ (Union kts) =+    kts+unsafeExpectUnion name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecord+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecord _ (Record kts) =+    kts+unsafeExpectRecord name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectUnionLit+    :: Text+    -> Expr Src Void+    -> (Text, Maybe (Expr Src Void))+unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =+    (k, Nothing)+unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =+    (k, Just v)+unsafeExpectUnionLit name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecordLit+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecordLit _ (RecordLit kvs) =+    kvs+unsafeExpectRecordLit name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)+notEmptyRecordLit e = case e of+    RecordLit m | null m -> Nothing+    _                    -> Just e++notEmptyRecord :: Expr s a -> Maybe (Expr s a)+notEmptyRecord e = case e of+    Record m | null m -> Nothing+    _                 -> Just e++getSelName :: Selector s => M1 i s f a -> State Int Text+getSelName n = case selName n of+    "" -> do i <- get+             put (i + 1)+             pure (Data.Text.pack ("_" ++ show i))+    nn -> pure (Data.Text.pack nn)
+ src/Dhall/Normalize.hs view
@@ -0,0 +1,1037 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE ViewPatterns      #-}++module Dhall.Normalize (+      alphaNormalize+    , normalize+    , normalizeWith+    , normalizeWithM+    , Normalizer+    , NormalizerM+    , ReifiedNormalizer (..)+    , judgmentallyEqual+    , subst+    , Syntax.shift+    , isNormalized+    , isNormalizedWith+    , freeIn+    ) where++import Control.Applicative   (empty)+import Data.Foldable+import Data.Functor.Identity (Identity (..))+import Data.List.NonEmpty    (NonEmpty (..))+import Data.Sequence         (ViewL (..), ViewR (..))+import Data.Traversable+import Instances.TH.Lift     ()+import Prelude               hiding (succ)++import Dhall.Syntax+    ( Binding (Binding)+    , Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    , FieldSelection (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text     as Text+import qualified Dhall.Eval    as Eval+import qualified Dhall.Map+import qualified Dhall.Syntax  as Syntax+import qualified Lens.Micro    as Lens++{-| Returns `True` if two expressions are α-equivalent and β-equivalent and+    `False` otherwise++    `judgmentallyEqual` can fail with an `error` if you compare ill-typed+    expressions+-}+judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool+judgmentallyEqual = Eval.judgmentallyEqual+{-# INLINE judgmentallyEqual #-}++{-| Substitute all occurrences of a variable with an expression++> subst x C B  ~  B[x := C]+-}+subst :: Var -> Expr s a -> Expr s a -> Expr s a+subst _ _ (Const a) = Const a+subst (V x n) e (Lam cs (FunctionBinding src0 y src1 src2 _A) b) =+    Lam cs (FunctionBinding src0 y src1 src2 _A') b'+  where+    _A' = subst (V x n )                         e  _A+    b'  = subst (V x n') (Syntax.shift 1 (V y 0) e)  b+    n'  = if x == y then n + 1 else n+subst (V x n) e (Pi cs y _A _B) = Pi cs y _A' _B'+  where+    _A' = subst (V x n )                         e  _A+    _B' = subst (V x n') (Syntax.shift 1 (V y 0) e) _B+    n'  = if x == y then n + 1 else n+subst v e (Var v') = if v == v' then e else Var v'+subst (V x n) e (Let (Binding src0 f src1 mt src2 r) b) =+    Let (Binding src0 f src1 mt' src2 r') b'+  where+    b' = subst (V x n') (Syntax.shift 1 (V f 0) e) b+      where+        n' = if x == f then n + 1 else n++    mt' = fmap (fmap (subst (V x n) e)) mt+    r'  =             subst (V x n) e  r+subst x e expression = Lens.over Syntax.subExpressions (subst x e) expression++{-| This function is used to determine whether folds like @Natural/fold@ or+    @List/fold@ should be lazy or strict in their accumulator based on the type+    of the accumulator++    If this function returns `True`, then they will be strict in their+    accumulator since we can guarantee an upper bound on the amount of work to+    normalize the accumulator on each step of the loop.  If this function+    returns `False` then they will be lazy in their accumulator and only+    normalize the final result at the end of the fold+-}+boundedType :: Expr s a -> Bool+boundedType Bool             = True+boundedType Natural          = True+boundedType Integer          = True+boundedType Double           = True+boundedType Text             = True+boundedType (App List _)     = False+boundedType (App Optional t) = boundedType t+boundedType (Record kvs)     = all (boundedType . recordFieldValue) kvs+boundedType (Union kvs)      = all (all boundedType) kvs+boundedType _                = False++{-| α-normalize an expression by renaming all bound variables to @\"_\"@ and+    using De Bruijn indices to distinguish them++>>> mfb = Syntax.makeFunctionBinding+>>> alphaNormalize (Lam mempty (mfb "a" (Const Type)) (Lam mempty (mfb "b" (Const Type)) (Lam mempty (mfb "x" "a") (Lam mempty (mfb "y" "b") "x"))))+Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Var (V "_" 1)))))++    α-normalization does not affect free variables:++>>> alphaNormalize "x"+Var (V "x" 0)++-}+alphaNormalize :: Expr s a -> Expr s a+alphaNormalize = Eval.alphaNormalize+{-# INLINE alphaNormalize #-}++{-| Reduce an expression to its normal form, performing beta reduction++    `normalize` does not type-check the expression.  You may want to type-check+    expressions before normalizing them since normalization can convert an+    ill-typed expression into a well-typed expression.++    `normalize` can also fail with `error` if you normalize an ill-typed+    expression+-}+normalize :: Eq a => Expr s a -> Expr t a+normalize = Eval.normalize+{-# INLINE normalize #-}++{-| Reduce an expression to its normal form, performing beta reduction and applying+    any custom definitions.++    `normalizeWith` is designed to be used with function `Dhall.TypeCheck.typeWith`. The `Dhall.TypeCheck.typeWith`+    function allows typing of Dhall functions in a custom typing context whereas+    `normalizeWith` allows evaluating Dhall expressions in a custom context.++    To be more precise `normalizeWith` applies the given normalizer when it finds an+    application term that it cannot reduce by other means.++    Note that the context used in normalization will determine the properties of normalization.+    That is, if the functions in custom context are not total then the Dhall language, evaluated+    with those functions is not total either.++    `normalizeWith` can fail with an `error` if you normalize an ill-typed+    expression+-}+normalizeWith :: Eq a => Maybe (ReifiedNormalizer a) -> Expr s a -> Expr t a+normalizeWith (Just ctx) t = runIdentity (normalizeWithM (getReifiedNormalizer ctx) t)+normalizeWith _          t = Eval.normalize t+{-# INLINABLE normalizeWith #-}++{-| This function generalizes `normalizeWith` by allowing the custom normalizer+    to use an arbitrary `Monad`++    `normalizeWithM` can fail with an `error` if you normalize an ill-typed+    expression+-}+normalizeWithM+    :: (Monad m, Eq a) => NormalizerM m a -> Expr s a -> m (Expr t a)+normalizeWithM ctx e0 = loop (Syntax.denote e0)+ where+  loop e = ctx e >>= \case+      Just e' -> loop e'+      Nothing -> case e of+          Const k -> pure (Const k)+          Var v -> pure (Var v)+          Lam cs (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+              Lam cs <$> (Syntax.makeFunctionBinding x <$> _A') <*> b'+            where+              _A' = loop _A+              b'  = loop b+          Pi cs x _A _B -> Pi cs x <$> _A' <*> _B'+            where+              _A' = loop _A+              _B' = loop _B+          App f a -> do+              f' <- loop f+              a' <- loop a+              case f' of+                Lam _ (FunctionBinding _ x _ _ _A) b₀ -> do++                    let a₂ = Syntax.shift 1 (V x 0) a'+                    let b₁ = subst (V x 0) a₂ b₀+                    let b₂ = Syntax.shift (-1) (V x 0) b₁++                    loop b₂+                _ ->+                  case App f' a' of+                    App (App (App (App NaturalFold (NaturalLit n0)) t) succ') zero -> do+                      t' <- loop t+                      if boundedType t' then strict else lazy+                      where+                        -- Use an `Integer` for the loop, due to the following+                        -- issue:+                        --+                        -- https://github.com/ghcjs/ghcjs/issues/782+                        strict =       strictLoop (fromIntegral n0 :: Integer)+                        lazy   = loop (  lazyLoop (fromIntegral n0 :: Integer))++                        strictLoop !n = do+                            z <- loop zero+                            strictLoopShortcut n z++                        strictLoopShortcut 0 !previous = pure previous+                        strictLoopShortcut !n !previous = do+                            current <- loop (App succ' previous)+                            if judgmentallyEqual previous current+                                then pure previous+                                else strictLoopShortcut (n - 1) current++                        lazyLoop 0 = zero+                        lazyLoop !n = App succ' (lazyLoop (n - 1))+                    App NaturalBuild g -> loop (App (App (App g Natural) succ) zero)+                      where+                        succ = Lam mempty (Syntax.makeFunctionBinding "n" Natural) (NaturalPlus "n" (NaturalLit 1))++                        zero = NaturalLit 0+                    App NaturalIsZero (NaturalLit n) -> pure (BoolLit (n == 0))+                    App NaturalEven (NaturalLit n) -> pure (BoolLit (even n))+                    App NaturalOdd (NaturalLit n) -> pure (BoolLit (odd n))+                    App NaturalToInteger (NaturalLit n) -> pure (IntegerLit (toInteger n))+                    App NaturalShow (NaturalLit n) ->+                        pure (TextLit (Chunks [] (Text.pack (show n))))+                    App (App NaturalSubtract (NaturalLit x)) (NaturalLit y)+                        -- Use an `Integer` for the subtraction, due to the+                        -- following issue:+                        --+                        -- https://github.com/ghcjs/ghcjs/issues/782+                        | y >= x ->+                            pure (NaturalLit (fromIntegral (subtract (fromIntegral x :: Integer) (fromIntegral y :: Integer))))+                        | otherwise ->+                            pure (NaturalLit 0)+                    App (App NaturalSubtract (NaturalLit 0)) y -> pure y+                    App (App NaturalSubtract _) (NaturalLit 0) -> pure (NaturalLit 0)+                    App (App NaturalSubtract x) y | Eval.judgmentallyEqual x y -> pure (NaturalLit 0)+                    App IntegerClamp (IntegerLit n)+                        | 0 <= n -> pure (NaturalLit (fromInteger n))+                        | otherwise -> pure (NaturalLit 0)+                    App IntegerNegate (IntegerLit n) ->+                        pure (IntegerLit (negate n))+                    App IntegerShow (IntegerLit n)+                        | 0 <= n    -> pure (TextLit (Chunks [] ("+" <> Text.pack (show n))))+                        | otherwise -> pure (TextLit (Chunks [] (Text.pack (show n))))+                    -- `(read . show)` is used instead of `fromInteger` because `read` uses+                    -- the correct rounding rule.+                    -- See https://gitlab.haskell.org/ghc/ghc/issues/17231.+                    App IntegerToDouble (IntegerLit n) -> pure (DoubleLit ((DhallDouble . read . show) n))+                    App DoubleShow (DoubleLit (DhallDouble n)) ->+                        pure (TextLit (Chunks [] (Text.pack (show n))))+                    App (App ListBuild _A₀) g -> loop (App (App (App g list) cons) nil)+                      where+                        _A₁ = Syntax.shift 1 "a" _A₀++                        list = App List _A₀++                        cons =+                            Lam mempty (Syntax.makeFunctionBinding "a" _A₀)+                                (Lam mempty+                                    (Syntax.makeFunctionBinding "as" (App List _A₁))+                                    (ListAppend (ListLit Nothing (pure "a")) "as")+                                )++                        nil = ListLit (Just (App List _A₀)) empty+                    App (App (App (App (App ListFold _) (ListLit _ xs)) t) cons) nil -> do+                      t' <- loop t+                      if boundedType t' then strict else lazy+                      where+                        strict =       foldr strictCons strictNil xs+                        lazy   = loop (foldr   lazyCons   lazyNil xs)++                        strictNil = loop nil+                        lazyNil   =      nil++                        strictCons y ys =+                          App (App cons y) <$> ys >>= loop+                        lazyCons   y ys =       App (App cons y) ys+                    App (App ListLength _) (ListLit _ ys) ->+                        pure (NaturalLit (fromIntegral (Data.Sequence.length ys)))+                    App (App ListHead t) (ListLit _ ys) -> loop o+                      where+                        o = case Data.Sequence.viewl ys of+                                y :< _ -> Some y+                                _      -> App None t+                    App (App ListLast t) (ListLit _ ys) -> loop o+                      where+                        o = case Data.Sequence.viewr ys of+                                _ :> y -> Some y+                                _      -> App None t+                    App (App ListIndexed _A₀) (ListLit _ as₀) -> loop (ListLit t as₁)+                      where+                        as₁ = Data.Sequence.mapWithIndex adapt as₀++                        _A₂ = Record (Dhall.Map.fromList kts)+                          where+                            kts = [ ("index", Syntax.makeRecordField Natural)+                                  , ("value", Syntax.makeRecordField _A₀)+                                  ]++                        t | null as₀  = Just (App List _A₂)+                          | otherwise = Nothing++                        adapt n a_ =+                            RecordLit (Dhall.Map.fromList kvs)+                          where+                            kvs = [ ("index", Syntax.makeRecordField $ NaturalLit (fromIntegral n))+                                  , ("value", Syntax.makeRecordField a_)+                                  ]+                    App (App ListReverse _) (ListLit t xs) ->+                        loop (ListLit t (Data.Sequence.reverse xs))+                    App TextShow (TextLit (Chunks [] oldText)) ->+                        loop (TextLit (Chunks [] newText))+                      where+                        newText = Eval.textShow oldText+                    App+                        (App (App TextReplace (TextLit (Chunks [] ""))) _)+                        haystack ->+                            return haystack+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            (TextLit (Chunks [] replacementText))+                        )+                        (TextLit (Chunks xys z)) -> do+                            let xys' = do+                                    (x, y) <- xys++                                    let x' = Text.replace needleText replacementText x+                                    return (x', y)++                            let z' = Text.replace needleText replacementText z++                            return (TextLit (Chunks xys' z'))+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            replacement+                        )+                        (TextLit (Chunks [] lastText)) -> do+                            let (prefix, suffix) =+                                    Text.breakOn needleText lastText++                            if Text.null suffix+                                then return (TextLit (Chunks [] lastText))+                                else do+                                    let remainder =+                                            Text.drop+                                                (Text.length needleText)+                                                suffix++                                    loop (TextAppend (TextLit (Chunks [(prefix, replacement)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks [] remainder))))+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            replacement+                        )+                        (TextLit+                            (Chunks+                                ((firstText, firstInterpolation) : chunks)+                                lastText+                            )+                        ) -> do+                            let (prefix, suffix) =+                                    Text.breakOn needleText firstText++                            if Text.null suffix+                                then do+                                    loop (TextAppend (TextLit (Chunks [(firstText, firstInterpolation)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks chunks lastText))))+                                else do+                                    let remainder =+                                            Text.drop+                                                (Text.length needleText)+                                                suffix++                                    loop (TextAppend (TextLit (Chunks [(prefix, replacement)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks ((remainder, firstInterpolation) : chunks) lastText))))+                    App DateShow (DateLiteral date) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.dateShow date+                    App TimeShow (TimeLiteral time precision) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.timeShow time precision+                    App TimeZoneShow (TimeZoneLiteral timezone) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.timezoneShow timezone+                    _ -> do+                        res2 <- ctx (App f' a')+                        case res2 of+                            Nothing -> pure (App f' a')+                            Just app' -> loop app'+          Let (Binding _ f _ _ _ r) b -> loop b''+            where+              r'  = Syntax.shift   1  (V f 0) r+              b'  = subst (V f 0) r' b+              b'' = Syntax.shift (-1) (V f 0) b'+          Annot x _ -> loop x+          Bool -> pure Bool+          BoolLit b -> pure (BoolLit b)+          BoolAnd x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit True )  r              = r+              decide (BoolLit False)  _              = BoolLit False+              decide  l              (BoolLit True ) = l+              decide  _              (BoolLit False) = BoolLit False+              decide  l               r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolAnd l r+          BoolOr x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit False)  r              = r+              decide (BoolLit True )  _              = BoolLit True+              decide  l              (BoolLit False) = l+              decide  _              (BoolLit True ) = BoolLit True+              decide  l               r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolOr l r+          BoolEQ x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit True )  r              = r+              decide  l              (BoolLit True ) = l+              decide  l               r+                  | Eval.judgmentallyEqual l r = BoolLit True+                  | otherwise                  = BoolEQ l r+          BoolNE x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit False)  r              = r+              decide  l              (BoolLit False) = l+              decide  l               r+                  | Eval.judgmentallyEqual l r = BoolLit False+                  | otherwise                  = BoolNE l r+          BoolIf bool true false -> decide <$> loop bool <*> loop true <*> loop false+            where+              decide (BoolLit True )  l              _              = l+              decide (BoolLit False)  _              r              = r+              decide  b              (BoolLit True) (BoolLit False) = b+              decide  b               l              r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolIf b l r+          Bytes -> pure Bytes+          BytesLit b -> pure (BytesLit b)+          Natural -> pure Natural+          NaturalLit n -> pure (NaturalLit n)+          NaturalFold -> pure NaturalFold+          NaturalBuild -> pure NaturalBuild+          NaturalIsZero -> pure NaturalIsZero+          NaturalEven -> pure NaturalEven+          NaturalOdd -> pure NaturalOdd+          NaturalToInteger -> pure NaturalToInteger+          NaturalShow -> pure NaturalShow+          NaturalSubtract -> pure NaturalSubtract+          NaturalPlus x y -> decide <$> loop x <*> loop y+            where+              decide (NaturalLit 0)  r             = r+              decide  l             (NaturalLit 0) = l+              decide (NaturalLit m) (NaturalLit n) = NaturalLit (m + n)+              decide  l              r             = NaturalPlus l r+          NaturalTimes x y -> decide <$> loop x <*> loop y+            where+              decide (NaturalLit 1)  r             = r+              decide  l             (NaturalLit 1) = l+              decide (NaturalLit 0)  _             = NaturalLit 0+              decide  _             (NaturalLit 0) = NaturalLit 0+              decide (NaturalLit m) (NaturalLit n) = NaturalLit (m * n)+              decide  l              r             = NaturalTimes l r+          Integer -> pure Integer+          IntegerLit n -> pure (IntegerLit n)+          IntegerClamp -> pure IntegerClamp+          IntegerNegate -> pure IntegerNegate+          IntegerShow -> pure IntegerShow+          IntegerToDouble -> pure IntegerToDouble+          Double -> pure Double+          DoubleLit n -> pure (DoubleLit n)+          DoubleShow -> pure DoubleShow+          Text -> pure Text+          TextLit (Chunks xys z) -> do+              chunks' <- mconcat <$> chunks+              case chunks' of+                  Chunks [("", x)] "" -> pure x+                  c                   -> pure (TextLit c)+            where+              chunks =+                ((++ [Chunks [] z]) . concat) <$> traverse process xys++              process (x, y) = do+                y' <- loop y+                case y' of+                  TextLit c -> pure [Chunks [] x, c]+                  _         -> pure [Chunks [(x, y')] mempty]+          TextAppend x y -> loop (TextLit (Chunks [("", x), ("", y)] ""))+          TextReplace -> pure TextReplace+          TextShow -> pure TextShow+          Date -> pure Date+          DateLiteral d -> pure (DateLiteral d)+          DateShow -> pure DateShow+          Time -> pure Time+          TimeLiteral t p -> pure (TimeLiteral t p)+          TimeShow -> pure TimeShow+          TimeZone -> pure TimeZone+          TimeZoneLiteral z -> pure (TimeZoneLiteral z)+          TimeZoneShow -> pure TimeZoneShow+          List -> pure List+          ListLit t es+              | Data.Sequence.null es -> ListLit <$> t' <*> pure Data.Sequence.empty+              | otherwise             -> ListLit Nothing <$> es'+            where+              t'  = traverse loop t+              es' = traverse loop es+          ListAppend x y -> decide <$> loop x <*> loop y+            where+              decide (ListLit _ m)  r            | Data.Sequence.null m = r+              decide  l            (ListLit _ n) | Data.Sequence.null n = l+              decide (ListLit t m) (ListLit _ n)                        = ListLit t (m <> n)+              decide  l             r                                   = ListAppend l r+          ListBuild -> pure ListBuild+          ListFold -> pure ListFold+          ListLength -> pure ListLength+          ListHead -> pure ListHead+          ListLast -> pure ListLast+          ListIndexed -> pure ListIndexed+          ListReverse -> pure ListReverse+          Optional -> pure Optional+          Some a -> Some <$> a'+            where+              a' = loop a+          None -> pure None+          Record kts -> Record . Dhall.Map.sort <$> kts'+            where+              f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+              kts' = traverse f kts+          RecordLit kvs -> RecordLit . Dhall.Map.sort <$> kvs'+            where+              f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+              kvs' = traverse f kvs+          Union kts -> Union . Dhall.Map.sort <$> kts'+            where+              kts' = traverse (traverse loop) kts+          Combine cs mk x y -> decide <$> loop x <*> loop y+            where+              decide (RecordLit m) r | Data.Foldable.null m =+                  r+              decide l (RecordLit n) | Data.Foldable.null n =+                  l+              decide (RecordLit m) (RecordLit n) =+                  RecordLit (Dhall.Map.unionWith f m n)+                where+                  f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+                    Syntax.makeRecordField $ decide expr expr'+              decide l r =+                  Combine cs mk l r+          CombineTypes cs x y -> decide <$> loop x <*> loop y+            where+              decide (Record m) r | Data.Foldable.null m =+                  r+              decide l (Record n) | Data.Foldable.null n =+                  l+              decide (Record m) (Record n) =+                  Record (Dhall.Map.unionWith f m n)+                where+                  f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+                    Syntax.makeRecordField $ decide expr expr'+              decide l r =+                  CombineTypes cs l r+          Prefer cs _ x y -> decide <$> loop x <*> loop y+            where+              decide (RecordLit m) r | Data.Foldable.null m =+                  r+              decide l (RecordLit n) | Data.Foldable.null n =+                  l+              decide (RecordLit m) (RecordLit n) =+                  RecordLit (Dhall.Map.union n m)+              decide l r | Eval.judgmentallyEqual l r =+                  l+              decide l r =+                  Prefer cs PreferFromSource l r+          RecordCompletion x y ->+              loop (Annot (Prefer mempty PreferFromCompletion (Field x def) y) (Field x typ))+            where+              def = Syntax.makeFieldSelection "default"+              typ = Syntax.makeFieldSelection "Type"+          Merge x y t      -> do+              x' <- loop x+              y' <- loop y+              case x' of+                  RecordLit kvsX ->+                      case y' of+                          Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+                              case Dhall.Map.lookup kY ktsY of+                                  Just Nothing ->+                                      case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+                                          Just vX -> return vX+                                          Nothing -> Merge x' y' <$> t'+                                  _ ->+                                      Merge x' y' <$> t'+                          App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) vY ->+                              case Dhall.Map.lookup kY ktsY of+                                  Just (Just _) ->+                                      case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+                                          Just vX -> loop (App vX vY)+                                          Nothing -> Merge x' y' <$> t'+                                  _ ->+                                      Merge x' y' <$> t'+                          Some a ->+                              case recordFieldValue <$> Dhall.Map.lookup "Some" kvsX of+                                  Just vX -> loop (App vX a)+                                  Nothing -> Merge x' y' <$> t'+                          App None _ ->+                              case recordFieldValue <$> Dhall.Map.lookup "None" kvsX of+                                  Just vX -> return vX+                                  Nothing -> Merge x' y' <$> t'+                          _ -> Merge x' y' <$> t'+                  _ -> Merge x' y' <$> t'+            where+              t' = traverse loop t+          ToMap x t        -> do+              x' <- loop x+              t' <- traverse loop t+              case x' of+                  RecordLit kvsX -> do+                      let entry (key, value) =+                              RecordLit+                                  (Dhall.Map.fromList+                                      [ ("mapKey"  , Syntax.makeRecordField $ TextLit (Chunks [] key))+                                      , ("mapValue", Syntax.makeRecordField value                  )+                                      ]+                                  )++                      let keyValues = Data.Sequence.fromList (map entry (Dhall.Map.toList $ recordFieldValue <$> kvsX))++                      let listType = case t' of+                              Just _ | null keyValues ->+                                  t'+                              _ ->+                                  Nothing++                      return (ListLit listType keyValues)+                  _ ->+                      return (ToMap x' t')+          ShowConstructor x -> do+              x' <- loop x+              return $ case x' of+                  Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+                      case Dhall.Map.lookup kY ktsY of+                          Just Nothing -> TextLit (Chunks [] kY)+                          _ -> ShowConstructor x'+                  App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) _ ->+                      case Dhall.Map.lookup kY ktsY of+                          Just (Just _) -> TextLit (Chunks [] kY)+                          _ -> ShowConstructor x'+                  Some _ ->+                      TextLit (Chunks [] "Some")+                  App None _ ->+                      TextLit (Chunks [] "None")+                  _ -> ShowConstructor x'+          Field r k@FieldSelection{fieldSelectionLabel = x}        -> do+              let singletonRecordLit v = RecordLit (Dhall.Map.singleton x v)++              r' <- loop r+              case r' of+                  RecordLit kvs ->+                      case Dhall.Map.lookup x kvs of+                          Just v  -> pure $ recordFieldValue v+                          Nothing -> Field <$> (RecordLit <$> traverse (Syntax.recordFieldExprs loop) kvs) <*> pure k+                  Project r_ _ -> loop (Field r_ k)+                  Prefer cs _ (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Prefer cs PreferFromSource (singletonRecordLit v) r_) k)+                      Nothing -> loop (Field r_ k)+                  Prefer _ _ l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+                      Just v -> pure $ recordFieldValue v+                      Nothing -> loop (Field l k)+                  Combine cs m (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Combine cs m (singletonRecordLit v) r_) k)+                      Nothing -> loop (Field r_ k)+                  Combine cs m l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Combine cs m l (singletonRecordLit v)) k)+                      Nothing -> loop (Field l k)+                  _ -> pure (Field r' k)+          Project x (Left fields)-> do+              x' <- loop x+              let fieldsSet = Data.Set.fromList fields+              case x' of+                  RecordLit kvs ->+                      pure (RecordLit (Dhall.Map.restrictKeys kvs fieldsSet))+                  Project y _ ->+                      loop (Project y (Left fields))+                  Prefer cs _ l (RecordLit rKvs) -> do+                      let rKs = Dhall.Map.keysSet rKvs+                      let l' = Project l (Left (Data.Set.toList (Data.Set.difference fieldsSet rKs)))+                      let r' = RecordLit (Dhall.Map.restrictKeys rKvs fieldsSet)+                      loop (Prefer cs PreferFromSource l' r')+                  _ | null fields -> pure (RecordLit mempty)+                    | otherwise   -> pure (Project x' (Left (Data.Set.toList (Data.Set.fromList fields))))+          Project r (Right e1) -> do+              e2 <- loop e1++              case e2 of+                  Record kts ->+                      loop (Project r (Left (Data.Set.toList (Dhall.Map.keysSet kts))))+                  _ -> do+                      r' <- loop r+                      pure (Project r' (Right e2))+          Assert t -> do+              t' <- loop t++              pure (Assert t')+          Equivalent cs l r -> do+              l' <- loop l+              r' <- loop r++              pure (Equivalent cs l' r')+          With r ks v -> do+              r' <- loop r+              v' <- loop v++              case r' of+                  RecordLit kvs ->+                      case ks of+                          WithLabel k :| [] ->+                              return (RecordLit (Dhall.Map.insert k (Syntax.makeRecordField v') kvs))+                          WithLabel k₀ :| k₁ : ks' -> do+                              let e₁ =+                                      case Dhall.Map.lookup k₀ kvs of+                                          Nothing  -> RecordLit mempty+                                          Just val -> Syntax.recordFieldValue val++                              e₂ <- loop (With e₁ (k₁ :| ks') v')++                              return (RecordLit (Dhall.Map.insert k₀ (Syntax.makeRecordField e₂) kvs))+                          WithQuestion :| _ -> do+                              return (With r' ks v')+                  Some t ->+                      case ks of+                          WithQuestion :| [] -> do+                              return (Some v')+                          WithQuestion :| k : ks' -> do+                              w <- loop (With t (k :| ks') v)+                              return (Some w)+                          WithLabel _ :| _ ->+                              return (With r' ks v')+                  App None _T ->+                      case ks of+                          WithQuestion :| _ ->+                              return (App None _T)+                          WithLabel _ :| _ ->+                              return (With r' ks v')+                  _ ->+                      return (With r' ks v')+          Note _ e' -> loop e'+          ImportAlt l _r -> loop l+          Embed a -> pure (Embed a)++-- | Use this to wrap you embedded functions (see `normalizeWith`) to make them+--   polymorphic enough to be used.+type NormalizerM m a = forall s. Expr s a -> m (Maybe (Expr s a))++-- | An variation on `NormalizerM` for pure normalizers+type Normalizer a = NormalizerM Identity a++-- | A reified 'Normalizer', which can be stored in structures without+-- running into impredicative polymorphism.+newtype ReifiedNormalizer a = ReifiedNormalizer+  { getReifiedNormalizer :: Normalizer a }++-- | Check if an expression is in a normal form given a context of evaluation.+--   Unlike `isNormalized`, this will fully normalize and traverse through the expression.+--+--   It is much more efficient to use `isNormalized`.+--+--  `isNormalizedWith` can fail with an `error` if you check an ill-typed+--  expression+isNormalizedWith :: (Eq s, Eq a) => Normalizer a -> Expr s a -> Bool+isNormalizedWith ctx e = e == normalizeWith (Just (ReifiedNormalizer ctx)) e++-- | Quickly check if an expression is in normal form+--+-- Given a well-typed expression @e@, @'isNormalized' e@ is equivalent to+-- @e == 'normalize' e@.+--+-- Given an ill-typed expression, 'isNormalized' may fail with an error, or+-- evaluate to either False or True!+isNormalized :: Eq a => Expr s a -> Bool+isNormalized e0 = loop (Syntax.denote e0)+  where+    loop e = case e of+      Const _ -> True+      Var _ -> True+      Lam _ (FunctionBinding Nothing _ Nothing Nothing a) b -> loop a && loop b+      Lam _ _ _ -> False+      Pi _ _ a b -> loop a && loop b+      App f a -> loop f && loop a && case App f a of+          App (Lam _ _ _) _ -> False+          App (App (App (App NaturalFold (NaturalLit _)) _) _) _ -> False+          App NaturalBuild _ -> False+          App NaturalIsZero (NaturalLit _) -> False+          App NaturalEven (NaturalLit _) -> False+          App NaturalOdd (NaturalLit _) -> False+          App NaturalShow (NaturalLit _) -> False+          App DateShow (DateLiteral _) -> False+          App TimeShow (TimeLiteral _ _) -> False+          App TimeZoneShow (TimeZoneLiteral _) -> False+          App (App NaturalSubtract (NaturalLit _)) (NaturalLit _) -> False+          App (App NaturalSubtract (NaturalLit 0)) _ -> False+          App (App NaturalSubtract _) (NaturalLit 0) -> False+          App (App NaturalSubtract x) y -> not (Eval.judgmentallyEqual x y)+          App NaturalToInteger (NaturalLit _) -> False+          App IntegerNegate (IntegerLit _) -> False+          App IntegerClamp (IntegerLit _) -> False+          App IntegerShow (IntegerLit _) -> False+          App IntegerToDouble (IntegerLit _) -> False+          App DoubleShow (DoubleLit _) -> False+          App (App ListBuild _) _ -> False+          App (App (App (App (App (App ListFold _) (ListLit _ _)) _) _) _) _ -> False+          App (App ListLength _) (ListLit _ _) -> False+          App (App ListHead _) (ListLit _ _) -> False+          App (App ListLast _) (ListLit _ _) -> False+          App (App ListIndexed _) (ListLit _ _) -> False+          App (App ListReverse _) (ListLit _ _) -> False+          App TextShow (TextLit (Chunks [] _)) ->+              False+          App (App (App TextReplace (TextLit (Chunks [] ""))) _) _ ->+              False+          App (App (App TextReplace (TextLit (Chunks [] _))) _) (TextLit _) ->+              False+          _ -> True+      Let _ _ -> False+      Annot _ _ -> False+      Bool -> True+      BoolLit _ -> True+      BoolAnd x y -> loop x && loop y && decide x y+        where+          decide (BoolLit _)  _          = False+          decide  _          (BoolLit _) = False+          decide  l           r          = not (Eval.judgmentallyEqual l r)+      BoolOr x y -> loop x && loop y && decide x y+        where+          decide (BoolLit _)  _          = False+          decide  _          (BoolLit _) = False+          decide  l           r          = not (Eval.judgmentallyEqual l r)+      BoolEQ x y -> loop x && loop y && decide x y+        where+          decide (BoolLit True)  _             = False+          decide  _             (BoolLit True) = False+          decide  l              r             = not (Eval.judgmentallyEqual l r)+      BoolNE x y -> loop x && loop y && decide x y+        where+          decide (BoolLit False)  _               = False+          decide  _              (BoolLit False ) = False+          decide  l               r               = not (Eval.judgmentallyEqual l r)+      BoolIf x y z ->+          loop x && loop y && loop z && decide x y z+        where+          decide (BoolLit _)  _              _              = False+          decide  _          (BoolLit True) (BoolLit False) = False+          decide  _           l              r              = not (Eval.judgmentallyEqual l r)+      Bytes -> True+      BytesLit _ -> True+      Natural -> True+      NaturalLit _ -> True+      NaturalFold -> True+      NaturalBuild -> True+      NaturalIsZero -> True+      NaturalEven -> True+      NaturalOdd -> True+      NaturalShow -> True+      NaturalSubtract -> True+      NaturalToInteger -> True+      NaturalPlus x y -> loop x && loop y && decide x y+        where+          decide (NaturalLit 0)  _             = False+          decide  _             (NaturalLit 0) = False+          decide (NaturalLit _) (NaturalLit _) = False+          decide  _              _             = True+      NaturalTimes x y -> loop x && loop y && decide x y+        where+          decide (NaturalLit 0)  _             = False+          decide  _             (NaturalLit 0) = False+          decide (NaturalLit 1)  _             = False+          decide  _             (NaturalLit 1) = False+          decide (NaturalLit _) (NaturalLit _) = False+          decide  _              _             = True+      Integer -> True+      IntegerLit _ -> True+      IntegerClamp -> True+      IntegerNegate -> True+      IntegerShow -> True+      IntegerToDouble -> True+      Double -> True+      DoubleLit _ -> True+      DoubleShow -> True+      Text -> True+      TextLit (Chunks [("", _)] "") -> False+      TextLit (Chunks xys _) -> all (all check) xys+        where+          check y = loop y && case y of+              TextLit _ -> False+              _         -> True+      TextAppend _ _ -> False+      TextReplace -> True+      TextShow -> True+      Date -> True+      DateLiteral _ -> True+      DateShow -> True+      Time -> True+      TimeLiteral _ _ -> True+      TimeShow -> True+      TimeZone -> True+      TimeZoneLiteral _ -> True+      TimeZoneShow -> True+      List -> True+      ListLit t es -> all loop t && all loop es+      ListAppend x y -> loop x && loop y && decide x y+        where+          decide (ListLit _ m)  _            | Data.Sequence.null m = False+          decide  _            (ListLit _ n) | Data.Sequence.null n = False+          decide (ListLit _ _) (ListLit _ _)                        = False+          decide  _             _                                   = True+      ListBuild -> True+      ListFold -> True+      ListLength -> True+      ListHead -> True+      ListLast -> True+      ListIndexed -> True+      ListReverse -> True+      Optional -> True+      Some a -> loop a+      None -> True+      Record kts -> Dhall.Map.isSorted kts && all decide kts+        where+          decide (RecordField Nothing exp' Nothing Nothing) = loop exp'+          decide _ = False+      RecordLit kvs -> Dhall.Map.isSorted kvs && all decide kvs+        where+          decide (RecordField Nothing exp' Nothing Nothing) = loop exp'+          decide _ = False+      Union kts -> Dhall.Map.isSorted kts && all (all loop) kts+      Combine _ _ x y -> loop x && loop y && decide x y+        where+          decide (RecordLit m) _ | Data.Foldable.null m = False+          decide _ (RecordLit n) | Data.Foldable.null n = False+          decide (RecordLit _) (RecordLit _) = False+          decide  _ _ = True+      CombineTypes _ x y -> loop x && loop y && decide x y+        where+          decide (Record m) _ | Data.Foldable.null m = False+          decide _ (Record n) | Data.Foldable.null n = False+          decide (Record _) (Record _) = False+          decide  _ _ = True+      Prefer _ _ x y -> loop x && loop y && decide x y+        where+          decide (RecordLit m) _ | Data.Foldable.null m = False+          decide _ (RecordLit n) | Data.Foldable.null n = False+          decide (RecordLit _) (RecordLit _) = False+          decide l r = not (Eval.judgmentallyEqual l r)+      RecordCompletion _ _ -> False+      Merge x y t -> loop x && loop y && all loop t && case x of+          RecordLit _ -> case y of+              Field (Union _) _ -> False+              App (Field (Union _) _) _ -> False+              Some _ -> False+              App None _ -> False+              _ -> True+          _ -> True+      ToMap x t -> case x of+          RecordLit _ -> False+          _ -> loop x && all loop t+      ShowConstructor x -> loop x && case x of+          Field (Union kts) (Syntax.fieldSelectionLabel -> k) ->+              case Dhall.Map.lookup k kts of+                  Just Nothing -> False+                  _            -> True+          App (Field (Union kts) (Syntax.fieldSelectionLabel -> k)) _ ->+              case Dhall.Map.lookup k kts of+                  Just (Just _) -> False+                  _             -> True+          Some _ -> False+          App None _ -> False+          _ -> True+      Field r (FieldSelection Nothing k Nothing) -> case r of+          RecordLit _ -> False+          Project _ _ -> False+          Prefer _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+          Prefer _ _ _ (RecordLit _) -> False+          Combine _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+          Combine _ _ _ (RecordLit m) -> Dhall.Map.keys m == [k] && loop r+          _ -> loop r+      Field _ _ -> False+      Project r p -> loop r &&+          case p of+              Left s -> case r of+                  RecordLit _ -> False+                  Project _ _ -> False+                  Prefer _ _ _ (RecordLit _) -> False+                  _ -> not (null s) && Data.Set.toList (Data.Set.fromList s) == s+              Right e' -> case e' of+                  Record _ -> False+                  _ -> loop e'+      Assert t -> loop t+      Equivalent _ l r -> loop l && loop r+      With{} -> False+      Note _ e' -> loop e'+      ImportAlt _ _ -> False+      Embed _ -> True++{-| Detect if the given variable is free within the given expression++>>> "x" `freeIn` "x"+True+>>> "x" `freeIn` "y"+False+>>> "x" `freeIn` Lam mempty (Syntax.makeFunctionBinding "x" (Const Type)) "x"+False+-}+freeIn :: Eq a => Var -> Expr s a -> Bool+variable@(V var i) `freeIn` expression =+    subst variable (Var (V var (i + 1))) strippedExpression+      /= strippedExpression+  where+    denote' :: Expr t b -> Expr () b+    denote' = Syntax.denote++    strippedExpression = denote' expression+{-# INLINABLE freeIn #-}++{- $setup+>>> import Dhall.Syntax (Const(..))+-}
+ src/Dhall/Optics.hs view
@@ -0,0 +1,85 @@+{-| This module contains some useful utilities copy-and-pasted from the @lens@+    library to avoid a dependency which are used internally and also re-exported+    for convenience+-}++{-# LANGUAGE RankNTypes #-}++module Dhall.Optics {-# DEPRECATED "Use the definitions from Lens.Micro of the microlens package directly." #-}+    ( Optic+    , Optic'+       -- * Utilities+    , anyOf+    , rewriteOf+    , transformOf+    , rewriteMOf+    , transformMOf+    , mapMOf+    , cosmosOf+    , to+    , foldOf+    ) where++import Control.Applicative        (Const (..), WrappedMonad (..))+import Data.Monoid                (Any (..))+import Lens.Micro                 (ASetter, LensLike, Traversal, SimpleGetter)+import Lens.Micro.Internal        ((#.))++import qualified Lens.Micro++-- | Identical to @"Control.Lens.Getter".`Control.Lens.Getter.Getting`@+type Getting r s a = (a -> Const r a) -> s -> Const r s++-- | Identical to @"Control.Lens.Type".`Control.Lens.Type.Optic`@+type Optic p f s t a b = p a (f b) -> p s (f t)++-- | Identical to @"Control.Lens.Type".`Control.Lens.Type.Optic'`@+type Optic' p f s a = Optic p f s s a a++-- | Identical to @"Control.Lens".`Control.Lens.anyOf`@+anyOf :: Getting Any s a -> (a -> Bool) -> s -> Bool+anyOf = Lens.Micro.anyOf+{-# INLINE anyOf #-}++-- | Identical to @"Control.Lens".`Control.Lens.rewriteOf`@+rewriteOf :: ASetter a b a b -> (b -> Maybe a) -> a -> b+rewriteOf = Lens.Micro.rewriteOf+{-# INLINE rewriteOf #-}++-- | Identical to @"Control.Lens".`Control.Lens.transformOf`@+transformOf :: ASetter a b a b -> (b -> b) -> a -> b+transformOf = Lens.Micro.transformOf+{-# INLINE transformOf #-}++-- | Identical to @"Control.Lens".`Control.Lens.rewriteMOf`@+rewriteMOf+    :: Monad m+    => LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b+rewriteMOf = Lens.Micro.rewriteMOf+{-# INLINE rewriteMOf #-}++-- | Identical to @"Control.Lens".`Control.Lens.transformMOf`@+transformMOf+    :: Monad m => LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b+transformMOf = Lens.Micro.transformMOf+{-# INLINE transformMOf #-}++-- | Identical to @"Control.Lens".`Control.Lens.mapMOf`@+mapMOf :: LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t+mapMOf = Lens.Micro.mapMOf+{-# INLINE mapMOf #-}++-- | Identical to @"Control.Lens.Plated".`Control.Lens.Plated.cosmosOf`@+cosmosOf :: Traversal s t s t -> Traversal s t s b+cosmosOf = Lens.Micro.cosmosOf+{-# INLINE cosmosOf #-}++-- | Identical to @"Control.Lens.Getter".`Control.Lens.Getter.to`@+to :: (s -> a) -> SimpleGetter s a+to = Lens.Micro.to+{-# INLINE to #-}++-- | Identical to @"Control.Lens.Fold".`Control.Lens.Fold.foldOf`@+foldOf :: Getting a s a -> s -> a+foldOf l = getConst #. l Const+{-# INLINE foldOf #-}
+ src/Dhall/Package.hs view
@@ -0,0 +1,297 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase   #-}+{-# LANGUAGE MultiWayIf   #-}++-- | Create a package.dhall from files and directory contents.++module Dhall.Package+    ( Options+    , defaultOptions+    , characterSet+    , packageFileName+    , packagingMode+    , PackagingMode(..)+    , writePackage+    , getPackagePathAndContent+    , PackageError(..)+    ) where++import           Control.Exception  (Exception, throwIO)+import           Control.Monad+import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Text          (Text)+import qualified Data.Text          as Text+import           Data.Traversable   (for)+import           Dhall.Core+    ( Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , RecordField (..)+    , makeRecordField+    )+import           Dhall.Map          (Map)+import qualified Dhall.Map          as Map+import           Dhall.Pretty       (CharacterSet (..))+import qualified Dhall.Pretty+import           Dhall.Util         (_ERROR, renderExpression)+import           Lens.Micro         (Lens', lens)+import           System.Directory+import           System.FilePath++-- | Options for package creation.+data Options = Options+    { optionsCharacterSet :: CharacterSet+    , optionsPackageFileName :: String+    , optionsPackagingMode :: PackagingMode+    }++-- | The default options used for packaging.+--+-- The default values for the different settings are:+--+--  * The character set used is the one given by 'Dhall.Pretty.defaultCharacterSet'.+--  * The package file name is @package.dhall@.+--  * The packaging mode is 'OnlyThisPackage'.+defaultOptions :: Options+defaultOptions = Options+    { optionsCharacterSet = Dhall.Pretty.defaultCharacterSet+    , optionsPackageFileName = "package.dhall"+    , optionsPackagingMode = OnlyThisPackage+    }++-- | Access the character set used to render the package content.+characterSet :: Lens' Options CharacterSet+characterSet = lens optionsCharacterSet (\s x -> s { optionsCharacterSet = x })++-- | Access the file name used for the package file.+packageFileName :: Lens' Options String+packageFileName =+    lens optionsPackageFileName (\s x -> s { optionsPackageFileName = x })++-- | Access the packaging mode.+-- See the documentation of 'getPackagePathAndContent'.+packagingMode :: Lens' Options PackagingMode+packagingMode =+    lens optionsPackagingMode (\s x -> s { optionsPackagingMode = x })++-- | Whether to recursively create a package for each subdirectory or not.+-- See the documentation of 'getPackagePathAndContent'.+data PackagingMode+    = OnlyThisPackage+    | RecursiveSubpackages++-- | Create a package.dhall from files and directory contents.+-- For a description of how the package file is constructed see+-- 'getPackagePathAndContent'.+writePackage :: Options -> NonEmpty FilePath -> IO ()+writePackage options inputs = do+    (outputPath, expr) <- getPackagePathAndContent options inputs+    renderExpression (optionsCharacterSet options) True (Just outputPath) expr++-- | Get the path and the Dhall expression for a package file.+--+-- The location of the resulting package file is determined by the first path of the second argument:+--+--   * If it is a directory, it is also the output directory and the package+--     file will be placed there.+--+--   * If it is a file, then the directory that file resides in is the output+--     directory and the package file will be placed there.+--+-- All inputs provided as the second argument must be either in the output+-- directory or below it. They are processed depending on whether+-- the path points to a directory or a file:+--+--   * If the path points to a directory, all files with a @.dhall@ extensions+--     in that directory are included in the package.+--+--     If you passed `Recurse` to the this function, then in addition to these+--     files all subdirectories are traversed and a sub-package created for each+--     one. That sub-package will be included in the package too.+--+--   * If the path points to a regular file, it is included in the package+--     unless it is the path of the package file itself.+--+getPackagePathAndContent+    :: Options+    -> NonEmpty FilePath+    -> IO (FilePath, Expr s Import)+getPackagePathAndContent options (path :| paths) = do+    outputDir <- do+        isDirectory <- doesDirectoryExist path+        return $ if isDirectory then path else takeDirectory path+    outputDir' <- addTrailingPathSeparator <$> makeAbsolute (normalise outputDir)++    -- Check if the supplied @dir@ argument points to a filesystem entry below+    -- the output directory and return the path relative to the output directory.+    let checkOutputDir dir = do+            absoluteDir <- addTrailingPathSeparator <$> makeAbsolute (normalise dir)+            let relativeDir = makeRelative outputDir' absoluteDir+            unless (isRelative relativeDir) $+                throwIO $ AmbiguousOutputDirectory outputDir dir+            return relativeDir++    resultMap <- go Map.empty checkOutputDir (path:paths)+    return (outputDir </> outputFn, RecordLit $ Map.sort resultMap)+    where+        go+            :: Map Text (RecordField s Import)+            -> (FilePath -> IO FilePath)+            -> [FilePath]+            -> IO (Map Text (RecordField s Import))+        go !acc _checkOutputDir [] = return acc+        go !acc checkOutputDir (p:ps) = do+            isDirectory <- doesDirectoryExist p+            isFile <- doesFileExist p+            if | isDirectory -> do+                    void $ checkOutputDir p+                    entries <- listDirectory p+                    (dhallFiles, subdirectories) <- foldMap+                        ( \entry -> do+                            let entry' = p </> entry+                            isDirectoryEntry <- doesDirectoryExist entry'+                            return $ if isDirectoryEntry+                                then (mempty, [entry'])+                                else if hasDhallExtension entry+                                    then ([entry'], mempty)+                                    else mempty+                        ) entries+                    subpackages <- case optionsPackagingMode options of+                        RecursiveSubpackages ->+                            for subdirectories $ \subdirectory -> do+                                writePackage options (subdirectory :| [])+                                return (subdirectory </> outputFn)+                        OnlyThisPackage -> return []+                    go acc checkOutputDir (dhallFiles <> subpackages <> ps)+               | isFile -> do+                    dir <- checkOutputDir $ takeDirectory p++                    let p' = normalise $ dir </> takeFileName p++                    let resultMap = if p' == outputFn+                            then Map.empty+                            else filepathToMap outputFn p'++                    acc' <- mergeMaps acc resultMap+                    go acc' checkOutputDir ps+                | otherwise -> throwIO $ InvalidPath p++        hasDhallExtension :: FilePath -> Bool+        hasDhallExtension entry = takeExtension entry == ".dhall"++        outputFn :: String+        outputFn = optionsPackageFileName options++-- | Construct a nested 'Map' from a 'FilePath'.+-- For example, the filepath @some/file/path.dhall@ will result in something+-- similar to the following:+--+-- fromList+--   [ ("some", fromList+--     [ ("file", fromList+--       [ ("path", ./some/file/path.dhall)+--       ])+--     ])+--   ])+--+-- ... where ./some/file/path.dhall is a Dhall import. If the last component+-- equals the value passed in the @outputFn@ argument we produce a slightly+-- different result. Consider for example the Dhall Prelude: We have some+-- sub-packages there like @List/package.dhall@. If we want to construct the+-- top-level @package.dhall@ we want an entry like+--+-- > List = ./List/package.dhall+--+-- in there and not:+--+-- > List = { package = ./List/package.dhall }+--+filepathToMap :: FilePath -> FilePath -> Map Text (RecordField s Import)+filepathToMap outputFn = go [] . splitDirectories+    where+        go acc [] = go acc ["."]+        go !acc [x] =+                    let import_ = Import+                            { importHashed = ImportHashed+                                { hash = Nothing+                                , importType = Local Here File+                                    { directory = Directory acc+                                    , file = Text.pack x+                                    }+                                }+                            , importMode = Code+                            }+            in Map.singleton (Text.pack $ dropExtension x) $ makeRecordField $ Embed import_+        go !acc [x, y] | y == outputFn =+                    let import_ = Import+                            { importHashed = ImportHashed+                                { hash = Nothing+                                , importType = Local Here File+                                    { directory = Directory (Text.pack x : acc)+                                    , file = Text.pack y+                                    }+                                }+                            , importMode = Code+                            }+            in Map.singleton (Text.pack x) $ makeRecordField $ Embed import_+        go !acc (x:xs) = Map.singleton (Text.pack x) $ makeRecordField $ RecordLit $ go (Text.pack x : acc) xs++-- | Merge two 'Map's constructed with 'filepathToMap'.+-- It will throw an error if the arguments are not compatible with each other, e.g.+-- we cannot merge the following two maps:+--+-- > fromList [ ("file", ./file.dhall) ]+-- > fromList [ ("file", fromList [("nested", ./file/nested.dhall)]) ]+--+mergeMaps :: Map Text (RecordField s Import) -> Map Text (RecordField s Import) -> IO (Map Text (RecordField s Import))+mergeMaps x y = do+    let x' = fmap (:| []) x+        y' = fmap (:| []) y+        z = Map.unionWith (<>) x' y'+    for z $ \case+        v@RecordField{recordFieldValue = Embed{}} :| [] -> return v+        vs | Just rs <- traverse extractRecordLit vs -> makeRecordField . RecordLit . Map.sort <$> foldM mergeMaps Map.empty rs+           | otherwise -> throwIO $ IncompatiblePaths $ foldMap extractEmbeds vs+    where+        extractEmbeds :: RecordField s Import -> [Import]+        extractEmbeds RecordField{recordFieldValue = Embed import_} = [import_]+        extractEmbeds RecordField{recordFieldValue = RecordLit xs} = foldMap extractEmbeds xs+        extractEmbeds _ = mempty++        extractRecordLit :: RecordField s Import -> Maybe (Map Text (RecordField s Import))+        extractRecordLit RecordField{recordFieldValue = RecordLit xs} = Just xs+        extractRecordLit _ = Nothing++-- | Exception thrown when creating a package file.+data PackageError+    = AmbiguousOutputDirectory FilePath FilePath+    | IncompatiblePaths [Import]+    | InvalidPath FilePath++instance Exception PackageError++instance Show PackageError where+    show (AmbiguousOutputDirectory dir1 dir2) =+        _ERROR <> ": ❰dhall package❱ failed because the inputs make it impossible to\n\+        \determine the output directory of the package file. You asked to include files\n\+        \from the following directories in the package:\n\+        \\n" <> dir1 <>+        "\n" <> dir2 <>+        "\n\n\+        \Although those paths might point to the same location they are not lexically the\n\+        \same."++    show (IncompatiblePaths imports) =+        _ERROR <> ": ❰dhall package❱ failed because some inputs are not compatible with\n\+        \each other:\n\+        \\n" <> unlines (map (show . Dhall.Pretty.prettyExpr . Embed) imports)++    show (InvalidPath fp) =+        _ERROR <> ": ❰dhall package❱ failed because the input does not exist or is\n\+        \neither a directory nor a regular file:\n\+        \\n" <> fp
src/Dhall/Parser.hs view
@@ -1,1579 +1,132 @@-{-# LANGUAGE CPP               #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE RecordWildCards            #-}---- | This module contains Dhall's parsing logic--module Dhall.Parser (-    -- * Utilities-      exprFromText-    , exprAndHeaderFromText--    -- * Parsers-    , expr, exprA--    -- * Types-    , Src(..)-    , ParseError(..)-    , Parser(..)-    ) where--import Control.Applicative (Alternative(..), liftA2, optional)-import Control.Exception (Exception)-import Control.Monad (MonadPlus)-import Data.ByteString (ByteString)-import Data.Functor (void)-import Data.HashMap.Strict.InsOrd (InsOrdHashMap)-import Data.Monoid ((<>))-import Data.Sequence (ViewL(..))-import Data.Scientific (Scientific)-import Data.String (IsString(..))-import Data.Text.Buildable (Buildable(..))-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-import Data.Typeable (Typeable)-import Dhall.Core-import Numeric.Natural (Natural)-import Prelude hiding (const, pi)-import Text.PrettyPrint.ANSI.Leijen (Doc)-import Text.Parser.Combinators (choice, try, (<?>))-import Text.Parser.Token (TokenParsing(..))-import Text.Trifecta-    (CharParsing, DeltaParsing, MarkParsing, Parsing, Result(..))-import Text.Trifecta.Delta (Delta)--import qualified Control.Monad-import qualified Crypto.Hash-import qualified Data.ByteString.Lazy-import qualified Data.Char-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.HashSet-import qualified Data.List-import qualified Data.Sequence-import qualified Data.Text-import qualified Data.Text.Encoding-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Builder-import qualified Data.Text.Lazy.Encoding-import qualified Text.Parser.Char-import qualified Text.Parser.Combinators-import qualified Text.Parser.Token-import qualified Text.Parser.Token.Style-import qualified Text.PrettyPrint.ANSI.Leijen-import qualified Text.Trifecta---- | Source code extract-data Src = Src Delta Delta ByteString deriving (Eq, Show)--instance Buildable Src where-    build (Src begin _ bytes) =-            build text <> "\n"-        <>  "\n"-        <>  build (show (Text.PrettyPrint.ANSI.Leijen.pretty begin))-        <>  "\n"-      where-        bytes' = Data.ByteString.Lazy.fromStrict bytes--        text = Data.Text.Lazy.strip (Data.Text.Lazy.Encoding.decodeUtf8 bytes')--{-| A `Parser` that is almost identical to-    @"Text.Trifecta".`Text.Trifecta.Parser`@ except treating Haskell-style-    comments as whitespace--}-newtype Parser a = Parser { unParser :: Text.Trifecta.Parser a }-    deriving-    (   Functor-    ,   Applicative-    ,   Monad-    ,   Alternative-    ,   MonadPlus-    ,   Parsing-    ,   CharParsing-    ,   DeltaParsing-    ,   MarkParsing Delta-    )--instance Monoid a => Monoid (Parser a) where-    mempty = pure mempty--#if MIN_VERSION_base(4,11,0)-instance Semigroup a => Semigroup (Parser a) where-    (<>) = liftA2 (<>)-#else-    mappend = liftA2 mappend-#endif--instance IsString a => IsString (Parser a) where-    fromString x = fmap fromString (Text.Parser.Char.string x)--instance TokenParsing Parser where-    someSpace =-        Text.Parser.Token.Style.buildSomeSpaceParser-            (Parser someSpace)-            Text.Parser.Token.Style.haskellCommentStyle--    nesting (Parser m) = Parser (nesting m)--    semi = Parser semi--    highlight h (Parser m) = Parser (highlight h m)--noted :: Parser (Expr Src a) -> Parser (Expr Src a)-noted parser = do-    before     <- Text.Trifecta.position-    (e, bytes) <- Text.Trifecta.slicedWith (,) parser-    after      <- Text.Trifecta.position-    return (Note (Src before after bytes) e)--count :: Monoid a => Int -> Parser a -> Parser a-count n parser = mconcat (replicate n parser)--range :: Monoid a => Int -> Int -> Parser a -> Parser a-range minimumBound maximumMatches parser =-    count minimumBound parser <> loop maximumMatches-  where-    loop 0 = mempty-    loop n = (parser <> loop (n - 1)) <|> mempty--option :: (Alternative f, Monoid a) => f a -> f a-option p = p <|> pure mempty--star :: (Alternative f, Monoid a) => f a -> f a-star p = plus p <|> pure mempty--plus :: (Alternative f, Monoid a) => f a -> f a-plus p = mappend <$> p <*> star p--satisfy :: (Char -> Bool) -> Parser Builder-satisfy predicate =-    fmap Data.Text.Lazy.Builder.singleton (Text.Parser.Char.satisfy predicate)--blockComment :: Parser ()-blockComment = do-    _ <- Text.Parser.Char.text "{-"-    blockCommentContinue--blockCommentChunk :: Parser ()-blockCommentChunk =-    choice-        [ blockComment  -- Nested block comment-        , character-        , endOfLine-        ]-  where-    character = void (Text.Parser.Char.satisfy predicate)-      where-        predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t'--    endOfLine = void (Text.Parser.Char.text "\r\n")--blockCommentContinue :: Parser ()-blockCommentContinue = endOfComment <|> continue-  where-    endOfComment = void (Text.Parser.Char.text "-}")--    continue = do-        blockCommentChunk-        blockCommentContinue--lineComment :: Parser ()-lineComment = do-    _ <- Text.Parser.Char.text "--"-    Text.Parser.Combinators.skipMany notEndOfLine-    endOfLine-    return ()-  where-    endOfLine =-            void (Text.Parser.Char.char '\n'  )-        <|> void (Text.Parser.Char.text "\r\n")--    notEndOfLine = void (Text.Parser.Char.satisfy predicate)-      where-        predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'---whitespaceChunk :: Parser ()-whitespaceChunk =-    choice-        [ void (Text.Parser.Char.satisfy predicate)-        , void (Text.Parser.Char.text "\r\n")-        , lineComment-        , blockComment-        ] <?> "whitespace"-  where-    predicate c = c == ' ' || c == '\t' || c == '\n'--whitespace :: Parser ()-whitespace = Text.Parser.Combinators.skipMany whitespaceChunk--alpha :: Char -> Bool-alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')--digit :: Char -> Bool-digit c = '\x30' <= c && c <= '\x39'--hexdig :: Char -> Bool-hexdig c =-        ('0' <= c && c <= '9')-    ||  ('A' <= c && c <= 'F')-    ||  ('a' <= c && c <= 'f')--hexNumber :: Parser Int-hexNumber = choice [ hexDigit, hexUpper, hexLower ]-  where-    hexDigit = do-        c <- Text.Parser.Char.satisfy predicate-        return (Data.Char.ord c - Data.Char.ord '0')-      where-        predicate c = '0' <= c && c <= '9'--    hexUpper = do-        c <- Text.Parser.Char.satisfy predicate-        return (10 + Data.Char.ord c - Data.Char.ord 'A')-      where-        predicate c = 'A' <= c && c <= 'F'--    hexLower = do-        c <- Text.Parser.Char.satisfy predicate-        return (10 + Data.Char.ord c - Data.Char.ord 'a')-      where-        predicate c = 'a' <= c && c <= 'f'--simpleLabel :: Parser Text-simpleLabel = try (do-    c  <- Text.Parser.Char.satisfy headCharacter-    cs <- many (Text.Parser.Char.satisfy tailCharacter)-    let string = c:cs-    let text = Data.Text.Lazy.pack string-    Control.Monad.guard (not (Data.HashSet.member text reservedIdentifiers))-    return text )-  where-    headCharacter c = alpha c || c == '_'--    tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/'--backtickLabel :: Parser Text-backtickLabel = do-    _ <- Text.Parser.Char.char '`'-    t <- some (Text.Parser.Char.satisfy predicate)-    _ <- Text.Parser.Char.char '`'-    return (Data.Text.Lazy.pack t)-  where-    predicate c = alpha c || digit c || elem c ("-/_:." :: String)--label :: Parser Text-label = (do-    t <- backtickLabel <|> simpleLabel-    whitespace-    return t ) <?> "label"--doubleQuotedChunk :: Parser a -> Parser (Chunks Src a)-doubleQuotedChunk embedded =-    choice-        [ interpolation-        , unescapedCharacter-        , escapedCharacter-        ]-  where-    interpolation = do-        _ <- Text.Parser.Char.text "${"-        e <- expression embedded-        _ <- Text.Parser.Char.char '}'-        return (Chunks [(mempty, e)] mempty)--    unescapedCharacter = do-        c <- Text.Parser.Char.satisfy predicate-        return (Chunks [] (Data.Text.Lazy.Builder.singleton c))-      where-        predicate c =-                ('\x20' <= c && c <= '\x21'    )-            ||  ('\x23' <= c && c <= '\x5B'    )-            ||  ('\x5D' <= c && c <= '\x10FFFF')--    escapedCharacter = do-        _ <- Text.Parser.Char.char '\\'-        c <- choice-            [ quotationMark-            , dollarSign-            , backSlash-            , forwardSlash-            , backSpace-            , formFeed-            , lineFeed-            , carriageReturn-            , tab-            , unicode-            ]-        return (Chunks [] (Data.Text.Lazy.Builder.singleton c))-      where-        quotationMark = Text.Parser.Char.char '"'--        dollarSign = Text.Parser.Char.char '$'--        backSlash = Text.Parser.Char.char '\\'--        forwardSlash = Text.Parser.Char.char '/'--        backSpace = do _ <- Text.Parser.Char.char 'b'; return '\b'--        formFeed = do _ <- Text.Parser.Char.char 'f'; return '\f'--        lineFeed = do _ <- Text.Parser.Char.char 'n'; return '\n'--        carriageReturn = do _ <- Text.Parser.Char.char 'r'; return '\r'--        tab = do _ <- Text.Parser.Char.char 't'; return '\t'--        unicode = do-            _  <- Text.Parser.Char.char 'u';-            n0 <- hexNumber-            n1 <- hexNumber-            n2 <- hexNumber-            n3 <- hexNumber-            let n = ((n0 * 16 + n1) * 16 + n2) * 16 + n3-            return (Data.Char.chr n)--doubleQuotedLiteral :: Parser a -> Parser (Chunks Src a)-doubleQuotedLiteral embedded = do-    _      <- Text.Parser.Char.char '"'-    chunks <- many (doubleQuotedChunk embedded)-    _      <- Text.Parser.Char.char '"'-    return (mconcat chunks)---- | Similar to `Dhall.Core.buildChunks` except that this doesn't bother to--- render interpolated expressions to avoid a `Buildable a` constraint.  The--- interpolated contents are not necessary for computing how much to dedent a--- multi-line string------ This also doesn't include the surrounding quotes since they would interfere--- with the whitespace detection-buildChunks :: Chunks s a -> Builder-buildChunks (Chunks a b) = foldMap buildChunk a <> escapeText b-  where-    buildChunk (c, _) = escapeText c <> "${x}"--dedent :: Chunks Src a -> Chunks Src a-dedent chunks0 = process chunks0-  where-    builder0 = buildChunks chunks0--    text0 = Data.Text.Lazy.Builder.toLazyText builder0--    lines0 = Data.Text.Lazy.lines text0--    isEmpty = Data.Text.Lazy.all Data.Char.isSpace--    nonEmptyLines = filter (not . isEmpty) lines0--    indentLength line =-        Data.Text.Lazy.length (Data.Text.Lazy.takeWhile Data.Char.isSpace line)--    shortestIndent = case nonEmptyLines of-        [] -> 0-        _  -> minimum (map indentLength nonEmptyLines)--    -- The purpose of this complicated `trimBegin`/`trimContinue` is to ensure-    -- that we strip leading whitespace without stripping whitespace after-    -- variable interpolation--    -- This is the trim function we use up until the first variable-    -- interpolation, dedenting all lines-    trimBegin =-          build-        . Data.Text.Lazy.intercalate "\n"-        . map (Data.Text.Lazy.drop shortestIndent)-        . Data.Text.Lazy.splitOn "\n"-        . Data.Text.Lazy.Builder.toLazyText--    -- This is the trim function we use after each variable interpolation-    -- where we indent each line except the first line (since it's not a true-    -- beginning of a line)-    trimContinue builder = build (Data.Text.Lazy.intercalate "\n" lines_)-      where-        text = Data.Text.Lazy.Builder.toLazyText builder--        lines_ = case Data.Text.Lazy.splitOn "\n" text of-            []   -> []-            l:ls -> l:map (Data.Text.Lazy.drop shortestIndent) ls--    -- This is the loop that drives whether or not to use `trimBegin` or-    -- `trimContinue`.  We call this function with `trimBegin`, but after the-    -- first interpolation we switch permanently to `trimContinue`-    process (Chunks ((x0, y0):xys) z) =-        Chunks ((trimBegin x0, y0):xys') (trimContinue z)-      where-        xys' = [ (trimContinue x, y) | (x, y) <- xys ]-    process (Chunks [] z) =-        Chunks [] (trimBegin z)--singleQuoteContinue :: Parser a -> Parser (Chunks Src a)-singleQuoteContinue embedded =-    choice-        [ escapeSingleQuotes-        , interpolation-        , escapeInterpolation-        , endLiteral-        , unescapedCharacter-        , tab-        , endOfLine-        ]-  where-        escapeSingleQuotes = do-            _ <- "'''" :: Parser Builder-            b <- singleQuoteContinue embedded-            return ("''" <> b)--        interpolation = do-            _ <- Text.Parser.Char.text "${"-            a <- expression embedded-            _ <- Text.Parser.Char.char '}'-            b <- singleQuoteContinue embedded-            return (Chunks [(mempty, a)] mempty <> b)--        escapeInterpolation = do-            _ <- Text.Parser.Char.text "''${"-            b <- singleQuoteContinue embedded-            return ("${" <> b)--        endLiteral = do-            _ <- Text.Parser.Char.text "''"-            return mempty--        unescapedCharacter = do-            a <- satisfy predicate-            b <- singleQuoteContinue embedded-            return (Chunks [] a <> b)-          where-            predicate c = '\x20' <= c && c <= '\x10FFFF'--        endOfLine = do-            a <- "\n" <|> "\r\n"-            b <- singleQuoteContinue embedded-            return (Chunks [] a <> b)--        tab = do-            _ <- Text.Parser.Char.char '\t'-            b <- singleQuoteContinue embedded-            return ("\t" <> b)--singleQuoteLiteral :: Parser a -> Parser (Chunks Src a)-singleQuoteLiteral embedded = do-    _ <- Text.Parser.Char.text "''"--    -- This is technically not in the grammar, but it's still equivalent to the-    -- original grammar and an easy way to discard the first character if it's-    -- a newline-    _ <- optional endOfLine--    a <- singleQuoteContinue embedded--    return (dedent a)-  where-    endOfLine =-            void (Text.Parser.Char.char '\n'  )-        <|> void (Text.Parser.Char.text "\r\n")--textLiteral :: Parser a -> Parser (Expr Src a)-textLiteral embedded = (do-    literal <- doubleQuotedLiteral embedded <|> singleQuoteLiteral embedded-    whitespace-    return (TextLit literal) ) <?> "text literal"--reserved :: Data.Text.Text -> Parser ()-reserved x = do _ <- Text.Parser.Char.text x; whitespace--_if :: Parser ()-_if = reserved "if"--_then :: Parser ()-_then = reserved "then"--_else :: Parser ()-_else = reserved "else"--_let :: Parser ()-_let = reserved "let"--_in :: Parser ()-_in = reserved "in"--_as :: Parser ()-_as = reserved "as"--_using :: Parser ()-_using = reserved "using"--_merge :: Parser ()-_merge = reserved "merge"--_constructors :: Parser ()-_constructors = reserved "constructors"--_NaturalFold :: Parser ()-_NaturalFold = reserved "Natural/fold"--_NaturalBuild :: Parser ()-_NaturalBuild = reserved "Natural/build"--_NaturalIsZero :: Parser ()-_NaturalIsZero = reserved "Natural/isZero"--_NaturalEven :: Parser ()-_NaturalEven = reserved "Natural/even"--_NaturalOdd :: Parser ()-_NaturalOdd = reserved "Natural/odd"--_NaturalToInteger :: Parser ()-_NaturalToInteger = reserved "Natural/toInteger"--_NaturalShow :: Parser ()-_NaturalShow = reserved "Natural/show"--_IntegerShow :: Parser ()-_IntegerShow = reserved "Integer/show"--_DoubleShow :: Parser ()-_DoubleShow = reserved "Double/show"--_ListBuild :: Parser ()-_ListBuild = reserved "List/build"--_ListFold :: Parser ()-_ListFold = reserved "List/fold"--_ListLength :: Parser ()-_ListLength = reserved "List/length"--_ListHead :: Parser ()-_ListHead = reserved "List/head"--_ListLast :: Parser ()-_ListLast = reserved "List/last"--_ListIndexed :: Parser ()-_ListIndexed = reserved "List/indexed"--_ListReverse :: Parser ()-_ListReverse = reserved "List/reverse"--_OptionalFold :: Parser ()-_OptionalFold = reserved "Optional/fold"--_OptionalBuild :: Parser ()-_OptionalBuild = reserved "Optional/build"--_Bool :: Parser ()-_Bool = reserved "Bool"--_Optional :: Parser ()-_Optional = reserved "Optional"--_Natural :: Parser ()-_Natural = reserved "Natural"--_Integer :: Parser ()-_Integer = reserved "Integer"--_Double :: Parser ()-_Double = reserved "Double"--_Text :: Parser ()-_Text = reserved "Text"--_List :: Parser ()-_List = reserved "List"--_True :: Parser ()-_True = reserved "True"--_False :: Parser ()-_False = reserved "False"--_Type :: Parser ()-_Type = reserved "Type"--_Kind :: Parser ()-_Kind = reserved "Kind"--_equal :: Parser ()-_equal = reserved "="--_or :: Parser ()-_or = reserved "||"--_plus :: Parser ()-_plus = reserved "+"--_textAppend :: Parser ()-_textAppend = reserved "++"--_listAppend :: Parser ()-_listAppend = reserved "#"--_and :: Parser ()-_and = reserved "&&"--_times :: Parser ()-_times = reserved "*"--_doubleEqual :: Parser ()-_doubleEqual = reserved "=="--_notEqual :: Parser ()-_notEqual = reserved "!="--_dot :: Parser ()-_dot = reserved "."--_openBrace :: Parser ()-_openBrace = reserved "{"--_closeBrace :: Parser ()-_closeBrace = reserved "}"--_openBracket :: Parser ()-_openBracket = reserved "["--_closeBracket :: Parser ()-_closeBracket = reserved "]"--_openAngle :: Parser ()-_openAngle = reserved "<"--_closeAngle :: Parser ()-_closeAngle = reserved ">"--_bar :: Parser ()-_bar = reserved "|"--_comma :: Parser ()-_comma = reserved ","--_openParens :: Parser ()-_openParens = reserved "("--_closeParens :: Parser ()-_closeParens = reserved ")"--_colon :: Parser ()-_colon = reserved ":"--_at :: Parser ()-_at = reserved "@"--_combine :: Parser ()-_combine = do-    void (Text.Parser.Char.char '∧' <?> "\"∧\"") <|> void (Text.Parser.Char.text "/\\")-    whitespace--_prefer :: Parser ()-_prefer = do-    void (Text.Parser.Char.char '⫽' <?> "\"⫽\"") <|> void (Text.Parser.Char.text "//")-    whitespace--_lambda :: Parser ()-_lambda = do-    _ <- Text.Parser.Char.satisfy predicate-    whitespace-  where-    predicate 'λ'  = True-    predicate '\\' = True-    predicate _    = False--_forall :: Parser ()-_forall = do-    void (Text.Parser.Char.char '∀' <?> "\"∀\"") <|> void (Text.Parser.Char.text "forall")-    whitespace--_arrow :: Parser ()-_arrow = do-    void (Text.Parser.Char.char '→' <?> "\"→\"") <|> void (Text.Parser.Char.text "->")-    whitespace--doubleLiteral :: Parser Scientific-doubleLiteral = (do-    sign <-  fmap (\_ -> negate) (Text.Parser.Char.char '-')-         <|> pure id-    a    <-  Text.Parser.Token.scientific-    return (sign a) ) <?> "double literal"--integerLiteral :: Parser Integer-integerLiteral = Text.Parser.Token.integer <?> "integer literal"--naturalLiteral :: Parser Natural-naturalLiteral = (do-    _ <- Text.Parser.Char.char '+'-    a <- Text.Parser.Token.natural-    return (fromIntegral a) ) <?> "natural literal"--identifier :: Parser Var-identifier = do-    x <- label--    let indexed = do-            _ <- Text.Parser.Char.char '@'-            Text.Parser.Token.natural--    n <- indexed <|> pure 0-    return (V x n)--headPathCharacter :: Char -> Bool-headPathCharacter c =-        ('\x21' <= c && c <= '\x27')-    ||  ('\x2A' <= c && c <= '\x2B')-    ||  ('\x2D' <= c && c <= '\x2E')-    ||  ('\x30' <= c && c <= '\x3B')-    ||  c == '\x3D'-    ||  ('\x3F' <= c && c <= '\x5A')-    ||  ('\x5E' <= c && c <= '\x7A')-    ||  c == '\x7C'-    ||  c == '\x7E'--pathCharacter :: Char -> Bool-pathCharacter c =-        headPathCharacter c-    ||  c == '\\'-    ||  c == '/'--fileRaw :: Parser PathType-fileRaw =-    choice-        [ try absolutePath-        , relativePath-        , parentPath-        , homePath-        ]-  where-    absolutePath = do-        _  <- Text.Parser.Char.char '/'-        a  <- Text.Parser.Char.satisfy headPathCharacter-        bs <- many (Text.Parser.Char.satisfy pathCharacter)-        let filepath = '/':a:bs-        return (File Homeless filepath)--    relativePath = do-        _  <- Text.Parser.Char.text "./"-        as <- many (Text.Parser.Char.satisfy pathCharacter)-        let filepath = "./" <> as-        return (File Homeless filepath)--    parentPath = do-        _  <- Text.Parser.Char.text "../"-        as <- many (Text.Parser.Char.satisfy pathCharacter)-        let filepath = "../" <> as-        return (File Homeless filepath)--    homePath = do-        _  <- Text.Parser.Char.text "~/"-        as <- many (Text.Parser.Char.satisfy pathCharacter)-        return (File Home as)--file :: Parser PathType-file = do-    a <- fileRaw-    whitespace-    return a--scheme :: Parser Builder-scheme = "http" <> option "s"--httpRaw :: Parser Builder-httpRaw =-        scheme-    <>  "://"-    <>  authority-    <>  pathAbempty-    <>  option ("?" <> query)-    <>  option ("#" <> fragment)--authority :: Parser Builder-authority = option (try (userinfo <> "@")) <> host <> option (":" <> port)--userinfo :: Parser Builder-userinfo = star (satisfy predicate <|> pctEncoded)-  where-    predicate c = unreserved c || subDelims c || c == ':'--host :: Parser Builder-host = choice [ ipLiteral, ipV4Address, regName ]--port :: Parser Builder-port = star (satisfy digit)--ipLiteral :: Parser Builder-ipLiteral = "[" <> (ipV6Address <|> ipVFuture) <> "]"--ipVFuture :: Parser Builder-ipVFuture = "v" <> plus (satisfy hexdig) <> "." <> plus (satisfy predicate)-  where-    predicate c = unreserved c || subDelims c || c == ':'--ipV6Address :: Parser Builder-ipV6Address =-    choice-        [ try alternative0-        , try alternative1-        , try alternative2-        , try alternative3-        , try alternative4-        , try alternative5-        , try alternative6-        , try alternative7-        ,     alternative8-        ]-  where-    alternative0 = count 6 (h16 <> ":") <> ls32--    alternative1 = "::" <> count 5 (h16 <> ":") <> ls32--    alternative2 = option h16 <> "::" <> count 4 (h16 <> ":") <> ls32--    alternative3 =-            option (range 0 1 (h16 <> ":") <> h16)-        <>  "::"-        <>  count 3 (h16 <> ":")-        <>  ls32--    alternative4 =-            option (range 0 2 (h16 <> ":") <> h16)-        <>  "::"-        <>  count 2 (h16 <> ":")-        <>  ls32--    alternative5 =-        option (range 0 3 (h16 <> ":") <> h16) <> "::" <> h16 <> ":" <> ls32--    alternative6 =-        option (range 0 4 (h16 <> ":") <> h16) <> "::" <> ls32--    alternative7 =-        option (range 0 5 (h16 <> ":") <> h16) <> "::" <> h16--    alternative8 =-        option (range 0 6 (h16 <> ":") <> h16) <> "::"--h16 :: Parser Builder-h16 = range 1 3 (satisfy hexdig)--ls32 :: Parser Builder-ls32 = (h16 <> ":" <> h16) <|> ipV4Address--ipV4Address :: Parser Builder-ipV4Address = decOctet <> "." <> decOctet <> "." <> decOctet <> "." <> decOctet--decOctet :: Parser Builder-decOctet =-    choice-        [ try alternative4-        , try alternative3-        , try alternative2-        , try alternative1-        ,     alternative0-        ]-  where-    alternative0 = satisfy digit--    alternative1 = satisfy predicate <> satisfy digit-      where-        predicate c = '\x31' <= c && c <= '\x39'--    alternative2 = "1" <> count 2 (satisfy digit)--    alternative3 = "2" <> satisfy predicate <> satisfy digit-      where-        predicate c = '\x30' <= c && c <= '\x34'--    alternative4 = "25" <> satisfy predicate-      where-        predicate c = '\x30' <= c && c <= '\x35'--regName :: Parser Builder-regName = star (satisfy predicate <|> pctEncoded)-  where-    predicate c = unreserved c || subDelims c--pathAbempty :: Parser Builder-pathAbempty = star ("/" <> segment)--segment :: Parser Builder-segment = star pchar--pchar :: Parser Builder-pchar = satisfy predicate <|> pctEncoded-  where-    predicate c = unreserved c || subDelims c || c == ':' || c == '@'--query :: Parser Builder-query = star (pchar <|> satisfy predicate)-  where-    predicate c = c == '/' || c == '?'--fragment :: Parser Builder-fragment = star (pchar <|> satisfy predicate)-  where-    predicate c = c == '/' || c == '?'--pctEncoded :: Parser Builder-pctEncoded = "%" <> count 2 (satisfy hexdig)--unreserved :: Char -> Bool-unreserved c =-    alpha c || digit c || c == '-' || c == '.' || c == '_' || c == '~'--subDelims :: Char -> Bool-subDelims c = c `elem` ("!$&'()*+,;=" :: String)--http :: Parser PathType-http = do-    a <- httpRaw-    whitespace-    b <- optional (do-        _using-        pathHashed_ )-    return (URL (Data.Text.Lazy.Builder.toLazyText a) b)--env :: Parser PathType-env = do-    _ <- Text.Parser.Char.text "env:"-    a <- (alternative0 <|> alternative1)-    whitespace-    return (Env a)-  where-    alternative0 = do-        a <- bashEnvironmentVariable-        return (Data.Text.Lazy.Builder.toLazyText a)--    alternative1 = do-        _ <- Text.Parser.Char.char '"'-        a <- posixEnvironmentVariable-        _ <- Text.Parser.Char.char '"'-        return (Data.Text.Lazy.Builder.toLazyText a)--bashEnvironmentVariable :: Parser Builder-bashEnvironmentVariable = satisfy predicate0 <> star (satisfy predicate1)-  where-    predicate0 c = alpha c || c == '_'--    predicate1 c = alpha c || digit c || c == '_'--posixEnvironmentVariable :: Parser Builder-posixEnvironmentVariable = plus posixEnvironmentVariableCharacter--posixEnvironmentVariableCharacter :: Parser Builder-posixEnvironmentVariableCharacter =-    ("\\" <> satisfy predicate0) <|> satisfy predicate1-  where-    predicate0 c = c `elem` ("\"\\abfnrtv" :: String)--    predicate1 c =-            ('\x20' <= c && c <= '\x21')-        ||  ('\x23' <= c && c <= '\x3C')-        ||  ('\x3E' <= c && c <= '\x5B')-        ||  ('\x5D' <= c && c <= '\x7E')--expression :: Parser a -> Parser (Expr Src a)-expression embedded =-    (   noted-        ( choice-            [ alternative0-            , alternative1-            , alternative2-            , alternative3-            , alternative4-            ]-        )-    <|> alternative5-    ) <?> "expression"-  where-    alternative0 = do-        _lambda-        _openParens-        a <- label-        _colon-        b <- expression embedded-        _closeParens-        _arrow-        c <- expression embedded-        return (Lam a b c)--    alternative1 = do-        _if-        a <- expression embedded-        _then-        b <- expression embedded-        _else-        c <- expression embedded-        return (BoolIf a b c)--    alternative2 = do-        _let-        a <- label-        b <- optional (do-            _colon-            expression embedded )-        _equal-        c <- expression embedded-        _in-        d <- expression embedded-        return (Let a b c d)--    alternative3 = do-        _forall-        _openParens-        a <- label-        _colon-        b <- expression embedded-        _closeParens-        _arrow-        c <- expression embedded-        return (Pi a b c)--    alternative4 = do-        a <- try (do a <- operatorExpression embedded; _arrow; return a)-        b <- expression embedded-        return (Pi "_" a b)--    alternative5 = annotatedExpression embedded--annotatedExpression :: Parser a -> Parser (Expr Src a)-annotatedExpression embedded =-    noted-        ( choice-            [ alternative0-            , try alternative1-            , alternative2-            ]-        )-  where-    alternative0 = do-        _merge-        a <- selectorExpression embedded-        b <- selectorExpression embedded-        c <- optional (do-            _colon-            applicationExpression embedded )-        return (Merge a b c)--    alternative1 = (do-        _openBracket-        (emptyCollection embedded <|> nonEmptyOptional embedded) )-        <?> "list literal"--    alternative2 = do-        a <- operatorExpression embedded-        b <- optional (do _colon; expression embedded)-        case b of-            Nothing -> return a-            Just c  -> return (Annot a c)--emptyCollection :: Parser a -> Parser (Expr Src a)-emptyCollection embedded = do-    _closeBracket-    _colon-    a <- alternative0 <|> alternative1-    b <- selectorExpression embedded-    return (a b)-  where-    alternative0 = do-        _List-        return (\a -> ListLit (Just a) empty)--    alternative1 = do-        _Optional-        return (\a -> OptionalLit a empty)--nonEmptyOptional :: Parser a -> Parser (Expr Src a)-nonEmptyOptional embedded = do-    a <- expression embedded-    _closeBracket-    _colon-    _Optional-    b <- selectorExpression embedded-    return (OptionalLit b (pure a))--operatorExpression :: Parser a -> Parser (Expr Src a)-operatorExpression = orExpression--makeOperatorExpression-    :: (Parser a -> Parser (Expr Src a))-    -> Parser ()-    -> (Expr Src a -> Expr Src a -> Expr Src a)-    -> Parser a-    -> Parser (Expr Src a)-makeOperatorExpression subExpression operatorParser operator embedded =-    noted (do-        a <- subExpression embedded-        b <- many (do operatorParser; subExpression embedded)-        return (foldr1 operator (a:b)) )--orExpression :: Parser a -> Parser (Expr Src a)-orExpression =-    makeOperatorExpression plusExpression _or BoolOr--plusExpression :: Parser a -> Parser (Expr Src a)-plusExpression =-    makeOperatorExpression textAppendExpression _plus NaturalPlus--textAppendExpression :: Parser a -> Parser (Expr Src a)-textAppendExpression =-    makeOperatorExpression listAppendExpression _textAppend TextAppend--listAppendExpression :: Parser a -> Parser (Expr Src a)-listAppendExpression =-    makeOperatorExpression andExpression _listAppend ListAppend--andExpression :: Parser a -> Parser (Expr Src a)-andExpression =-    makeOperatorExpression combineExpression _and BoolAnd--combineExpression :: Parser a -> Parser (Expr Src a)-combineExpression =-    makeOperatorExpression preferExpression _combine Combine--preferExpression :: Parser a -> Parser (Expr Src a)-preferExpression =-    makeOperatorExpression timesExpression _prefer Prefer--timesExpression :: Parser a -> Parser (Expr Src a)-timesExpression =-    makeOperatorExpression equalExpression _times NaturalTimes--equalExpression :: Parser a -> Parser (Expr Src a)-equalExpression =-    makeOperatorExpression notEqualExpression _doubleEqual BoolEQ--notEqualExpression :: Parser a -> Parser (Expr Src a)-notEqualExpression =-    makeOperatorExpression applicationExpression _notEqual BoolNE--applicationExpression :: Parser a -> Parser (Expr Src a)-applicationExpression embedded = do-    f <- (do _constructors; return Constructors) <|> return id-    a <- noted (selectorExpression embedded)-    b <- many (noted (selectorExpression embedded))-    return (foldl app (f a) b)-  where-    app nL@(Note (Src before _ bytesL) _) nR@(Note (Src _ after bytesR) _) =-        Note (Src before after (bytesL <> bytesR)) (App nL nR)-    app nL nR =-        App nL nR--selectorExpression :: Parser a -> Parser (Expr Src a)-selectorExpression embedded = noted (do-    a <- primitiveExpression embedded-    b <- many (try (do _dot; label))-    return (foldl Field a b) )--primitiveExpression :: Parser a -> Parser (Expr Src a)-primitiveExpression embedded =-    noted-        ( choice-            [ alternative00-            , alternative01-            , alternative02-            , alternative03-            , alternative04-            , alternative05-            , alternative06-            , alternative07-            , alternative37--            , choice-                [ alternative08-                , alternative09-                , alternative10-                , alternative11-                , alternative12-                , alternative13-                , alternative14-                , alternative15-                , alternative16-                , alternative17-                , alternative18-                , alternative19-                , alternative20-                , alternative21-                , alternative22-                , alternative23-                , alternative24-                , alternative25-                , alternative26-                , alternative27-                , alternative28-                , alternative29-                , alternative30-                , alternative31-                , alternative32-                , alternative33-                , alternative34-                , alternative35-                , alternative36-                ] <?> "built-in expression"-            ]-        )-    <|> alternative38-  where-    alternative00 = do-        a <- try doubleLiteral-        return (DoubleLit a)--    alternative01 = do-        a <- try naturalLiteral-        return (NaturalLit a)--    alternative02 = do-        a <- try integerLiteral-        return (IntegerLit a)--    alternative03 = textLiteral embedded--    alternative04 = (do-        _openBrace-        a <- recordTypeOrLiteral embedded-        _closeBrace-        return a ) <?> "record type or literal"--    alternative05 = (do-        _openAngle-        a <- unionTypeOrLiteral embedded-        _closeAngle-        return a ) <?> "union type or literal"--    alternative06 = nonEmptyListLiteral embedded--    alternative07 = do-        a <- embedded-        return (Embed a)--    alternative08 = do-        _NaturalFold-        return NaturalFold--    alternative09 = do-        _NaturalBuild-        return NaturalBuild--    alternative10 = do-        _NaturalIsZero-        return NaturalIsZero--    alternative11 = do-        _NaturalEven-        return NaturalEven--    alternative12 = do-        _NaturalOdd-        return NaturalOdd--    alternative13 = do-        _NaturalToInteger-        return NaturalToInteger--    alternative14 = do-        _NaturalShow-        return NaturalShow--    alternative15 = do-        _IntegerShow-        return IntegerShow--    alternative16 = do-        _DoubleShow-        return DoubleShow--    alternative17 = do-        _ListBuild-        return ListBuild--    alternative18 = do-        _ListFold-        return ListFold--    alternative19 = do-        _ListLength-        return ListLength--    alternative20 = do-        _ListHead-        return ListHead--    alternative21 = do-        _ListLast-        return ListLast--    alternative22 = do-        _ListIndexed-        return ListIndexed--    alternative23 = do-        _ListReverse-        return ListReverse--    alternative24 = do-        _OptionalFold-        return OptionalFold--    alternative25 = do-        _OptionalBuild-        return OptionalBuild--    alternative26 = do-        _Bool-        return Bool--    alternative27 = do-        _Optional-        return Optional--    alternative28 = do-        _Natural-        return Natural--    alternative29 = do-        _Integer-        return Integer--    alternative30 = do-        _Double-        return Double--    alternative31 = do-        _Text-        return Text--    alternative32 = do-        _List-        return List--    alternative33 = do-        _True-        return (BoolLit True)--    alternative34 = do-        _False-        return (BoolLit False)--    alternative35 = do-        _Type-        return (Const Type)--    alternative36 = do-        _Kind-        return (Const Kind)--    alternative37 = do-        a <- identifier-        return (Var a)--    alternative38 = do-        _openParens-        a <- expression embedded-        _closeParens-        return a--recordTypeOrLiteral :: Parser a -> Parser (Expr Src a)-recordTypeOrLiteral embedded =-    choice-        [ alternative0-        , alternative1-        , alternative2-        ]-  where-    alternative0 = do-        _equal-        return (RecordLit Data.HashMap.Strict.InsOrd.empty)--    alternative1 = nonEmptyRecordTypeOrLiteral embedded--    alternative2 = return (Record Data.HashMap.Strict.InsOrd.empty)--nonEmptyRecordTypeOrLiteral :: Parser a -> Parser (Expr Src a)-nonEmptyRecordTypeOrLiteral embedded = do-    a <- label--    let nonEmptyRecordType = do-            _colon-            b <- expression embedded-            e <- many (do-                _comma-                c <- label-                _colon-                d <- expression embedded-                return (c, d) )-            return (Record (Data.HashMap.Strict.InsOrd.fromList ((a, b):e)))--    let nonEmptyRecordLiteral = do-            _equal-            b <- expression embedded-            e <- many (do-                _comma-                c <- label-                _equal-                d <- expression embedded-                return (c, d) )-            return (RecordLit (Data.HashMap.Strict.InsOrd.fromList ((a, b):e)))--    nonEmptyRecordType <|> nonEmptyRecordLiteral--unionTypeOrLiteral :: Parser a -> Parser (Expr Src a)-unionTypeOrLiteral embedded =-        nonEmptyUnionTypeOrLiteral embedded-    <|> return (Union Data.HashMap.Strict.InsOrd.empty)--nonEmptyUnionTypeOrLiteral :: Parser a -> Parser (Expr Src a)-nonEmptyUnionTypeOrLiteral embedded = do-    (f, kvs) <- loop-    m <- toMap kvs-    return (f m)-  where-    loop = do-        a <- label--        let alternative0 = do-                _equal-                b <- expression embedded-                kvs <- many (do-                    _bar-                    c <- label-                    _colon-                    d <- expression embedded-                    return (c, d) )-                return (UnionLit a b, kvs)--        let alternative1 = do-                _colon-                b <- expression embedded--                let alternative2 = do-                        _bar-                        (f, kvs) <- loop-                        return (f, (a, b):kvs)--                let alternative3 = return (Union, [(a, b)])--                alternative2 <|> alternative3--        alternative0 <|> alternative1--nonEmptyListLiteral :: Parser a -> Parser (Expr Src a)-nonEmptyListLiteral embedded = (do-    _openBracket-    a <- expression embedded-    b <- many (do _comma; expression embedded)-    _closeBracket-    return (ListLit Nothing (Data.Sequence.fromList (a:b))) ) <?> "list literal"--completeExpression :: Parser a -> Parser (Expr Src a)-completeExpression embedded = do-    whitespace-    expression embedded--toMap :: [(Text, a)] -> Parser (InsOrdHashMap Text a)-toMap kvs = do-    let adapt (k, v) = (k, pure v)-    let m = fromListWith (<|>) (fmap adapt kvs)-    let action k vs = case Data.Sequence.viewl vs of-            EmptyL  -> empty-            v :< vs' ->-                if null vs'-                then pure v-                else-                    Text.Parser.Combinators.unexpected-                        ("duplicate field: " ++ Data.Text.Lazy.unpack k)-    Data.HashMap.Strict.InsOrd.traverseWithKey action m-  where-    fromListWith combine = Data.List.foldl' snoc nil-      where-        nil = Data.HashMap.Strict.InsOrd.empty--        snoc m (k, v) = Data.HashMap.Strict.InsOrd.insertWith combine k v m---- | Parser for a top-level Dhall expression-expr :: Parser (Expr Src Path)-expr = exprA import_---- | Parser for a top-level Dhall expression. The expression is parameterized--- over any parseable type, allowing the language to be extended as needed.-exprA :: Parser a -> Parser (Expr Src a)-exprA = completeExpression--pathType_ :: Parser PathType-pathType_ = choice [ file, http, env ]--pathHashed_ :: Parser PathHashed-pathHashed_ = do-    pathType <- pathType_-    hash     <- optional pathHash_-    return (PathHashed {..})-  where-    pathHash_ = do-        _ <- Text.Parser.Char.text "sha256:"-        builder <- count 64 (satisfy hexdig <?> "hex digit")-        whitespace-        let lazyText = Data.Text.Lazy.Builder.toLazyText builder-        let lazyBytes = Data.Text.Lazy.Encoding.encodeUtf8 lazyText-        case Crypto.Hash.digestFromByteString (Data.ByteString.Lazy.toStrict lazyBytes) of-          Nothing -> fail "Invalid sha256 hash"-          Just h -> pure h--import_ :: Parser Path-import_ = (do-    pathHashed <- pathHashed_-    pathMode   <- alternative <|> pure Code-    return (Path {..}) ) <?> "import"-  where-    alternative = do-        _as-        _Text-        return RawText---- | A parsing error-newtype ParseError = ParseError Doc deriving (Typeable)--instance Show ParseError where-    show (ParseError doc) =-      "\n\ESC[1;31mError\ESC[0m: Invalid input\n\n" <> show doc--instance Exception ParseError---- | Parse an expression from `Text` containing a Dhall program-exprFromText :: Delta -> Text -> Either ParseError (Expr Src Path)-exprFromText delta text = fmap snd (exprAndHeaderFromText delta text)--{-| Like `exprFromText` but also returns the leading comments and whitespace-    (i.e. header) up to the last newline before the code begins--    In other words, if you have a Dhall file of the form:--> -- Comment 1-> {- Comment -} 2--    Then this will preserve @Comment 1@, but not @Comment 2@--    This is used by @dhall-format@ to preserve leading comments and whitespace--}-exprAndHeaderFromText-    :: Delta-    -> Text-    -> Either ParseError (Text, Expr Src Path)-exprAndHeaderFromText delta text = case result of-    Failure errInfo    -> Left (ParseError (Text.Trifecta._errDoc errInfo))-    Success (bytes, r) -> case Data.Text.Encoding.decodeUtf8' bytes of-        Left  errInfo -> Left (ParseError (fromString (show errInfo)))-        Right txt     -> do-            let stripped = Data.Text.dropWhileEnd (/= '\n') txt-            let lazyText = Data.Text.Lazy.fromStrict stripped-            Right (lazyText, r)-  where-    string = Data.Text.Lazy.unpack text--    parser = unParser (do-        bytes <- Text.Trifecta.slicedWith (\_ x -> x) whitespace-        r <- expr-        Text.Parser.Combinators.eof-        return (bytes, r) )--    result = Text.Trifecta.parseString parser delta string+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++-- | This module contains Dhall's parsing logic++module Dhall.Parser (+    -- * Utilities+      exprFromText+    , exprAndHeaderFromText+    , censor+    , createHeader++    -- * Parsers+    , expr, exprA++    -- * Types+    , Header(..)+    , Src(..)+    , SourcedException(..)+    , ParseError(..)+    , Parser(..)+    ) where++import Control.Applicative (many)+import Control.Exception   (Exception)+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Src           (Src (..))+import Dhall.Syntax+import Text.Megaparsec     (ParseErrorBundle (..), PosState (..))++import qualified Data.Text       as Text+import qualified Dhall.Core      as Core+import qualified Text.Megaparsec++import Dhall.Parser.Combinators+import Dhall.Parser.Expression+import Dhall.Parser.Token       hiding (text)++-- | Parser for a top-level Dhall expression+expr :: Parser (Expr Src Import)+expr = exprA (Text.Megaparsec.try import_)++-- | Parser for a top-level Dhall expression. The expression is parameterized+-- over any parseable type, allowing the language to be extended as needed.+exprA :: Parser a -> Parser (Expr Src a)+exprA = completeExpression+{-# DEPRECATED exprA "Support for parsing custom imports will be dropped in a future release" #-}++-- | A parsing error+data ParseError = ParseError {+      unwrap :: Text.Megaparsec.ParseErrorBundle Text Void+    , input  :: Text+    }++{-| Replace the source code with spaces when rendering error messages++    This utility is used to implement the @--censor@ flag+-}+censor :: ParseError -> ParseError+censor parseError =+    parseError+        { unwrap =+            (unwrap parseError)+                { bundlePosState =+                    (bundlePosState (unwrap parseError))+                        { pstateInput =+                            Core.censorText+                                (pstateInput (bundlePosState (unwrap parseError)))+                        }+                }+        }++instance Show ParseError where+    show (ParseError {..}) =+      "\n\ESC[1;31mError\ESC[0m: Invalid input\n\n" <> Text.Megaparsec.errorBundlePretty unwrap++instance Exception ParseError++-- | Parse an expression from `Text.Text` containing a Dhall program+exprFromText+  :: String -- ^ User-friendly name describing the input expression,+            --   used in parsing error messages+  -> Text   -- ^ Input expression to parse+  -> Either ParseError (Expr Src Import)+exprFromText delta text = fmap snd (exprAndHeaderFromText delta text)++-- | A header corresponds to the leading comment at the top of a Dhall file.+--+-- The header includes comment characters but is stripped of leading spaces and+-- trailing newlines+newtype Header = Header Text deriving Show++-- | Create a header with stripped leading spaces and trailing newlines+createHeader :: Text -> Header+createHeader text = Header (prefix <> newSuffix)+  where+    isWhitespace c = c == ' ' || c == '\n' || c == '\r' || c == '\t'++    prefix = Text.dropAround isWhitespace text++    newSuffix+        | Text.null prefix = ""+        | otherwise        = "\n"++-- | Like `exprFromText` but also returns the leading comments and whitespace+-- (i.e. header) up to the last newline before the code begins+--+-- In other words, if you have a Dhall file of the form:+--+-- > -- Comment 1+-- > {- Comment -} 2+--+-- Then this will preserve @Comment 1@, but not @Comment 2@+--+-- This is used by @dhall-format@ to preserve leading comments and whitespace+exprAndHeaderFromText+    :: String -- ^ User-friendly name describing the input expression,+              --   used in parsing error messages+    -> Text   -- ^ Input expression to parse+    -> Either ParseError (Header, Expr Src Import)+exprAndHeaderFromText delta text = case result of+    Left errInfo   -> Left (ParseError { unwrap = errInfo, input = text })+    Right (txt, r) -> Right (createHeader txt, r)+  where+    parser = do+        (bytes, _) <- Text.Megaparsec.match (many shebang *> whitespace)+        r <- expr+        Text.Megaparsec.eof+        return (bytes, r)++    result = Text.Megaparsec.parse (unParser parser) delta text
+ src/Dhall/Parser/Combinators.hs view
@@ -0,0 +1,292 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}++{-| This module contains Dhall's parser combinators+-}++module Dhall.Parser.Combinators+    ( Parser(..)+    , SourcedException(..)+    , laxSrcEq+    , count+    , range+    , option+    , star+    , plus+    , satisfy+    , Dhall.Parser.Combinators.takeWhile+    , takeWhile1+    , toMap+    , toMapWith+    , base+    ) where+++import Control.Applicative     (Alternative (..), liftA2)+import Control.Exception       (Exception)+import Control.Monad           (MonadPlus (..))+import Data.String             (IsString (..))+import Data.Text               (Text)+import Data.Void               (Void)+import Dhall.Map               (Map)+import Dhall.Src               (Src (..))+import Prettyprinter           (Pretty (..))+import Text.Parser.Combinators (try, (<?>))+import Text.Parser.Token       (TokenParsing (..))++import qualified Control.Monad.Fail+import qualified Data.Char                   as Char+import qualified Data.Text+import qualified Dhall.Map+import qualified Dhall.Pretty+import qualified Prettyprinter.Render.String as Pretty+import qualified Text.Megaparsec+import qualified Text.Megaparsec.Char+import qualified Text.Parser.Char+import qualified Text.Parser.Combinators+import qualified Text.Parser.Token.Style++-- | An exception annotated with a `Src` span+data SourcedException e = SourcedException Src e++instance Exception e => Exception (SourcedException e)++instance Show e => Show (SourcedException e) where+    show (SourcedException source exception) =+            show exception+        <>  "\n"+        <>  "\n"+        <>  Pretty.renderString+                (Dhall.Pretty.layout (pretty source))++-- | Doesn't force the 'Data.Text.Text' part+laxSrcEq :: Src -> Src -> Bool+laxSrcEq (Src p q _) (Src p' q' _) = eq p p' && eq q q'+  where+    -- Don't compare filename (which is FilePath = String)+    eq  :: Text.Megaparsec.SourcePos -> Text.Megaparsec.SourcePos -> Bool+    eq (Text.Megaparsec.SourcePos _ a b) (Text.Megaparsec.SourcePos _ a' b') =+        a == a' && b == b'+{-# INLINE laxSrcEq #-}++{-| A `Parser` that is almost identical to+    @"Text.Megaparsec".`Text.Megaparsec.Parsec`@ except treating Haskell-style+    comments as whitespace+-}+newtype Parser a = Parser { unParser :: Text.Megaparsec.Parsec Void Text a }++instance Functor Parser where+    fmap f (Parser x) = Parser (fmap f x)+    {-# INLINE fmap #-}++    f <$ Parser x = Parser (f <$ x)+    {-# INLINE (<$) #-}++instance Applicative Parser where+    pure = Parser . pure+    {-# INLINE pure #-}++    Parser f <*> Parser x = Parser (f <*> x)+    {-# INLINE (<*>) #-}++    Parser a <* Parser b = Parser (a <* b)+    {-# INLINE (<*) #-}++    Parser a *> Parser b = Parser (a *> b)+    {-# INLINE (*>) #-}++instance Monad Parser where+    return = pure+    {-# INLINE return #-}++    (>>) = (*>)+    {-# INLINE (>>) #-}++    Parser n >>= k = Parser (n >>= unParser . k)+    {-# INLINE (>>=) #-}++#if !(MIN_VERSION_base(4,13,0))+    fail = Control.Monad.Fail.fail+    {-# INLINE fail #-}+#endif++instance Control.Monad.Fail.MonadFail Parser where+    fail = Parser . Control.Monad.Fail.fail+    {-# INLINE fail #-}++instance Alternative Parser where+    empty = Parser empty+    -- {-# INLINE empty #-}++    Parser a <|> Parser b = Parser (a <|> b)+    -- {-# INLINE (<|>) #-}++    some (Parser a) = Parser (some a)+    -- {-# INLINE some #-}++    many (Parser a) = Parser (many a)+    -- {-# INLINE many #-}++instance MonadPlus Parser where+    mzero = empty+    -- {-# INLINE mzero #-}++    mplus = (<|>)+    -- {-# INLINE mplus #-}++instance Text.Megaparsec.MonadParsec Void Text Parser where+    parseError e = Parser (Text.Megaparsec.parseError e)++    label l (Parser p) = Parser (Text.Megaparsec.label l p)++    hidden (Parser p) = Parser (Text.Megaparsec.hidden p)++    try (Parser p) = Parser (Text.Megaparsec.try p)++    lookAhead (Parser p) = Parser (Text.Megaparsec.lookAhead p)++    notFollowedBy (Parser p) = Parser (Text.Megaparsec.notFollowedBy p)++    withRecovery e (Parser p) = Parser (Text.Megaparsec.withRecovery (unParser . e) p)++    observing (Parser p) = Parser (Text.Megaparsec.observing p)++    eof = Parser Text.Megaparsec.eof++    token f e = Parser (Text.Megaparsec.token f e)++    tokens f ts = Parser (Text.Megaparsec.tokens f ts)++    takeWhileP s f = Parser (Text.Megaparsec.takeWhileP s f)++    takeWhile1P s f = Parser (Text.Megaparsec.takeWhile1P s f)++    takeP s n = Parser (Text.Megaparsec.takeP s n)++    getParserState = Parser Text.Megaparsec.getParserState+    {-# INLINE getParserState #-}++    updateParserState f = Parser (Text.Megaparsec.updateParserState f)++#if MIN_VERSION_megaparsec(9,4,0)+    mkParsec f = Parser (Text.Megaparsec.mkParsec f)+#endif++instance Semigroup a => Semigroup (Parser a) where+    (<>) = liftA2 (<>)++instance (Semigroup a, Monoid a) => Monoid (Parser a) where+    mempty = pure mempty++instance IsString a => IsString (Parser a) where+    fromString x = fromString x <$ Text.Megaparsec.Char.string (fromString x)++instance Text.Parser.Combinators.Parsing Parser where+  try = Text.Megaparsec.try++  (<?>) = (Text.Megaparsec.<?>)++  skipMany = Text.Megaparsec.skipMany++  skipSome = Text.Megaparsec.skipSome++  unexpected = fail++  eof = Parser Text.Megaparsec.eof++  notFollowedBy = Text.Megaparsec.notFollowedBy++instance Text.Parser.Char.CharParsing Parser where+  satisfy = Parser . Text.Megaparsec.satisfy++  char = Text.Megaparsec.Char.char++  notChar = Text.Megaparsec.Char.char++  anyChar = Text.Megaparsec.anySingle++  string = fmap Data.Text.unpack . Text.Megaparsec.Char.string . fromString++  text = Text.Megaparsec.Char.string++instance TokenParsing Parser where+    someSpace =+        Text.Parser.Token.Style.buildSomeSpaceParser+            (Parser (Text.Megaparsec.skipSome (Text.Megaparsec.satisfy Char.isSpace)))+            Text.Parser.Token.Style.haskellCommentStyle++    highlight _ = id++    semi = token (Text.Megaparsec.Char.char ';' <?> ";")++-- | @count n p@ parses @n@ occurrences of @p@+count :: (Semigroup a, Monoid a) => Int -> Parser a -> Parser a+count n parser = mconcat (replicate n parser)++-- | @range lo hi p@ parses @n@ ocurrences of @p@ where @lo <= n <= hi@+range :: (Semigroup a, Monoid a) => Int -> Int -> Parser a -> Parser a+range minimumBound maximumMatches parser =+    count minimumBound parser <> loop maximumMatches+  where+    loop 0 = mempty+    loop n = (parser <> loop (n - 1)) <|> mempty++-- | @option p@ tries to apply parser @p@ returning @mempty@ if parsing failed+option :: (Alternative f, Monoid a) => f a -> f a+option p = p <|> pure mempty++-- | @star p@ tries to apply a parser @0@ or more times+star :: (Alternative f, Monoid a) => f a -> f a+star p = plus p <|> pure mempty++-- | @plus p@ tries to apply a parser @1@ or more times+plus :: (Alternative f, Monoid a) => f a -> f a+plus p = mappend <$> p <*> star p++-- | @satisfy p@ creates a parser that consumes and return the next character+--   if it satisfies the predicate @p@+satisfy :: (Char -> Bool) -> Parser Text+satisfy = fmap Data.Text.singleton . Text.Parser.Char.satisfy++-- | @takeWhile p@ creates a parser that accepts the longest sequence of characters+--   that match the given predicate possibly returning an empty sequence+takeWhile :: (Char -> Bool) -> Parser Text+takeWhile predicate = Parser (Text.Megaparsec.takeWhileP Nothing predicate)++-- | @takeWhile1 p@ creates a parser that accepts the longest sequence of characters+--   that match the given predicate. It fails when no character was consumed+takeWhile1 :: (Char -> Bool) -> Parser Text+takeWhile1 predicate = Parser (Text.Megaparsec.takeWhile1P Nothing predicate)++-- | Creates a map with the given key-value pairs, failing if there was a+--   duplicate key.+toMap :: [(Text, a)] -> Parser (Map Text a)+toMap kvs = Dhall.Map.unorderedTraverseWithKey (\_k v -> v) m+  where+    m = Dhall.Map.fromListWithKey err (map (\(k, v) -> (k, pure v)) kvs)++    err k _v1 _v2 = Text.Parser.Combinators.unexpected+                        ("duplicate field: " ++ Data.Text.unpack k)++-- | Creates a 'Map Text a' using the provided combining function and the+--   key-value pairs+toMapWith+    :: (Text -> Parser a -> Parser a -> Parser a)+    -> [(Text, a)]+    -> Parser (Map Text a)+toMapWith combine kvs = sequence m+  where+    m = Dhall.Map.fromListWithKey combine (map (\(k, v) -> (k, pure v)) kvs)++-- | Convert a list of digits to the equivalent number+base :: Num n => [Char] -> n -> n+digits `base` b = foldl snoc 0 (map (fromIntegral . digitToNumber) digits)+  where+    snoc result number = result * b + number++    digitToNumber c+        | '0' <= c && c <= '9' = 0x0 + Char.ord c - Char.ord '0'+        | 'A' <= c && c <= 'F' = 0xA + Char.ord c - Char.ord 'A'+        | 'a' <= c && c <= 'f' = 0xa + Char.ord c - Char.ord 'a'+        | otherwise = error "Invalid hexadecimal digit"
+ src/Dhall/Parser/Expression.hs view
@@ -0,0 +1,1279 @@+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE NamedFieldPuns      #-}+{-# LANGUAGE OverloadedLists     #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | Parsing Dhall expressions.+module Dhall.Parser.Expression where++import Control.Applicative     (Alternative (..), liftA2, optional)+import Data.Foldable           (foldl')+import Data.List.NonEmpty      (NonEmpty (..))+import Data.Text               (Text)+import Dhall.Src               (Src (..))+import Dhall.Syntax+import Text.Parser.Combinators (choice, try, (<?>))++import qualified Control.Monad+import qualified Control.Monad.Combinators          as Combinators+import qualified Control.Monad.Combinators.NonEmpty as Combinators.NonEmpty+import qualified Data.ByteString                    as ByteString+import qualified Data.ByteString.Base16             as Base16+import qualified Data.Char                          as Char+import qualified Data.List+import qualified Data.List.NonEmpty                 as NonEmpty+import qualified Data.Sequence+import qualified Data.Text+import qualified Data.Text.Encoding+import qualified Data.Time                          as Time+import qualified Dhall.Crypto+import qualified Text.Megaparsec++import Dhall.Parser.Combinators+import Dhall.Parser.Token++-- | Get the current source offset (in tokens)+getOffset :: Text.Megaparsec.MonadParsec e s m => m Int+getOffset = Text.Megaparsec.stateOffset <$> Text.Megaparsec.getParserState+{-# INLINE getOffset #-}++-- | Set the current source offset+setOffset :: Text.Megaparsec.MonadParsec e s m => Int -> m ()+setOffset o = Text.Megaparsec.updateParserState $ \state ->+    state+        { Text.Megaparsec.stateOffset = o }+{-# INLINE setOffset #-}++{-| Wrap a `Parser` to still match the same text but return only the `Src`+    span+-}+src :: Parser a -> Parser Src+src parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, _) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    return (Src before after tokens)++-- | Same as `src`, except also return the parsed value+srcAnd :: Parser a -> Parser (Src, a)+srcAnd parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, x) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    return (Src before after tokens, x)++{-| Wrap a `Parser` to still match the same text, but to wrap the resulting+    `Expr` in a `Note` constructor containing the `Src` span+-}+noted :: Parser (Expr Src a) -> Parser (Expr Src a)+noted parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, e) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    let src₀ = Src before after tokens+    case e of+        Note src₁ _ | laxSrcEq src₀ src₁ -> return e+        _                                -> return (Note src₀ e)++{-| Parse a complete expression (with leading and trailing whitespace)++    This corresponds to the @complete-expression@ rule from the official+    grammar+-}+completeExpression :: Parser a -> Parser (Expr Src a)+completeExpression embedded = completeExpression_+  where+    Parsers {..} = parsers embedded++{-| Parse an \"import expression\"++    This is not the same thing as @`fmap` `Embed`@.  This parses any+    expression of the same or higher precedence as an import expression (such+    as a selector expression).  For example, this parses @(1)@++    This corresponds to the @import-expression@ rule from the official grammar+-}+importExpression :: Parser a -> Parser (Expr Src a)+importExpression embedded = importExpression_+  where+    Parsers {..} = parsers embedded++{-| For efficiency (and simplicity) we only expose two parsers from the+    result of the `parsers` function, since these are the only parsers needed+    outside of this module+-}+data Parsers a = Parsers+    { completeExpression_ :: Parser (Expr Src a)+    , importExpression_   :: Parser (Expr Src a)+    , letBinding          :: Parser (Binding Src a)+    }++{-| Parse a numeric `TimeZone`++    This corresponds to the @time-numoffset@ rule from the official grammar+-}+timeNumOffset :: Parser (Expr s a)+timeNumOffset = do+    s <- signPrefix++    hour <- timeHour++    _ <- text ":"++    minute <- timeMinute++    let minutes = s (hour * 60 + minute)++    return (TimeZoneLiteral (Time.TimeZone minutes Prelude.False ""))++{-| Parse a numeric `TimeZone` or a @Z@++    This corresponds to the @time-offset@ rule from the official grammar+-}+timeOffset :: Parser (Expr s a)+timeOffset =+        (do _ <- text "Z"++            return (TimeZoneLiteral (Time.TimeZone 0 Prelude.False ""))+        )+    <|> timeNumOffset++{-| Parse a `Time`++    This corresponds to the @partial-time@ rule from the official grammar+-}+partialTime :: Parser (Expr s a)+partialTime = do+    hour <- timeHour++    _ <- text ":"++    minute <- timeMinute++    _ <- text ":"++    second <- timeSecond++    (fraction, precision) <- timeSecFrac <|> pure (0, 0)++    let time = Time.TimeOfDay hour minute (second + fraction)++    return (TimeLiteral time precision)++{-| Parse a `Date`++    This corresponds to the @full-date@ rule from the official grammar+-}+fullDate :: Parser (Expr s a)+fullDate = do+    year <- dateFullYear++    _ <- text "-"++    month <- dateMonth++    _ <- text "-"++    day <- dateMday++    case Time.fromGregorianValid year month day of+        Nothing -> fail "Invalid calendar day"+        Just d  -> return (DateLiteral d)++{-| Parse a `Date`, `Time`, `TimeZone` or any valid permutation of them as a+    record++    This corresponds to the @temporal-literal@ rule from the official grammar+-}+temporalLiteral :: Parser (Expr s a)+temporalLiteral =+        try (do+            date <- fullDate++            _ <- text "T" <|> text "t"++            time <- partialTime++            timeZone <- timeOffset++            return+                (RecordLit+                    [   ("date"    , makeRecordField date)+                    ,   ("time"    , makeRecordField time)+                    ,   ("timeZone", makeRecordField timeZone)+                    ]+                )+        )+    <|> try (do+            date <- fullDate++            _ <- text "T" <|> text "t"++            time <- partialTime++            return+                (RecordLit+                    [   ("date", makeRecordField date)+                    ,   ("time", makeRecordField time)+                    ]+                )+        )+    <|> try (do+            time <- partialTime++            timeZone <- timeOffset++            return+                (RecordLit+                    [   ("time"    , makeRecordField time)+                    ,   ("timeZone", makeRecordField timeZone)+                    ]+                )+        )+    <|> try fullDate+    <|> try partialTime+    <|> try timeNumOffset++-- | Parse a \"shebang\" line (i.e. an initial line beginning with @#!@)+shebang :: Parser ()+shebang = do+    _ <- text "#!"++    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++    _ <- Dhall.Parser.Combinators.takeWhile predicate++    _ <- endOfLine++    return ()++-- | Given a parser for imports,+parsers :: forall a. Parser a -> Parsers a+parsers embedded = Parsers{..}+  where+    completeExpression_ =+            whitespace+        *>  expression+        <*  whitespace+        <*  optional lineCommentPrefix++    letBinding = do+        src0 <- try (_let *> src nonemptyWhitespace)++        c <- label++        src1 <- src whitespace++        d <- optional (do+            _colon++            src2 <- src nonemptyWhitespace++            e <- expression++            whitespace++            return (Just src2, e) )++        _equal++        src3 <- src whitespace++        f <- expression++        whitespace++        return (Binding (Just src0) c (Just src1) d (Just src3) f)++    expression =+        noted+            ( choice+                [ alternative0+                , alternative1+                , alternative2+                , alternative3+                , alternative4+                , alternative5+                ]+            ) <?> "expression"+      where+        alternative0 = do+            cs <- _lambda+            whitespace+            _openParens+            src0 <- src whitespace+            a <- label+            src1 <- src whitespace+            _colon+            src2 <- src nonemptyWhitespace+            b <- expression+            whitespace+            _closeParens+            whitespace+            cs' <- _arrow+            whitespace+            c <- expression+            return (Lam (Just (cs <> cs')) (FunctionBinding (Just src0) a (Just src1) (Just src2) b) c)++        alternative1 = do+            try (_if *> nonemptyWhitespace)+            a <- expression+            whitespace+            try (_then *> nonemptyWhitespace)+            b <- expression+            whitespace+            try (_else *> nonemptyWhitespace)+            c <- expression+            return (BoolIf a b c)++        alternative2 = do+            as <- NonEmpty.some1 letBinding++            try (_in *> nonemptyWhitespace)++            b <- expression++            -- 'Note's in let-in-let:+            --+            -- Subsequent @let@s that are not separated by an @in@ only get a+            -- single surrounding 'Note'. For example:+            --+            -- let x = a+            -- let y = b+            -- in  let z = c+            --     in x+            --+            -- is parsed as+            --+            -- (Note …+            --   (Let x …+            --     (Let y …+            --       (Note …+            --         (Let z …+            return (Dhall.Syntax.wrapInLets as b)++        alternative3 = do+            cs <- try (_forall <* whitespace <* _openParens)+            whitespace+            a <- label+            whitespace+            _colon+            nonemptyWhitespace+            b <- expression+            whitespace+            _closeParens+            whitespace+            cs' <- _arrow+            whitespace+            c <- expression+            return (Pi (Just (cs <> cs')) a b c)++        alternative4 = do+            try (_assert *> whitespace *> _colon)+            nonemptyWhitespace+            a <- expression+            return (Assert a)++        alternative5 = do+            (a0Info, a0) <- applicationExpressionWithInfo++            let (parseFirstOperatorExpression, parseOperatorExpression) =+                    operatorExpression (pure a0)++            let alternative5A = do+                    case a0Info of+                        ImportExpr -> return ()+                        _          -> empty++                    bs <- some (do+                        try (nonemptyWhitespace *> _with *> nonemptyWhitespace)++                        let withComponent =+                                    fmap WithLabel anyLabelOrSome+                                <|> fmap (\_ -> WithQuestion) (text "?")++                        keys <- Combinators.NonEmpty.sepBy1 withComponent (try (whitespace *> _dot) *> whitespace)++                        whitespace++                        _equal++                        whitespace++                        value <- parseOperatorExpression++                        return (\e -> With e keys value) )++                    return (foldl (\e f -> f e) a0 bs)++            let alternative5B = do+                    a <- parseFirstOperatorExpression++                    whitespace++                    let alternative5B0 = do+                            cs <- _arrow+                            whitespace+                            b <- expression+                            whitespace+                            return (Pi (Just cs) "_" a b)++                    let alternative5B1 = do+                            _colon+                            nonemptyWhitespace+                            case (shallowDenote a, a0Info) of+                                (ListLit Nothing [], _) -> do+                                    b <- expression++                                    return (ListLit (Just b) [])+                                (Merge c d Nothing, NakedMergeOrSomeOrToMap) -> do+                                    b <- expression++                                    return (Merge c d (Just b))+                                (ToMap c Nothing, NakedMergeOrSomeOrToMap) -> do+                                    b <- expression++                                    return (ToMap c (Just b))+                                _ -> do+                                    b <- expression++                                    return (Annot a b)++                    let alternative5B2 =+                            case shallowDenote a of+                                ListLit Nothing [] ->+                                    fail "Empty list literal without annotation"+                                _ -> pure a++                    alternative5B0 <|> alternative5B1 <|> alternative5B2++            alternative5A <|> alternative5B++    -- The firstApplicationExpression argument is necessary in order to+    -- left-factor the parsers for function types and @with@ expressions to+    -- minimize backtracking+    --+    -- For a longer explanation, see:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1770#discussion_r419022486+    operatorExpression firstApplicationExpression =+        foldr cons nil operatorParsers+      where+        cons operatorParser (p0, p) =+            ( makeOperatorExpression p0 operatorParser p+            , makeOperatorExpression p  operatorParser p+            )++        nil = (firstApplicationExpression, applicationExpression)++    makeOperatorExpression firstSubExpression operatorParser subExpression = do+            a <- firstSubExpression++            bs <- Text.Megaparsec.many $ do+                (Src _ _ textOp, op0) <- srcAnd (try (whitespace *> operatorParser))++                r0 <- subExpression++                let l@(Note (Src startL _ textL) _) `op` r@(Note (Src _ endR textR) _) =+                        Note (Src startL endR (textL <> textOp <> textR)) (l `op0` r)+                    -- We shouldn't hit this branch if things are working, but+                    -- that is not enforced in the types+                    l `op` r =+                        l `op0` r++                return (`op` r0)++            return (foldl' (\x f -> f x) a bs)++    operatorParsers :: [Parser (Expr s a -> Expr s a -> Expr s a)]+    operatorParsers =+        [ Equivalent . Just           <$> _equivalent   <* whitespace+        , ImportAlt                   <$ _importAlt     <* nonemptyWhitespace+        , BoolOr                      <$ _or            <* whitespace+        , NaturalPlus                 <$ _plus          <* nonemptyWhitespace+        , TextAppend                  <$ _textAppend    <* whitespace+        , ListAppend                  <$ _listAppend    <* whitespace+        , BoolAnd                     <$ _and           <* whitespace+        , (\cs -> Combine (Just cs) Nothing)         <$> _combine <* whitespace+        , (\cs -> Prefer (Just cs) PreferFromSource) <$> _prefer  <* whitespace+        , CombineTypes . Just         <$> _combineTypes <* whitespace+        , NaturalTimes                <$ _times         <* whitespace+        -- Make sure that `==` is not actually the prefix of `===`+        , BoolEQ                      <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace+        , BoolNE                      <$ _notEqual      <* whitespace+        ]++    applicationExpression = snd <$> applicationExpressionWithInfo++    applicationExpressionWithInfo :: Parser (ApplicationExprInfo, Expr Src a)+    applicationExpressionWithInfo = do+            let alternative0 = do+                    try (_merge *> nonemptyWhitespace)++                    a <- importExpression_ <* nonemptyWhitespace++                    return (\b -> Merge a b Nothing, Just "second argument to ❰merge❱")++            let alternative1 = do+                    try (_Some *> nonemptyWhitespace)++                    return (Some, Just "argument to ❰Some❱")++            let alternative2 = do+                    try (_toMap *> nonemptyWhitespace)++                    return (\a -> ToMap a Nothing, Just "argument to ❰toMap❱")++            let alternative3 = do+                    try (_showConstructor *> nonemptyWhitespace)++                    return (\a -> ShowConstructor a, Just "argument to ❰showConstructor❱")++            let alternative4 =+                    return (id, Nothing)++            (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3 <|> alternative4++            let adapt parser =+                    case maybeMessage of+                        Nothing      -> parser+                        Just message -> parser <?> message++            a <- adapt (noted importExpression_)++            bs <- Text.Megaparsec.many . try $ do+                (sep, _) <- Text.Megaparsec.match nonemptyWhitespace+                b <- importExpression_+                return (sep, b)++            let c = foldl' app (f a) bs++            let info =+                    case (maybeMessage, bs) of+                        (Just _ , []) -> NakedMergeOrSomeOrToMap+                        (Nothing, []) -> ImportExpr+                        _             -> ApplicationExpr++            return (info, c)+          where+            app a (sep, b)+                | Note (Src left _ bytesL) _ <- a+                , Note (Src _ right bytesR) _ <- b+                = Note (Src left right (bytesL <> sep <> bytesR)) (App a b)+            app a (_, b) =+                App a b++    importExpression_ = noted (choice [ alternative0, alternative1 ])+          where+            alternative0 = do+                a <- embedded+                return (Embed a)++            alternative1 = completionExpression++    completionExpression = noted (do+        a <- selectorExpression++        mb <- optional (do+            try (whitespace *> _doubleColon)++            whitespace++            selectorExpression )++        case mb of+            Nothing -> return a+            Just b  -> return (RecordCompletion a b) )++    selectorExpression = noted (do+            a <- primitiveExpression++            let recordType = _openParens *> whitespace *> expression <* whitespace <* _closeParens++            let field               x  e = Field   e  x+            let projectBySet        xs e = Project e (Left  xs)+            let projectByExpression xs e = Project e (Right xs)++            let alternatives = do+                    src0 <- src whitespace++                    let fieldSelection = do+                            l <- anyLabel++                            pos <- Text.Megaparsec.getSourcePos++                            -- FIXME: Suffix whitespace can't be parsed given our limitation+                            -- about whitespace treatment, but for @dhall-docs@ this+                            -- is enough+                            let src1 = Src pos pos ""++                            return (FieldSelection (Just src0) l (Just src1))++                    let result =+                                fmap field               fieldSelection+                            <|> fmap projectBySet        labels+                            <|> fmap projectByExpression recordType++                    result++            b <- Text.Megaparsec.many (try (whitespace *> _dot *> alternatives))++            return (foldl' (\e k -> k e) a b) )++    primitiveExpression =+            noted+                ( choice+                    [ bytesLiteral+                    , temporalLiteral+                    , alternative00+                    , alternative01+                    , alternative02+                    , textLiteral+                    , alternative04+                    , unionType+                    , listLiteral+                    , alternative37+                    , alternative09+                    , builtin+                    ]+                )+            <|> alternative38+          where+            alternative00 = do+                n <- getOffset+                a <- try doubleLiteral+                b <- if isInfinite a+                       then setOffset n *> fail "double out of bounds"+                       else return a+                return (DoubleLit (DhallDouble b))++            alternative01 = do+                a <- try naturalLiteral+                return (NaturalLit a)++            alternative02 = do+                a <- try integerLiteral+                return (IntegerLit a)++            alternative04 = (do+                _openBrace++                src0 <- src whitespace+                mComma <- optional _comma++                -- `src1` corresponds to the prefix whitespace of the first key-value+                -- pair. This is done to avoid using `try` to recover the consumed+                -- whitespace when the comma is not consumed+                src1 <- case mComma of+                    Nothing -> return src0+                    Just _ -> src whitespace++                a <- recordTypeOrLiteral src1++                _closeBrace++                return a ) <?> "literal"++            alternative09 = do+                a <- try doubleInfinity+                return (DoubleLit (DhallDouble a))++            builtin = do+                let predicate c =+                            c == 'N'+                        ||  c == 'I'+                        ||  c == 'D'+                        ||  c == 'L'+                        ||  c == 'O'+                        ||  c == 'B'+                        ||  c == 'S'+                        ||  c == 'T'+                        ||  c == 'F'+                        ||  c == 'K'++                let nan = DhallDouble (0.0/0.0)++                c <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)++                case c of+                    'N' ->+                        choice+                            [ NaturalFold      <$ _NaturalFold+                            , NaturalBuild     <$ _NaturalBuild+                            , NaturalIsZero    <$ _NaturalIsZero+                            , NaturalEven      <$ _NaturalEven+                            , NaturalOdd       <$ _NaturalOdd+                            , NaturalSubtract  <$ _NaturalSubtract+                            , NaturalToInteger <$ _NaturalToInteger+                            , NaturalShow      <$ _NaturalShow+                            , Natural          <$ _Natural+                            , None             <$ _None+                            , DoubleLit nan    <$ _NaN+                            ]+                    'I' ->+                        choice+                            [ IntegerClamp     <$ _IntegerClamp+                            , IntegerNegate    <$ _IntegerNegate+                            , IntegerShow      <$ _IntegerShow+                            , IntegerToDouble  <$ _IntegerToDouble+                            , Integer          <$ _Integer+                            ]++                    'D' ->+                        choice+                            [ DateShow         <$ _DateShow+                            , Date             <$ _Date+                            , DoubleShow       <$ _DoubleShow+                            , Double           <$ _Double+                            ]+                    'L' ->+                        choice+                            [ ListBuild        <$ _ListBuild+                            , ListFold         <$ _ListFold+                            , ListLength       <$ _ListLength+                            , ListHead         <$ _ListHead+                            , ListLast         <$ _ListLast+                            , ListIndexed      <$ _ListIndexed+                            , ListReverse      <$ _ListReverse+                            , List             <$ _List+                            ]+                    'O' ->    Optional         <$ _Optional+                    'B' ->+                        choice+                            [ Bool             <$ _Bool+                            , Bytes            <$ _Bytes+                            ]+                    'S' ->    Const Sort       <$ _Sort+                    'T' ->+                        choice+                            [ TextReplace      <$ _TextReplace+                            , TextShow         <$ _TextShow+                            , Text             <$ _Text+                            , TimeZoneShow     <$ _TimeZoneShow+                            , TimeZone         <$ _TimeZone+                            , TimeShow         <$ _TimeShow+                            , Time             <$ _Time+                            , BoolLit True     <$ _True+                            , Const Type       <$ _Type+                            ]+                    'F' ->    BoolLit False    <$ _False+                    'K' ->    Const Kind       <$ _Kind+                    _   ->    empty++            alternative37 = do+                a <- identifier+                return (Var a)++            alternative38 = do+                _openParens+                whitespace+                a <- expression+                whitespace+                _closeParens+                return a++    doubleQuotedChunk =+            choice+                [ interpolation+                , unescapedCharacterFast+                , unescapedCharacterSlow+                , escapedCharacter+                ]+          where+            interpolation = do+                _ <- text "${"+                e <- completeExpression_+                _ <- char '}'+                return (Chunks [(mempty, e)] mempty)++            unescapedCharacterFast = do+                t <- Text.Megaparsec.takeWhile1P Nothing predicate+                return (Chunks [] t)+              where+                predicate c =+                    (   ('\x20' <= c && c <= '\x21'    )+                    ||  ('\x23' <= c && c <= '\x5B'    )+                    ||  ('\x5D' <= c && c <= '\x10FFFF')+                    ) && c /= '$'++            unescapedCharacterSlow = do+                _ <- char '$'+                return (Chunks [] "$")++            escapedCharacter = do+                _ <- char '\\'+                c <- choice+                    [ quotationMark+                    , dollarSign+                    , backSlash+                    , forwardSlash+                    , backSpace+                    , formFeed+                    , lineFeed+                    , carriageReturn+                    , tab+                    , unicode+                    ]+                return (Chunks [] (Data.Text.singleton c))+              where+                quotationMark = char '"'++                dollarSign = char '$'++                backSlash = char '\\'++                forwardSlash = char '/'++                backSpace = do _ <- char 'b'; return '\b'++                formFeed = do _ <- char 'f'; return '\f'++                lineFeed = do _ <- char 'n'; return '\n'++                carriageReturn = do _ <- char 'r'; return '\r'++                tab = do _ <- char 't'; return '\t'++                unicode = do+                    _  <- char 'u';++                    let toNumber = Data.List.foldl' (\x y -> x * 16 + y) 0++                    let fourCharacterEscapeSequence = do+                            ns <- Control.Monad.replicateM 4 hexNumber++                            let number = toNumber ns++                            Control.Monad.guard (validCodepoint number)+                                <|> fail "Invalid Unicode code point"++                            return number++                    let bracedEscapeSequence = do+                            _  <- char '{'+                            ns <- some hexNumber++                            let number = toNumber ns++                            Control.Monad.guard (number <= 0x10FFFD && validCodepoint number)+                                <|> fail "Invalid Unicode code point"++                            _  <- char '}'++                            return number++                    n <- bracedEscapeSequence <|> fourCharacterEscapeSequence++                    return (Char.chr n)++    doubleQuotedLiteral = do+            _      <- char '"'+            chunks <- Text.Megaparsec.many doubleQuotedChunk+            _      <- char '"'+            return (mconcat chunks)++    singleQuoteContinue =+            choice+                [ escapeSingleQuotes+                , interpolation+                , escapeInterpolation+                , endLiteral+                , unescapedCharacterFast+                , unescapedCharacterSlow+                , tab+                , endOfLine_+                ]+          where+                escapeSingleQuotes = do+                    _ <- "'''" :: Parser Text+                    b <- singleQuoteContinue+                    return ("''" <> b)++                interpolation = do+                    _ <- text "${"+                    a <- completeExpression_+                    _ <- char '}'+                    b <- singleQuoteContinue+                    return (Chunks [(mempty, a)] mempty <> b)++                escapeInterpolation = do+                    _ <- text "''${"+                    b <- singleQuoteContinue+                    return ("${" <> b)++                endLiteral = do+                    _ <- text "''"+                    return mempty++                unescapedCharacterFast = do+                    a <- Text.Megaparsec.takeWhile1P Nothing predicate+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)+                  where+                    predicate c =+                        ('\x20' <= c && c <= '\x10FFFF') && c /= '$' && c /= '\''++                unescapedCharacterSlow = do+                    a <- satisfy predicate+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)+                  where+                    predicate c = c == '$' || c == '\''++                endOfLine_ = do+                    a <- "\n" <|> "\r\n"+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)++                tab = do+                    _ <- char '\t' <?> "tab"+                    b <- singleQuoteContinue+                    return ("\t" <> b)++    singleQuoteLiteral = do+            _ <- text "''"++            _ <- endOfLine++            a <- singleQuoteContinue++            return (Dhall.Syntax.toDoubleQuoted a)++    textLiteral = (do+        literal <- doubleQuotedLiteral <|> singleQuoteLiteral+        return (TextLit literal) ) <?> "literal"++    bytesLiteral = (do+        _ <- text "0x\""++        let byte = do+                nibble0 <- Text.Megaparsec.satisfy hexdig+                nibble1 <- Text.Megaparsec.satisfy hexdig+                return ([nibble0, nibble1] `base` 16)++        bytes <- Text.Megaparsec.many byte++        _ <- char '"'++        return (BytesLit (ByteString.pack bytes)) ) <?> "literal"++    recordTypeOrLiteral firstSrc0 =+            choice+                [ emptyRecordLiteral+                , nonEmptyRecordTypeOrLiteral firstSrc0+                , emptyRecordType+                ]++    emptyRecordLiteral = do+        _equal++        _ <- optional (try (whitespace *> _comma))++        whitespace+        return (RecordLit mempty)++    emptyRecordType = return (Record mempty)++    nonEmptyRecordTypeOrLiteral firstSrc0 = do+            let nonEmptyRecordType = do+                    (firstKeySrc1, a) <- try $ do+                        a <- anyLabelOrSome+                        s <- src whitespace+                        _colon+                        return (s, a)++                    firstKeySrc2 <- src nonemptyWhitespace++                    b <- expression++                    e <- Text.Megaparsec.many $ do+                        (src0', c) <- try $ do+                            _comma+                            src0' <- src whitespace+                            c <- anyLabelOrSome+                            return (src0', c)++                        src1 <- src whitespace++                        _colon++                        src2 <- src nonemptyWhitespace++                        d <- expression++                        whitespace++                        return (c, RecordField (Just src0') d (Just src1) (Just src2))++                    _ <- optional (whitespace *> _comma)+                    whitespace++                    m <- toMap ((a, RecordField (Just firstSrc0) b (Just firstKeySrc1) (Just firstKeySrc2)) : e)++                    return (Record m)++            let keysValue maybeSrc = do+                    firstSrc0' <- case maybeSrc of+                        Just src0 -> return src0+                        Nothing -> src whitespace+                    firstLabel <- anyLabelOrSome+                    firstSrc1 <- src whitespace++                    let parseLabelWithWhsp = try $ do+                            _dot+                            src0 <- src whitespace+                            l <- anyLabelOrSome+                            src1 <- src whitespace+                            return (src0, l, src1)++                    restKeys <- Combinators.many parseLabelWithWhsp+                    let keys = (firstSrc0', firstLabel, firstSrc1) :| restKeys++                    let normalRecordEntry = do+                            try _equal++                            lastSrc2 <- src whitespace++                            value <- expression++                            let cons (s0, key, s1) (key', values) =+                                    (key, RecordField (Just s0) (RecordLit [ (key', values) ]) (Just s1) Nothing)++                            let (lastSrc0, lastLabel, lastSrc1) = NonEmpty.last keys+                            let nil = (lastLabel, RecordField (Just lastSrc0) value (Just lastSrc1) (Just lastSrc2))++                            return (foldr cons nil (NonEmpty.init keys))++                    let punnedEntry =+                            case keys of+                                (s0, x, s1) :| [] -> return (x, RecordField (Just s0) (Var (V x 0)) (Just s1) Nothing)+                                _       -> empty++                    (normalRecordEntry <|> punnedEntry) <* whitespace++            let nonEmptyRecordLiteral = do+                    a <- keysValue (Just firstSrc0)++                    as <- many (try (_comma *> keysValue Nothing))++                    _ <- optional (whitespace *> _comma)++                    whitespace++                    let combine k = liftA2 $ \rf rf' -> makeRecordField $ Combine mempty (Just k)+                                                            (recordFieldValue rf')+                                                            (recordFieldValue rf)++                    m <- toMapWith combine (a : as)++                    return (RecordLit m)++            nonEmptyRecordType <|> nonEmptyRecordLiteral++    unionType = (do+            _openAngle++            whitespace++            let unionTypeEntry = do+                    a <- anyLabelOrSome++                    whitespace++                    b <- optional (_colon *> nonemptyWhitespace *> expression <* whitespace)++                    return (a, b)++            let nonEmptyUnionType = do+                    kv <- try (optional (_bar *> whitespace) *> unionTypeEntry)++                    kvs <- many (try (_bar *> whitespace *> unionTypeEntry))++                    m <- toMap (kv : kvs)++                    _ <- optional (_bar *> whitespace)++                    _closeAngle++                    return (Union m)++            let emptyUnionType = do+                    try (optional (_bar *> whitespace) *> _closeAngle)++                    return (Union mempty)++            nonEmptyUnionType <|> emptyUnionType ) <?> "literal"++    listLiteral = (do+            _openBracket++            whitespace++            let nonEmptyListLiteral = do+                    a <- try (optional (_comma *> whitespace) *> expression)++                    whitespace++                    as <- many (try (_comma *> whitespace *> expression) <* whitespace)++                    _ <- optional (_comma *> whitespace)++                    _closeBracket++                    return (ListLit Nothing (Data.Sequence.fromList (a : as)))++            let emptyListLiteral = do+                    try (optional (_comma *> whitespace) *> _closeBracket)++                    return (ListLit Nothing mempty)++            nonEmptyListLiteral <|> emptyListLiteral) <?> "literal"++{-| Parse an environment variable import++    This corresponds to the @env@ rule from the official grammar+-}+env :: Parser ImportType+env = do+    _ <- text "env:"+    a <- (alternative0 <|> alternative1)+    return (Env a)+  where+    alternative0 = bashEnvironmentVariable++    alternative1 = do+        _ <- char '"'+        a <- posixEnvironmentVariable+        _ <- char '"'+        return a++-- | Parse a local import without trailing whitespace+localOnly :: Parser ImportType+localOnly =+    choice+        [ parentPath+        , herePath+        , homePath+        , try absolutePath+        ]+  where+    parentPath = do+        _    <- ".." :: Parser Text+        file <- file_ FileComponent++        return (Local Parent file)++    herePath = do+        _    <- "." :: Parser Text+        file <- file_ FileComponent++        return (Local Here file)++    homePath = do+        _    <- "~" :: Parser Text+        file <- file_ FileComponent++        return (Local Home file)++    absolutePath = do+        file <- file_ FileComponent++        return (Local Absolute file)++{-| Parse a local import++    This corresponds to the @local@ rule from the official grammar+-}+local :: Parser ImportType+local = do+    a <- localOnly+    return a++{-| Parse an HTTP(S) import++    This corresponds to the @http@ rule from the official grammar+-}+http :: Parser ImportType+http = do+    url <- httpRaw+    headers <- optional (do+        try (whitespace *> _using *> nonemptyWhitespace)+        importExpression import_ )+    return (Remote (url { headers }))++{-| Parse a `Missing` import++    This corresponds to the @missing@ rule from the official grammar+-}+missing :: Parser ImportType+missing = do+  _missing+  return Missing++{-| Parse an `ImportType`++    This corresponds to the @import-type@ rule from the official grammar+-}+importType_ :: Parser ImportType+importType_ = do+    let predicate c =+            c == '~' || c == '.' || c == '/' || c == 'h' || c == 'e' || c == 'm'++    _ <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)++    choice [ local, http, env, missing ]++{-| Parse a `Dhall.Crypto.SHA256Digest`++    This corresponds to the @hash@ rule from the official grammar+-}+importHash_ :: Parser Dhall.Crypto.SHA256Digest+importHash_ = do+    _ <- text "sha256:"+    t <- count 64 (satisfy hexdig <?> "hex digit")+    let strictBytes16 = Data.Text.Encoding.encodeUtf8 t+    strictBytes <- case Base16.decode strictBytes16 of+        Left  string      -> fail string+        Right strictBytes -> return strictBytes+    case Dhall.Crypto.sha256DigestFromByteString strictBytes of+      Nothing -> fail "Invalid sha256 hash"+      Just h  -> pure h++{-| Parse an `ImportHashed`++    This corresponds to the @import-hashed@ rule from the official grammar+-}+importHashed_ :: Parser ImportHashed+importHashed_ = do+    importType <- importType_+    hash       <- optional (try (nonemptyWhitespace *> importHash_))+    return (ImportHashed {..})++{-| Parse an `Import`++    This corresponds to the @import@ rule from the official grammar+-}+import_ :: Parser Import+import_ = (do+    importHashed <- importHashed_+    importMode   <- alternative <|> pure Code+    return (Import {..}) ) <?> "import"+  where+    alternative = do+      try (whitespace *> _as *> nonemptyWhitespace)++      (_Text >> pure RawText)+          <|> (_Location >> pure Location)+          <|> (_Bytes >> pure RawBytes)++-- | 'ApplicationExprInfo' distinguishes certain subtypes of application+-- expressions.+data ApplicationExprInfo+    = NakedMergeOrSomeOrToMap+    -- ^ @merge x y@, @Some x@ or @toMap x@, unparenthesized.+    | ImportExpr+    -- ^ An import expression.+    | ApplicationExpr+    -- ^ Any other application expression.
+ src/Dhall/Parser/Token.hs view
@@ -0,0 +1,1438 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++-- | Parse Dhall tokens. Even though we don't have a tokenizer per-se this+---  module is useful for keeping some small parsing utilities.+module Dhall.Parser.Token (+    endOfLine,+    validCodepoint,+    whitespace,+    lineComment,+    lineCommentPrefix,+    blockComment,+    nonemptyWhitespace,+    bashEnvironmentVariable,+    posixEnvironmentVariable,+    ComponentType(..),+    text,+    char,+    file_,+    label,+    anyLabelOrSome,+    anyLabel,+    labels,+    httpRaw,+    hexdig,+    identifier,+    hexNumber,+    signPrefix,+    doubleLiteral,+    doubleInfinity,+    naturalLiteral,+    integerLiteral,+    dateFullYear,+    dateMonth,+    dateMday,+    timeHour,+    timeMinute,+    timeSecond,+    timeSecFrac,+    _Optional,+    _if,+    _then,+    _else,+    _let,+    _in,+    _as,+    _using,+    _merge,+    _toMap,+    _showConstructor,+    _assert,+    _Some,+    _None,+    _NaturalFold,+    _NaturalBuild,+    _NaturalIsZero,+    _NaturalEven,+    _NaturalOdd,+    _NaturalToInteger,+    _NaturalShow,+    _NaturalSubtract,+    _IntegerClamp,+    _IntegerNegate,+    _IntegerShow,+    _IntegerToDouble,+    _DoubleShow,+    _ListBuild,+    _ListFold,+    _ListLength,+    _ListHead,+    _ListLast,+    _ListIndexed,+    _ListReverse,+    _Bool,+    _Bytes,+    _Natural,+    _Integer,+    _Double,+    _Text,+    _TextReplace,+    _TextShow,+    _Date,+    _DateShow,+    _Time,+    _TimeShow,+    _TimeZone,+    _TimeZoneShow,+    _List,+    _True,+    _False,+    _NaN,+    _Type,+    _Kind,+    _Sort,+    _Location,+    _equal,+    _or,+    _plus,+    _textAppend,+    _listAppend,+    _and,+    _times,+    _doubleEqual,+    _notEqual,+    _dot,+    _openBrace,+    _closeBrace,+    _openBracket,+    _closeBracket,+    _openAngle,+    _closeAngle,+    _bar,+    _comma,+    _openParens,+    _closeParens,+    _colon,+    _at,+    _equivalent,+    _missing,+    _importAlt,+    _combine,+    _combineTypes,+    _prefer,+    _lambda,+    _forall,+    _arrow,+    _doubleColon,+    _with,+    ) where++import Dhall.Parser.Combinators++import Control.Applicative     (Alternative (..), optional)+import Data.Bits               ((.&.))+import Data.Fixed              (Pico)+import Data.Functor            (void, ($>))+import Data.Ratio              ((%))+import Data.Text               (Text)+import Dhall.Syntax+import Text.Parser.Combinators (choice, try, (<?>))++import qualified Control.Monad              as Monad+import qualified Data.Char                  as Char+import qualified Data.Foldable+import qualified Data.HashSet+import qualified Data.List                  as List+import qualified Data.List.NonEmpty+import qualified Data.Scientific            as Scientific+import qualified Data.Text+import qualified Text.Megaparsec+import qualified Text.Megaparsec.Char.Lexer+import qualified Text.Parser.Char+import qualified Text.Parser.Combinators+import qualified Text.Parser.Token++import Numeric.Natural (Natural)++-- | Match an end-of-line character sequence+endOfLine :: Parser Text+endOfLine =+    (   Text.Parser.Char.text "\n"  +    <|> Text.Parser.Char.text "\r\n"+    ) <?> "newline"++-- | Returns `True` if the given `Int` is a valid Unicode codepoint+validCodepoint :: Int -> Bool+validCodepoint c =+    not (category == Char.Surrogate+      || c .&. 0xFFFE == 0xFFFE+      || c .&. 0xFFFF == 0xFFFF)+  where+    category = Char.generalCategory (Char.chr c)++{-| Parse 0 or more whitespace characters (including comments)++    This corresponds to the @whsp@ rule in the official grammar+-}+whitespace :: Parser ()+whitespace = Text.Parser.Combinators.skipMany whitespaceChunk++{-| Parse 1 or more whitespace characters (including comments)++    This corresponds to the @whsp1@ rule in the official grammar+-}+nonemptyWhitespace :: Parser ()+nonemptyWhitespace = Text.Parser.Combinators.skipSome whitespaceChunk++alpha :: Char -> Bool+alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')++digit :: Char -> Bool+digit c = '\x30' <= c && c <= '\x39'++alphaNum :: Char -> Bool+alphaNum c = alpha c || digit c++{-| Parse a hex digit (uppercase or lowercase)++    This corresponds to the @HEXDIG@ rule in the official grammar+-}+hexdig :: Char -> Bool+hexdig c =+        ('0' <= c && c <= '9')+    ||  ('A' <= c && c <= 'F')+    ||  ('a' <= c && c <= 'f')++-- | Parse a leading @+@ or @-@ sign+signPrefix :: Num a => Parser (a -> a)+signPrefix = (do+    let positive = fmap (\_ -> id    ) (char '+')+    let negative = fmap (\_ -> negate) (char '-')+    positive <|> negative ) <?> "sign"++{-| Parse a `Dhall.Syntax.Double` literal++    This corresponds to the @double-literal@ rule from the official grammar+-}+doubleLiteral :: Parser Double+doubleLiteral = (do+    -- We don't use `Text.Parser.Token.double` since that consumes trailing+    -- whitespace and there is no whitespace-free alternative.  See:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1646+    -- https://github.com/dhall-lang/dhall-haskell/pull/1647+    --+    -- We also don't use `Text.Megaparsec.Char.Lexer.float` because that+    -- transitively depends on `Data.Char.toTitle` which is broken on older+    -- versions of GHCJS that we still support.  See:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1681+    -- https://github.com/ghcjs/ghcjs-base/issues/62+    --+    -- Also, hand-writing the parser code for `Double` literals helps to better+    -- ensure that we follow the standard exactly as written.+    sign <- signPrefix <|> pure id++    x <- Text.Parser.Token.decimal++    let alternative0 = do+            y <- fraction++            e <- exponent' <|> pure 1++            return ((fromInteger x + y) * e)++    let alternative1 = do+            expo <- exponent'++            return (fromInteger x * expo)++    n <- alternative0 <|> alternative1++    return (sign (Scientific.toRealFloat n)) ) <?> "literal"+  where+    fraction = do+        _ <- Text.Parser.Char.char '.'++        digits <- some Text.Parser.Char.digit++        let snoc y d =+              y + Scientific.scientific (fromIntegral (Char.digitToInt d)) (Scientific.base10Exponent y - 1)++        return (List.foldl' snoc 0 digits)++    exponent' = do+        _ <- Text.Parser.Char.oneOf "eE"++        sign <- signPrefix <|> pure id++        x <- Text.Parser.Token.decimal++        return (Scientific.scientific 1 (fromInteger (sign x)))++{-| Parse a signed @Infinity@++    This corresponds to the @minus-infinity-literal@ and @plus-infinity-literal@+    rules from the official grammar+-}+doubleInfinity :: Parser Double+doubleInfinity = (do+    let negative = fmap (\_ -> negate) (char '-')+    sign <- negative <|> pure id+    a <- text "Infinity" >> return (1.0/0.0)+    return (sign a) ) <?> "literal"++{-| Parse an `Dhall.Syntax.Integer` literal++    This corresponds to the @integer-literal@ rule from the official grammar+-}+integerLiteral :: Parser Integer+integerLiteral = (do+    sign <- signPrefix+    a    <- naturalLiteral+    return (sign (fromIntegral a)) ) <?> "literal"++{-| Parse a `Dhall.Syntax.Natural` literal++    This corresponds to the @natural-literal@ rule from the official grammar+-}+naturalLiteral :: Parser Natural+naturalLiteral = (do+    a <-    binary+        <|> hexadecimal+        <|> decimal+        <|> (char '0' $> 0)+    return a ) <?> "literal"+  where+    binary = try (char '0' >> char 'b' >> Text.Megaparsec.Char.Lexer.binary)+    hexadecimal = try (char '0' >> char 'x' >> Text.Megaparsec.Char.Lexer.hexadecimal)+    decimal = do+        n <- headDigit+        ns <- many tailDigit+        return (mkNum (n:ns))+      where+        headDigit = decimalDigit nonZeroDigit <?> "non-zero digit"+          where+            nonZeroDigit c = '1' <= c && c <= '9'++        tailDigit = decimalDigit digit <?> "digit"++        decimalDigit predicate = do+            c <- Text.Parser.Char.satisfy predicate+            return (fromIntegral (Char.ord c - Char.ord '0'))++        mkNum = Data.Foldable.foldl' step 0+          where+            step acc x = acc * 10 + x++{-| Parse a 4-digit year++    This corresponds to the @date-fullyear@ rule from the official grammar+-}+dateFullYear :: Parser Integer+dateFullYear = do+    digits <- Monad.replicateM 4 (Text.Parser.Char.satisfy digit)++    return (digits `base` 10)++{-| Parse a 2-digit month++    This corresponds to the @date-month@ rule from the official grammar+-}+dateMonth :: Parser Int+dateMonth = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let month = digits `base` 10++    if 1 <= month && month <= 12+        then return month+        else fail "Invalid month"++{-| Parse a 2-digit day of the month++    This corresponds to the @date-mday@ rule from the official grammar+-}+dateMday :: Parser Int+dateMday = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let day = digits `base` 10++    if 1 <= day && day <= 31+        then return day+        else fail "Invalid day"++{-| Parse a 2-digit hour++    This corresponds to the @time-hour@ rule from the official grammar+-}+timeHour :: Parser Int+timeHour = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let hour = digits `base` 10++    if 0 <= hour && hour < 24+        then return hour+        else fail "Invalid hour"++{-| Parse a 2-digit minute++    This corresponds to the @time-minute@ rule from the official grammar+-}+timeMinute :: Parser Int+timeMinute = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let minute = digits `base` 10++    if 0 <= minute && minute < 60+        then return minute+        else fail "Invalid minute"++{-| Parse a 2-digit second++    This corresponds to the @time-second@ rule from the official grammar+-}+timeSecond :: Parser Pico+timeSecond = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let second = digits `base` 10++    if 0 <= second && second < 60+        then return second+        else fail "Invalid second"++{-| Parse the fractional component of a second++    This corresponds to the @time-secfrac@ rule from the official grammar+-}+timeSecFrac :: Parser (Pico, Word)+timeSecFrac = do+    _ <- Text.Parser.Char.text "."++    digits <- some (Text.Parser.Char.satisfy digit)++    let precision = fromIntegral (length digits)++    return (fromRational ((digits `base` 10) % (10 ^ precision)), precision)++{-| Parse an identifier (i.e. a variable or built-in)++    Variables can have an optional index to disambiguate shadowed variables++    This corresponds to the @identifier@ rule from the official grammar+-}+identifier :: Parser Var+identifier = do+    x <- label++    let indexed = try $ do+            whitespace+            _at+            whitespace+            n <- naturalLiteral+            return (fromIntegral n)++    n <- indexed <|> pure 0+    return (V x n)++whitespaceChunk :: Parser ()+whitespaceChunk =+    choice+        [ void (Dhall.Parser.Combinators.takeWhile1 predicate)+        , void (Text.Parser.Char.text "\r\n" <?> "newline")+        , void lineComment+        , void blockComment+        ] <?> "whitespace"+  where+    predicate c = c == ' ' || c == '\t' || c == '\n'++-- | Parse a hexademical number and convert to the corresponding `Int`+hexNumber :: Parser Int+hexNumber = choice [ hexDigit, hexUpper, hexLower ]+  where+    hexDigit = do+        c <- Text.Parser.Char.satisfy predicate+        return (Char.ord c - Char.ord '0')+      where+        predicate c = '0' <= c && c <= '9'++    hexUpper = do+        c <- Text.Parser.Char.satisfy predicate+        return (10 + Char.ord c - Char.ord 'A')+      where+        predicate c = 'A' <= c && c <= 'F'++    hexLower = do+        c <- Text.Parser.Char.satisfy predicate+        return (10 + Char.ord c - Char.ord 'a')+      where+        predicate c = 'a' <= c && c <= 'f'++-- | Same as `lineComment` except that this doesn't parse the end-of-line+--   character+lineCommentPrefix :: Parser Text+lineCommentPrefix = do+    _ <- text "--"++    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++    commentText <- Dhall.Parser.Combinators.takeWhile predicate++    return ("--" <> commentText)++-- | Parse a Dhall's single-line comment, starting from `--` and until the+--   last character of the line /before/ the end-of-line character+lineComment :: Parser Text+lineComment = try (lineCommentPrefix <* endOfLine)++-- | Parsed text doesn't include opening braces+blockComment :: Parser Text+blockComment = do+    _ <- text "{-"+    c <- blockCommentContinue+    pure ("{-" <> c <> "-}")++blockCommentChunk :: Parser Text+blockCommentChunk =+    choice+        [ blockComment  -- Nested block comment+        , characters+        , character+        , endOfLine+        ]+  where+    characters = (Dhall.Parser.Combinators.takeWhile1 predicate)+      where+        predicate c =+                '\x20' <= c && c <= '\x10FFFF' && c /= '-' && c /= '{'+            ||  c == '\n'+            ||  c == '\t'++    character = (Dhall.Parser.Combinators.satisfy predicate)+      where+        predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t'++blockCommentContinue :: Parser Text+blockCommentContinue = endOfComment <|> continue+  where+    endOfComment = void (text "-}") *> pure ""++    continue = do+        c <- blockCommentChunk+        c' <- blockCommentContinue+        pure (c <> c')++simpleLabel :: Bool -> Parser Text+simpleLabel allowReserved = try $ do+    c    <- Text.Parser.Char.satisfy headCharacter+    rest <- Dhall.Parser.Combinators.takeWhile tailCharacter+    let t = Data.Text.cons c rest+    let isNotAKeyword = not $ t `Data.HashSet.member` reservedKeywords+    let isNotAReservedIdentifier = not $ t `Data.HashSet.member` reservedIdentifiers+    Monad.guard (isNotAKeyword && (allowReserved || isNotAReservedIdentifier))+    return t++headCharacter :: Char -> Bool+headCharacter c = alpha c || c == '_'++tailCharacter :: Char -> Bool+tailCharacter c = alphaNum c || c == '_' || c == '-' || c == '/'++backtickLabel :: Parser Text+backtickLabel = do+    _ <- char '`'+    t <- Dhall.Parser.Combinators.takeWhile predicate+    _ <- char '`'+    return t+  where+    predicate c =+            '\x20' <= c && c <= '\x5F'+        ||  '\x61' <= c && c <= '\x7E'++{-| Parse a braced sequence of comma-separated labels++    For example, this is used to parse the record projection syntax++    This corresponds to the @labels@ rule in the official grammar+-}+labels :: Parser [Text]+labels = do+    _openBrace++    whitespace++    nonEmptyLabels <|> emptyLabels+  where+    emptyLabels = do+        try (optional (_comma *> whitespace) *> _closeBrace)++        pure []++    nonEmptyLabels = do+        x  <- try (optional (_comma *> whitespace) *> anyLabelOrSome)++        whitespace++        xs <- many (try (_comma *> whitespace *> anyLabelOrSome) <* whitespace)++        _ <- optional (_comma *> whitespace)++        _closeBrace++        return (x : xs)++{-| Parse a label (e.g. a variable\/field\/alternative name)++    Rejects labels that match built-in names (e.g. @Natural/even@)++    This corresponds to the @nonreserved-label@ rule in the official grammar+-}+label :: Parser Text+label = backtickLabel <|> simpleLabel False <?> "label"++{-| Same as `label` except that built-in names are allowed++    This corresponds to the @any-label@ rule in the official grammar+-}+anyLabel :: Parser Text+anyLabel = (do+    t <- backtickLabel <|> simpleLabel True+    return t ) <?> "any label"++{-| Same as `anyLabel` except that `Some` is allowed++    This corresponds to the @any-label-or-some@ rule in the official grammar+-}++anyLabelOrSome :: Parser Text+anyLabelOrSome = try anyLabel <|> ("Some" <$ _Some)++{-| Parse a valid Bash environment variable name++    This corresponds to the @bash-environment-variable@ rule in the official+    grammar+-}+bashEnvironmentVariable :: Parser Text+bashEnvironmentVariable = satisfy predicate0 <> star (satisfy predicate1)+  where+    predicate0 c = alpha c || c == '_'++    predicate1 c = alphaNum c || c == '_'++{-| Parse a valid POSIX environment variable name, which permits a wider range+    of characters than a Bash environment variable name++    This corresponds to the @posix-environment-variable@ rule in the official+    grammar+-}+posixEnvironmentVariable :: Parser Text+posixEnvironmentVariable = plus posixEnvironmentVariableCharacter++posixEnvironmentVariableCharacter :: Parser Text+posixEnvironmentVariableCharacter =+    escapeCharacter <|> satisfy predicate1+  where+    escapeCharacter = do+        _ <- char '\\'++        c <- Text.Parser.Char.satisfy (`elem` ("\"\\abfnrtv" :: String))++        case c of+            '"'  -> return "\""+            '\\' -> return "\\"+            'a'  -> return "\a"+            'b'  -> return "\b"+            'f'  -> return "\f"+            'n'  -> return "\n"+            'r'  -> return "\r"+            't'  -> return "\t"+            'v'  -> return "\v"+            _    -> empty++    predicate1 c =+            ('\x20' <= c && c <= '\x21')+        ||  ('\x23' <= c && c <= '\x3C')+        ||  ('\x3E' <= c && c <= '\x5B')+        ||  ('\x5D' <= c && c <= '\x7E')++quotedPathCharacter :: Char -> Bool+quotedPathCharacter c =+        ('\x20' <= c && c <= '\x21')+    ||  ('\x23' <= c && c <= '\x2E')+    ||  ('\x30' <= c && c <= '\x10FFFF')++{-| The @pathComponent@ function uses this type to distinguish whether to parse+    a URL path component or a file path component+-}+data ComponentType = URLComponent | FileComponent++-- | Parse a path component+pathComponent :: ComponentType -> Parser Text+pathComponent componentType = do+    _ <- "/" :: Parser Text++    let pathData =+            case componentType of+                FileComponent ->+                    Text.Megaparsec.takeWhile1P Nothing Dhall.Syntax.pathCharacter+                URLComponent ->+                    star pchar++    let quotedPathData = do+            _ <- char '"'+            t <- Text.Megaparsec.takeWhile1P Nothing quotedPathCharacter+            _ <- char '"'+            return t++    case componentType of+        FileComponent -> quotedPathData <|> pathData+        URLComponent -> pathData++-- | Parse a `File`+file_ :: ComponentType -> Parser File+file_ componentType = do+    let emptyPath =+            case componentType of+                URLComponent  -> pure (pure "")+                FileComponent -> empty++    path <- Data.List.NonEmpty.some1 (pathComponent componentType) <|> emptyPath++    let directory = Directory (reverse (Data.List.NonEmpty.init path))+    let file      = Data.List.NonEmpty.last path++    return (File {..})++scheme_ :: Parser Scheme+scheme_ =+        ("http" :: Parser Text)+    *>  ((("s" :: Parser Text) *> pure HTTPS) <|> pure HTTP)+    <*  ("://" :: Parser Text)++{-| Parse an HTTP(S) URL without trailing whitespace++    This corresponds to the @http-raw@ rule in the official grammar+-}+httpRaw :: Parser URL+httpRaw = do+    scheme    <- scheme_+    authority <- authority_+    path      <- file_ URLComponent+    query     <- optional (("?" :: Parser Text) *> query_)++    let headers = Nothing++    return (URL {..})++authority_ :: Parser Text+authority_ = option (try (userinfo <> "@")) <> host <> option (":" <> port)++userinfo :: Parser Text+userinfo = star (satisfy predicate <|> pctEncoded)+  where+    predicate c = unreserved c || subDelims c || c == ':'++host :: Parser Text+host = choice [ ipLiteral, try ipV4Address, domain ]++port :: Parser Text+port = star (satisfy digit)++ipLiteral :: Parser Text+ipLiteral = "[" <> (ipV6Address <|> ipVFuture) <> "]"++ipVFuture :: Parser Text+ipVFuture = "v" <> plus (satisfy hexdig) <> "." <> plus (satisfy predicate)+  where+    predicate c = unreserved c || subDelims c || c == ':'++ipV6Address :: Parser Text+ipV6Address =+    choice+        [ try alternative0+        , try alternative1+        , try alternative2+        , try alternative3+        , try alternative4+        , try alternative5+        , try alternative6+        , try alternative7+        ,     alternative8+        ]+  where+    alternative0 = count 6 (h16 <> ":") <> ls32++    alternative1 = "::" <> count 5 (h16 <> ":") <> ls32++    alternative2 = option h16 <> "::" <> count 4 (h16 <> ":") <> ls32++    alternative3 =+            option (h16 <> range 0 1 (try (":" <> h16)))+        <>  "::"+        <>  count 3 (h16 <> ":")+        <>  ls32++    alternative4 =+            option (h16 <> range 0 2 (try (":" <> h16)))+        <>  "::"+        <>  count 2 (h16 <> ":")+        <>  ls32++    alternative5 =+            option (h16 <> range 0 3 (try (":" <> h16)))+        <>  "::"+        <>  h16+        <>  ":"+        <>  ls32++    alternative6 =+        option (h16 <> range 0 4 (try (":" <> h16))) <> "::" <> ls32++    alternative7 =+        option (h16 <> range 0 5 (try (":" <> h16))) <> "::" <> h16++    alternative8 =+        option (h16 <> range 0 6 (try (":" <> h16))) <> "::"++h16 :: Parser Text+h16 = range 1 3 (satisfy hexdig)++ls32 :: Parser Text+ls32 = try (h16 <> ":" <> h16) <|> ipV4Address++ipV4Address :: Parser Text+ipV4Address = decOctet <> "." <> decOctet <> "." <> decOctet <> "." <> decOctet++decOctet :: Parser Text+decOctet =+    choice+        [ try alternative4+        , try alternative3+        , try alternative2+        , try alternative1+        ,     alternative0+        ]+  where+    alternative0 = satisfy digit++    alternative1 = satisfy predicate <> satisfy digit+      where+        predicate c = '\x31' <= c && c <= '\x39'++    alternative2 = "1" <> count 2 (satisfy digit)++    alternative3 = "2" <> satisfy predicate <> satisfy digit+      where+        predicate c = '\x30' <= c && c <= '\x34'++    alternative4 = "25" <> satisfy predicate+      where+        predicate c = '\x30' <= c && c <= '\x35'++domain :: Parser Text+domain = domainLabel <> star ("." <> domainLabel ) <> option "."++domainLabel :: Parser Text+domainLabel = plus alphaNum_ <> star (plus "-" <> plus alphaNum_)+  where+    alphaNum_ = satisfy alphaNum++pchar :: Parser Text+pchar = satisfy predicate <|> pctEncoded+  where+    predicate c = unreserved c || subDelims c || c == ':' || c == '@'++query_ :: Parser Text+query_ = star (pchar <|> satisfy predicate)+  where+    predicate c = c == '/' || c == '?'++pctEncoded :: Parser Text+pctEncoded = "%" <> count 2 (satisfy hexdig)++subDelims :: Char -> Bool+subDelims c = c `elem` ("!$&'*+;=" :: String)++unreserved :: Char -> Bool+unreserved c =+    alphaNum c || c == '-' || c == '.' || c == '_' || c == '~'++{-| A variation on `Text.Parser.Char.text` that doesn't quote the expected+    in error messages+-}+text :: Data.Text.Text -> Parser Text+text t = Text.Parser.Char.text t <?> Data.Text.unpack t+{-# INLINE text #-}++{-| A variation on `Text.Parser.Char.char` that doesn't quote the expected+    token in error messages+-}+char :: Char -> Parser Char+char c = Text.Parser.Char.char c <?> [ c ]+{-# INLINE char #-}++reserved :: Data.Text.Text -> Parser ()+reserved x = void (text x)++reservedChar :: Char -> Parser ()+reservedChar c = void (char c)++builtin :: Data.Text.Text -> Parser ()+builtin x = reserved x <?> "built-in"+{-# INLINE builtin #-}++operator :: Data.Text.Text -> Parser ()+operator x = reserved x <?> "operator"+{-# INLINE operator #-}++operatorChar :: Char -> Parser ()+operatorChar x = reservedChar x <?> "operator"+{-# INLINE operatorChar #-}++keyword :: Data.Text.Text -> Parser ()+keyword x = try (void (text x)) <?> "keyword"++{-| Parse the @if@ keyword++    This corresponds to the @if@ rule from the official grammar+-}+_if :: Parser ()+_if = keyword "if"++{-| Parse the @then@ keyword++    This corresponds to the @then@ rule from the official grammar+-}+_then :: Parser ()+_then = keyword "then"++{-| Parse the @else@ keyword++    This corresponds to the @else@ rule from the official grammar+-}+_else :: Parser ()+_else = keyword "else"++{-| Parse the @let@ keyword++    This corresponds to the @let@ rule from the official grammar+-}+_let :: Parser ()+_let = keyword "let"++{-| Parse the @in@ keyword++    This corresponds to the @in@ rule from the official grammar+-}+_in :: Parser ()+_in = keyword "in"++{-| Parse the @as@ keyword++    This corresponds to the @as@ rule from the official grammar+-}+_as :: Parser ()+_as = keyword "as"++{-| Parse the @using@ keyword++    This corresponds to the @using@ rule from the official grammar+-}+_using :: Parser ()+_using = keyword "using"++{-| Parse the @merge@ keyword++    This corresponds to the @merge@ rule from the official grammar+-}+_merge :: Parser ()+_merge = keyword "merge"++{-| Parse the @toMap@ keyword++    This corresponds to the @toMap@ rule from the official grammar+-}+_toMap :: Parser ()+_toMap = keyword "toMap"++{-| Parse the @showConstructor@ keyword++    This corresponds to the @showConstructor@ rule from the official grammar+-}+_showConstructor :: Parser ()+_showConstructor = keyword "showConstructor"++{-| Parse the @assert@ keyword++    This corresponds to the @assert@ rule from the official grammar+-}+_assert :: Parser ()+_assert = keyword "assert"++-- | Parse the @with@ keyword+_with :: Parser ()+_with = keyword "with"++{-| Parse the @Some@ built-in++    This corresponds to the @Some@ rule from the official grammar+-}+_Some :: Parser ()+_Some = keyword "Some"++{-| Parse the @None@ built-in++    This corresponds to the @None@ rule from the official grammar+-}+_None :: Parser ()+_None = builtin "None"++{-| Parse the @Natural/fold@ built-in++    This corresponds to the @Natural-fold@ rule from the official grammar+-}+_NaturalFold :: Parser ()+_NaturalFold = builtin "Natural/fold"++{-| Parse the @Natural/build@ built-in++    This corresponds to the @Natural-build@ rule from the official grammar+-}+_NaturalBuild :: Parser ()+_NaturalBuild = builtin "Natural/build"++{-| Parse the @Natural/isZero@ built-in++    This corresponds to the @Natural-isZero@ rule from the official grammar+-}+_NaturalIsZero :: Parser ()+_NaturalIsZero = builtin "Natural/isZero"++{-| Parse the @Natural/even@ built-in++    This corresponds to the @Natural-even@ rule from the official grammar+-}+_NaturalEven :: Parser ()+_NaturalEven = builtin "Natural/even"++{-| Parse the @Natural/odd@ built-in++    This corresponds to the @Natural-odd@ rule from the official grammar+-}+_NaturalOdd :: Parser ()+_NaturalOdd = builtin "Natural/odd"++{-| Parse the @Natural/toInteger@ built-in++    This corresponds to the @Natural-toInteger@ rule from the official grammar+-}+_NaturalToInteger :: Parser ()+_NaturalToInteger = builtin "Natural/toInteger"++{-| Parse the @Natural/show@ built-in++    This corresponds to the @Natural-show@ rule from the official grammar+-}+_NaturalShow :: Parser ()+_NaturalShow = builtin "Natural/show"++{-| Parse the @Natural/subtract@ built-in++    This corresponds to the @Natural-subtract@ rule from the official grammar+-}+_NaturalSubtract :: Parser ()+_NaturalSubtract = builtin "Natural/subtract"++{-| Parse the @Integer/clamp@ built-in++    This corresponds to the @Integer-clamp@ rule from the official grammar+-}+_IntegerClamp :: Parser ()+_IntegerClamp = builtin "Integer/clamp"++{-| Parse the @Integer/negate@ built-in++    This corresponds to the @Integer-negate@ rule from the official grammar+-}+_IntegerNegate :: Parser ()+_IntegerNegate = builtin "Integer/negate"++{-| Parse the @Integer/show@ built-in++    This corresponds to the @Integer-show@ rule from the official grammar+-}+_IntegerShow :: Parser ()+_IntegerShow = builtin "Integer/show"++{-| Parse the @Integer/toDouble@ built-in++    This corresponds to the @Integer-toDouble@ rule from the official grammar+-}+_IntegerToDouble :: Parser ()+_IntegerToDouble = builtin "Integer/toDouble"++{-| Parse the @Double/show@ built-in++    This corresponds to the @Double-show@ rule from the official grammar+-}+_DoubleShow :: Parser ()+_DoubleShow = builtin "Double/show"++{-| Parse the @List/build@ built-in++    This corresponds to the @List-build@ rule from the official grammar+-}+_ListBuild :: Parser ()+_ListBuild = builtin "List/build"++{-| Parse the @List/fold@ built-in++    This corresponds to the @List-fold@ rule from the official grammar+-}+_ListFold :: Parser ()+_ListFold = builtin "List/fold"++{-| Parse the @List/length@ built-in++    This corresponds to the @List-length@ rule from the official grammar+-}+_ListLength :: Parser ()+_ListLength = builtin "List/length"++{-| Parse the @List/head@ built-in++    This corresponds to the @List-head@ rule from the official grammar+-}+_ListHead :: Parser ()+_ListHead = builtin "List/head"++{-| Parse the @List/last@ built-in++    This corresponds to the @List-last@ rule from the official grammar+-}+_ListLast :: Parser ()+_ListLast = builtin "List/last"++{-| Parse the @List/indexed@ built-in++    This corresponds to the @List-indexed@ rule from the official grammar+-}+_ListIndexed :: Parser ()+_ListIndexed = builtin "List/indexed"++{-| Parse the @List/reverse@ built-in++    This corresponds to the @List-reverse@ rule from the official grammar+-}+_ListReverse :: Parser ()+_ListReverse = builtin "List/reverse"++{-| Parse the @Bool@ built-in++    This corresponds to the @Bool@ rule from the official grammar+-}+_Bool :: Parser ()+_Bool = builtin "Bool"++{-| Parse the @Bytes@ built-in++    This corresponds to the @Bytes@ rule from the official grammar+-}+_Bytes :: Parser ()+_Bytes = builtin "Bytes"++{-| Parse the @Optional@ built-in++    This corresponds to the @Optional@ rule from the official grammar+-}+_Optional :: Parser ()+_Optional = builtin "Optional"++{-| Parse the @Natural@ built-in++    This corresponds to the @Natural@ rule from the official grammar+-}+_Natural :: Parser ()+_Natural = builtin "Natural"++{-| Parse the @Integer@ built-in++    This corresponds to the @Integer@ rule from the official grammar+-}+_Integer :: Parser ()+_Integer = builtin "Integer"++{-| Parse the @Double@ built-in++    This corresponds to the @Double@ rule from the official grammar+-}+_Double :: Parser ()+_Double = builtin "Double"++{-| Parse the @Text@ built-in++    This corresponds to the @Text@ rule from the official grammar+-}+_Text :: Parser ()+_Text = builtin "Text"++{-| Parse the @Text/replace@ built-in++    This corresponds to the @Text-replace@ rule from the official grammar+-}+_TextReplace :: Parser ()+_TextReplace = builtin "Text/replace"++{-| Parse the @Text/show@ built-in++    This corresponds to the @Text-show@ rule from the official grammar+-}+_TextShow :: Parser ()+_TextShow = builtin "Text/show"++{-| Parse the @Date@ bult-in++    This corresponds to the @Date@ rule from the official grammar+-}+_Date :: Parser ()+_Date = builtin "Date"++{-| Parse the @Date/show@ built-in++    This corresponds to the @Date-show@ rule from the official grammar+-}+_DateShow :: Parser ()+_DateShow = builtin "Date/show"++{-| Parse the @Time@ bult-in++    This corresponds to the @Time@ rule from the official grammar+-}+_Time :: Parser ()+_Time = builtin "Time"++{-| Parse the @Time/show@ built-in++    This corresponds to the @Time-show@ rule from the official grammar+-}+_TimeShow :: Parser ()+_TimeShow = builtin "Time/show"++{-| Parse the @TimeZone@ bult-in++    This corresponds to the @TimeZone@ rule from the official grammar+-}+_TimeZone :: Parser ()+_TimeZone = builtin "TimeZone"++{-| Parse the @TimeZone/show@ built-in++    This corresponds to the @TimeZone-show@ rule from the official grammar+-}+_TimeZoneShow :: Parser ()+_TimeZoneShow = builtin "TimeZone/show"++{-| Parse the @List@ built-in++    This corresponds to the @List@ rule from the official grammar+-}+_List :: Parser ()+_List = builtin "List"++{-| Parse the @True@ built-in++    This corresponds to the @True@ rule from the official grammar+-}+_True :: Parser ()+_True = builtin "True"++{-| Parse the @False@ built-in++    This corresponds to the @False@ rule from the official grammar+-}+_False :: Parser ()+_False = builtin "False"++{-| Parse a @NaN@ literal++    This corresponds to the @NaN@ rule from the official grammar+-}+_NaN :: Parser ()+_NaN = builtin "NaN"++{-| Parse the @Type@ built-in++    This corresponds to the @Type@ rule from the official grammar+-}+_Type :: Parser ()+_Type = builtin "Type"++{-| Parse the @Kind@ built-in++    This corresponds to the @Kind@ rule from the official grammar+-}+_Kind :: Parser ()+_Kind = builtin "Kind"++{-| Parse the @Sort@ built-in++    This corresponds to the @Sort@ rule from the official grammar+-}+_Sort :: Parser ()+_Sort = builtin "Sort"++{-| Parse the @Location@ keyword++    This corresponds to the @Location@ rule from the official grammar+-}+_Location :: Parser ()+_Location = builtin "Location"++-- | Parse the @=@ symbol+_equal :: Parser ()+_equal = reservedChar '='++-- | Parse the @||@ symbol+_or :: Parser ()+_or = operator "||"++-- | Parse the @+@ symbol+_plus :: Parser ()+_plus = operatorChar '+'++-- | Parse the @++@ symbol+_textAppend :: Parser ()+_textAppend = operator "++"++-- | Parse the @#@ symbol+_listAppend :: Parser ()+_listAppend = operatorChar '#'++-- | Parse the @&&@ symbol+_and :: Parser ()+_and = operator "&&"++-- | Parse the @*@ symbol+_times :: Parser ()+_times = operatorChar '*'++-- | Parse the @==@ symbol+_doubleEqual :: Parser ()+_doubleEqual = operator "=="++-- | Parse the @!=@ symbol+_notEqual :: Parser ()+_notEqual = operator "!="++-- | Parse the @.@ symbol+_dot :: Parser ()+_dot = operatorChar '.'++-- | Parse the @{@ symbol+_openBrace :: Parser ()+_openBrace = reservedChar '{'++-- | Parse the @}@ symbol+_closeBrace :: Parser ()+_closeBrace = reservedChar '}'++-- | Parse the @[@] symbol+_openBracket :: Parser ()+_openBracket = reservedChar '['++-- | Parse the @]@ symbol+_closeBracket :: Parser ()+_closeBracket = reservedChar ']'++-- | Parse the @<@ symbol+_openAngle :: Parser ()+_openAngle = reservedChar '<'++-- | Parse the @>@ symbol+_closeAngle :: Parser ()+_closeAngle = reservedChar '>'++-- | Parse the @|@ symbol+_bar :: Parser ()+_bar = reservedChar '|'++-- | Parse the @,@ symbol+_comma :: Parser ()+_comma = reservedChar ',' <?> "\',\'"++-- | Parse the @(@ symbol+_openParens :: Parser ()+_openParens = reservedChar '('++-- | Parse the @)@ symbol+_closeParens :: Parser ()+_closeParens = reservedChar ')'++-- | Parse the @:@ symbol+_colon :: Parser ()+_colon = reservedChar ':'++-- | Parse the @\@@ symbol+_at :: Parser ()+_at = reservedChar '@' <?> "\"@\""++-- | Parse the equivalence symbol (@===@ or @≡@)+_equivalent :: Parser CharacterSet+_equivalent =+        (Unicode <$ char '≡' <?> "\"≡\"")+    <|> (ASCII <$ text "===" <?> "===")++-- | Parse the @missing@ keyword+_missing :: Parser ()+_missing =+        keyword "missing"+    *>  Text.Megaparsec.notFollowedBy (Text.Parser.Char.satisfy tailCharacter)++-- | Parse the @?@ symbol+_importAlt :: Parser ()+_importAlt = operatorChar '?'++-- | Parse the record combine operator (@/\\@ or @∧@)+_combine :: Parser CharacterSet+_combine =+        (Unicode <$ char '∧' <?> "\"∧\"")+    <|> (ASCII <$ text "/\\" <?> "/\\")++-- | Parse the record type combine operator (@//\\\\@ or @⩓@)+_combineTypes :: Parser CharacterSet+_combineTypes =+        (Unicode <$ char '⩓' <?> "\"⩓\"")+    <|> (ASCII <$ text "//\\\\" <?> "//\\\\")++-- | Parse the record \"prefer\" operator (@//@ or @⫽@)+_prefer :: Parser CharacterSet+_prefer =+        (Unicode <$ char '⫽' <?> "\"⫽\"")+    <|> (ASCII <$ text "//" <?> "//")++-- | Parse a lambda (@\\@ or @λ@)+_lambda :: Parser CharacterSet+_lambda =+        (Unicode <$ char 'λ' <?> "\"λ\"")+    <|> (ASCII <$ char '\\' <?> "\\")++-- | Parse a forall (@forall@ or @∀@)+_forall :: Parser CharacterSet+_forall =+        (Unicode <$ char '∀' <?> "\"∀\"")+    <|> (ASCII <$ text "forall" <?> "forall")++-- | Parse a right arrow (@->@ or @→@)+_arrow :: Parser CharacterSet+_arrow =+        (Unicode <$ char '→' <?> "\"→\"")+    <|> (ASCII <$ text "->" <?> "->")++-- | Parse a double colon (@::@)+_doubleColon :: Parser ()+_doubleColon = operator "::"
src/Dhall/Pretty.hs view
@@ -1,6 +1,25 @@ {-| This module contains logic for pretty-printing expressions, including     support for syntax highlighting -}-module Dhall.Pretty ( Ann(..), annToAnsiStyle, prettyExpr ) where+module Dhall.Pretty+    ( -- * Pretty+      Ann(..)+    , annToAnsiStyle+    , prettyExpr++    , CharacterSet(..)+    , defaultCharacterSet+    , detectCharacterSet+    , prettyCharacterSet++    , Dhall.Pretty.Internal.layout+    , Dhall.Pretty.Internal.layoutOpts++    , escapeEnvironmentVariable+    , UnescapedLabel(..)+    , escapeLabel++    , temporalToText+    ) where  import Dhall.Pretty.Internal
src/Dhall/Pretty/Internal.hs view
@@ -1,1152 +1,1991 @@-{-# LANGUAGE CPP               #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -Wall #-}--{-| This module provides internal pretty-printing utilities which are used by-    other modules but are not part of the public facing API--}--module Dhall.Pretty.Internal (-      Ann(..)-    , annToAnsiStyle-    , prettyExpr-    , buildConst-    , buildVar-    , buildExpr-    , buildNatural-    , buildNumber-    , buildScientific-    , pretty-    , escapeText-    ) where--import {-# SOURCE #-} Dhall.Core--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative (Applicative(..), (<$>))-#endif-import Data.Foldable-import Data.HashMap.Strict.InsOrd (InsOrdHashMap)-import Data.Monoid ((<>))-import Data.Scientific (Scientific)-import Data.Text.Buildable (Buildable(..))-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-import Data.Text.Prettyprint.Doc (Doc, Pretty, space)-import Numeric.Natural (Natural)-import Prelude hiding (succ)-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Terminal--import qualified Data.Char-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.HashSet-import qualified Data.List-import qualified Data.Text.Lazy                        as Text-import qualified Data.Text.Lazy.Builder                as Builder-import qualified Data.Text.Prettyprint.Doc             as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty--{-| Annotation type used to tag elements in a pretty-printed document for-    syntax highlighting purposes--}-data Ann-  = Keyword     -- ^ Used for syntactic keywords-  | Syntax      -- ^ Syntax punctuation such as commas, parenthesis, and braces-  | Label       -- ^ Record labels-  | Literal     -- ^ Literals such as integers and strings-  | Builtin     -- ^ Builtin types and values-  | Operator    -- ^ Operators--{-| Convert annotations to their corresponding color for syntax highlighting-    purposes--}-annToAnsiStyle :: Ann -> Terminal.AnsiStyle-annToAnsiStyle Keyword  = Terminal.bold <> Terminal.colorDull Terminal.Green-annToAnsiStyle Syntax   = Terminal.bold <> Terminal.colorDull Terminal.Green-annToAnsiStyle Label    = mempty-annToAnsiStyle Literal  = Terminal.colorDull Terminal.Magenta-annToAnsiStyle Builtin  = Terminal.underlined-annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green---- | Pretty print an expression-prettyExpr :: Pretty a => Expr s a -> Doc Ann-prettyExpr = prettyExprA--{-| Internal utility for pretty-printing, used when generating element lists-    to supply to `enclose` or `enclose'`.  This utility indicates that the-    compact represent is the same as the multi-line representation for each-    element--}-duplicate :: a -> (a, a)-duplicate x = (x, x)---- Annotation helpers-keyword, syntax, label, literal, builtin, operator :: Doc Ann -> Doc Ann-keyword  = Pretty.annotate Keyword-syntax   = Pretty.annotate Syntax-label    = Pretty.annotate Label-literal  = Pretty.annotate Literal-builtin  = Pretty.annotate Builtin-operator = Pretty.annotate Operator--comma, lbracket, rbracket, langle, rangle, lbrace, rbrace, lparen, rparen, pipe, rarrow, backtick, dollar, colon, lambda, forall, equals, dot :: Doc Ann-comma    = syntax Pretty.comma-lbracket = syntax Pretty.lbracket-rbracket = syntax Pretty.rbracket-langle   = syntax Pretty.langle-rangle   = syntax Pretty.rangle-lbrace   = syntax Pretty.lbrace-rbrace   = syntax Pretty.rbrace-lparen   = syntax Pretty.lparen-rparen   = syntax Pretty.rparen-pipe     = syntax Pretty.pipe-rarrow   = syntax "→"-backtick = syntax "`"-dollar   = syntax "$"-colon    = syntax ":"-lambda   = syntax "λ"-forall   = syntax "∀"-equals   = syntax "="-dot      = syntax "."---- | Pretty-print a list-list :: [Doc Ann] -> Doc Ann-list   [] = lbracket <> rbracket-list docs =-    enclose-        (lbracket <> space)-        (lbracket <> space)-        (comma <> space)-        (comma <> space)-        (space <> rbracket)-        rbracket-        (fmap duplicate docs)---- | Pretty-print union types and literals-angles :: [(Doc Ann, Doc Ann)] -> Doc Ann-angles   [] = langle <> rangle-angles docs =-    enclose-        (langle <> space)-        (langle <> space)-        (space <> pipe <> space)-        (pipe <> space)-        (space <> rangle)-        rangle-        docs---- | Pretty-print record types and literals-braces :: [(Doc Ann, Doc Ann)] -> Doc Ann-braces   [] = lbrace <> rbrace-braces docs =-    enclose-        (lbrace <> space)-        (lbrace <> space)-        (comma <> space)-        (comma <> space)-        (space <> rbrace)-        rbrace-        docs---- | Pretty-print anonymous functions and function types-arrows :: [(Doc Ann, Doc Ann)] -> Doc Ann-arrows =-    enclose'-        ""-        "  "-        (" " <> rarrow <> " ")-        (rarrow <> space)--{-| Format an expression that holds a variable number of elements, such as a-    list, record, or union--}-enclose-    :: Doc ann-    -- ^ Beginning document for compact representation-    -> Doc ann-    -- ^ Beginning document for multi-line representation-    -> Doc ann-    -- ^ Separator for compact representation-    -> Doc ann-    -- ^ Separator for multi-line representation-    -> Doc ann-    -- ^ Ending document for compact representation-    -> Doc ann-    -- ^ Ending document for multi-line representation-    -> [(Doc ann, Doc ann)]-    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@-    -> Doc ann-enclose beginShort _         _        _       endShort _       []   =-    beginShort <> endShort-  where-enclose beginShort beginLong sepShort sepLong endShort endLong docs =-    Pretty.group-        (Pretty.flatAlt-            (Pretty.align-                (mconcat (zipWith combineLong (beginLong : repeat sepLong) docsLong) <> endLong)-            )-            (mconcat (zipWith combineShort (beginShort : repeat sepShort) docsShort) <> endShort)-        )-  where-    docsShort = fmap fst docs--    docsLong = fmap snd docs--    combineLong x y = x <> y <> Pretty.hardline--    combineShort x y = x <> y--{-| Format an expression that holds a variable number of elements without a-    trailing document such as nested `let`, nested lambdas, or nested `forall`s--}-enclose'-    :: Doc ann-    -- ^ Beginning document for compact representation-    -> Doc ann-    -- ^ Beginning document for multi-line representation-    -> Doc ann-    -- ^ Separator for compact representation-    -> Doc ann-    -- ^ Separator for multi-line representation-    -> [(Doc ann, Doc ann)]-    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@-    -> Doc ann-enclose' beginShort beginLong sepShort sepLong docs =-    Pretty.group (Pretty.flatAlt long short)-  where-    longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong--    long =-        Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))--    short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort)--    docsShort = fmap fst docs--    docsLong = fmap snd docs--alpha :: Char -> Bool-alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')--digit :: Char -> Bool-digit c = '\x30' <= c && c <= '\x39'--headCharacter :: Char -> Bool-headCharacter c = alpha c || c == '_'--tailCharacter :: Char -> Bool-tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/'--prettyLabel :: Text -> Doc Ann-prettyLabel a = label doc-    where-        doc =-            case Text.uncons a of-                Just (h, t)-                    | headCharacter h && Text.all tailCharacter t && not (Data.HashSet.member a reservedIdentifiers)-                        -> Pretty.pretty a-                _       -> backtick <> Pretty.pretty a <> backtick--prettyNumber :: Integer -> Doc Ann-prettyNumber = literal . Pretty.pretty--prettyNatural :: Natural -> Doc Ann-prettyNatural = literal . Pretty.pretty--prettyScientific :: Scientific -> Doc Ann-prettyScientific = literal . Pretty.pretty . show--prettyChunks :: Pretty a => Chunks s a -> Doc Ann-prettyChunks (Chunks a b) =-    if any (\(builder, _) -> hasNewLine builder) a || hasNewLine b-    then Pretty.flatAlt long short-    else short-  where-    long =-        Pretty.align-        (   literal ("''" <> Pretty.hardline)-        <>  Pretty.align-            (foldMap prettyMultilineChunk a <> prettyMultilineBuilder b)-        <>  literal "''"-        )--    short =-        literal "\"" <> foldMap prettyChunk a <> literal (prettyText b <> "\"")--    hasNewLine builder = Text.any (== '\n') lazyText-      where-        lazyText = Builder.toLazyText builder--    prettyMultilineChunk (c, d) =-      prettyMultilineBuilder c <> dollar <> lbrace <> prettyExprA d <> rbrace--    prettyMultilineBuilder builder = literal (mconcat docs)-      where-        lazyText = Builder.toLazyText (escapeSingleQuotedText builder)--        lazyLines = Text.splitOn "\n" lazyText--        docs =-            Data.List.intersperse Pretty.hardline (fmap Pretty.pretty lazyLines)--    prettyChunk (c, d) = prettyText c <> syntax "${" <> prettyExprA d <> syntax rbrace--    prettyText t = literal (Pretty.pretty (Builder.toLazyText (escapeText t)))--prettyConst :: Const -> Doc Ann-prettyConst Type = builtin "Type"-prettyConst Kind = builtin "Kind"--prettyVar :: Var -> Doc Ann-prettyVar (V x 0) = label (Pretty.unAnnotate (prettyLabel x))-prettyVar (V x n) = label (Pretty.unAnnotate (prettyLabel x <> "@" <> prettyNumber n))--prettyExprA :: Pretty a => Expr s a -> Doc Ann-prettyExprA a0@(Annot _ _) =-    enclose'-        ""-        "  "-        (" " <> colon <> " ")-        (colon <> space)-        (fmap duplicate (docs a0))-  where-    docs (Annot a b) = prettyExprB a : docs b-    docs (Note  _ b) = docs b-    docs          b  = [ prettyExprB b ]-prettyExprA (Note _ a) =-    prettyExprA a-prettyExprA a0 =-    prettyExprB a0--prettyExprB :: Pretty a => Expr s a -> Doc Ann-prettyExprB a0@(Lam _ _ _) = arrows (fmap duplicate (docs a0))-  where-    docs (Lam a b c) = Pretty.group (Pretty.flatAlt long short) : docs c-      where-        long =  (lambda <> space)-            <>  Pretty.align-                (   (lparen <> space)-                <>  prettyLabel a-                <>  Pretty.hardline-                <>  (colon <> space)-                <>  prettyExprA b-                <>  Pretty.hardline-                <>  rparen-                )--        short = (lambda <> lparen)-            <>  prettyLabel a-            <>  (space <> colon <> space)-            <>  prettyExprA b-            <>  rparen-    docs (Note  _ c) = docs c-    docs          c  = [ prettyExprB c ]-prettyExprB a0@(BoolIf _ _ _) =-    enclose' "" "      " (space <> keyword "else" <> space) (Pretty.hardline <> keyword "else" <> "  ") (fmap duplicate (docs a0))-  where-    docs (BoolIf a b c) =-        Pretty.group (Pretty.flatAlt long short) : docs c-      where-        long =-             Pretty.align-                (   (keyword "if" <> "    ")-                <>  prettyExprA a-                <>  Pretty.hardline-                <>  (keyword "then" <> "  ")-                <>  prettyExprA b-                )--        short = (keyword "if" <> " ")-            <>  prettyExprA a-            <>  (space <> keyword "then" <> space)-            <>  prettyExprA b-    docs (Note  _    c) = docs c-    docs             c  = [ prettyExprB c ]-prettyExprB a0@(Pi _ _ _) =-    arrows (fmap duplicate (docs a0))-  where-    docs (Pi "_" b c) = prettyExprC b : docs c-    docs (Pi a   b c) = Pretty.group (Pretty.flatAlt long short) : docs c-      where-        long =  forall <> space-            <>  Pretty.align-                (   lparen <> space-                <>  prettyLabel a-                <>  Pretty.hardline-                <>  colon <> space-                <>  prettyExprA b-                <>  Pretty.hardline-                <>  rparen-                )--        short = forall <> lparen-            <>  prettyLabel a-            <>  space <> colon <> space-            <>  prettyExprA b-            <>  rparen-    docs (Note _   c) = docs c-    docs           c  = [ prettyExprB c ]-prettyExprB a0@(Let _ _ _ _) =-    enclose' "" "    " (space <> keyword "in" <> space) (Pretty.hardline <> keyword "in" <> "  ")-        (fmap duplicate (docs a0))-  where-    docs (Let a Nothing c d) =-        Pretty.group (Pretty.flatAlt long short) : docs d-      where-        long =  keyword "let" <> space-            <>  Pretty.align-                (   prettyLabel a-                <>  space <> equals-                <>  Pretty.hardline-                <>  "  "-                <>  prettyExprA c-                )--        short = keyword "let" <> space-            <>  prettyLabel a-            <>  (space <> equals <> space)-            <>  prettyExprA c-    docs (Let a (Just b) c d) =-        Pretty.group (Pretty.flatAlt long short) : docs d-      where-        long = keyword "let" <> space-            <>  Pretty.align-                (   prettyLabel a-                <>  Pretty.hardline-                <>  colon <> space-                <>  prettyExprA b-                <>  Pretty.hardline-                <>  equals <> space-                <>  prettyExprA c-                )--        short = keyword "let" <> space-            <>  prettyLabel a-            <>  space <> colon <> space-            <>  prettyExprA b-            <>  space <> equals <> space-            <>  prettyExprA c-    docs (Note _ d)  =-        docs d-    docs d =-        [ prettyExprB d ]-prettyExprB (ListLit Nothing b) =-    list (map prettyExprA (Data.Foldable.toList b))-prettyExprB (ListLit (Just a) b) =-        list (map prettyExprA (Data.Foldable.toList b))-    <>  " : "-    <>  prettyExprD (App List a)-prettyExprB (OptionalLit a b) =-        list (map prettyExprA (Data.Foldable.toList b))-    <>  " : "-    <>  prettyExprD (App Optional a)-prettyExprB (Merge a b (Just c)) =-    Pretty.group (Pretty.flatAlt long short)-  where-    long =-        Pretty.align-            (   keyword "merge"-            <>  Pretty.hardline-            <>  prettyExprE a-            <>  Pretty.hardline-            <>  prettyExprE b-            <>  Pretty.hardline-            <>  colon <> space-            <>  prettyExprD c-            )--    short = keyword "merge" <> space-        <>  prettyExprE a-        <>  " "-        <>  prettyExprE b-        <>  space <> colon <> space-        <>  prettyExprD c-prettyExprB (Merge a b Nothing) =-    Pretty.group (Pretty.flatAlt long short)-  where-    long =-        Pretty.align-            (   keyword "merge"-            <>  Pretty.hardline-            <>  prettyExprE a-            <>  Pretty.hardline-            <>  prettyExprE b-            )--    short = keyword "merge" <> space-        <>  prettyExprE a-        <>  " "-        <>  prettyExprE b-prettyExprB (Note _ b) =-    prettyExprB b-prettyExprB a =-    prettyExprC a--prettyExprC :: Pretty a => Expr s a -> Doc Ann-prettyExprC = prettyExprC0--prettyExprC0 :: Pretty a => Expr s a -> Doc Ann-prettyExprC0 a0@(BoolOr _ _) =-    enclose' "" "    " (space <> operator "||" <> space) (operator "||" <> "  ") (fmap duplicate (docs a0))-  where-    docs (BoolOr a b) = prettyExprC1 a : docs b-    docs (Note   _ b) = docs b-    docs           b  = [ prettyExprC1 b ]-prettyExprC0 (Note _ a) =-    prettyExprC0 a-prettyExprC0 a0 =-    prettyExprC1 a0--prettyExprC1 :: Pretty a => Expr s a -> Doc Ann-prettyExprC1 a0@(TextAppend _ _) =-    enclose' "" "    " (" " <> operator "++" <> " ") (operator "++" <> "  ") (fmap duplicate (docs a0))-  where-    docs (TextAppend a b) = prettyExprC2 a : docs b-    docs (Note       _ b) = docs b-    docs               b  = [ prettyExprC2 b ]-prettyExprC1 (Note _ a) =-    prettyExprC1 a-prettyExprC1 a0 =-    prettyExprC2 a0--prettyExprC2 :: Pretty a => Expr s a -> Doc Ann-prettyExprC2 a0@(NaturalPlus _ _) =-    enclose' "" "  " (" " <> operator "+" <> " ") (operator "+" <> " ") (fmap duplicate (docs a0))-  where-    docs (NaturalPlus a b) = prettyExprC3 a : docs b-    docs (Note        _ b) = docs b-    docs                b  = [ prettyExprC3 b ]-prettyExprC2 (Note _ a) =-    prettyExprC2 a-prettyExprC2 a0 =-    prettyExprC3 a0--prettyExprC3 :: Pretty a => Expr s a -> Doc Ann-prettyExprC3 a0@(ListAppend _ _) =-    enclose' "" "  " (" " <> operator "#" <> " ") (operator "#" <> " ") (fmap duplicate (docs a0))-  where-    docs (ListAppend a b) = prettyExprC4 a : docs b-    docs (Note       _ b) = docs b-    docs               b  = [ prettyExprC4 b ]-prettyExprC3 (Note _ a) =-    prettyExprC3 a-prettyExprC3 a0 =-    prettyExprC4 a0--prettyExprC4 :: Pretty a => Expr s a -> Doc Ann-prettyExprC4 a0@(BoolAnd _ _) =-    enclose' "" "    " (" " <> operator "&&" <> " ") (operator "&&" <> "  ") (fmap duplicate (docs a0))-  where-    docs (BoolAnd a b) = prettyExprC5 a : docs b-    docs (Note    _ b) = docs b-    docs            b  = [ prettyExprC5 b ]-prettyExprC4 (Note _ a) =-    prettyExprC4 a-prettyExprC4 a0 =-   prettyExprC5 a0--prettyExprC5 :: Pretty a => Expr s a -> Doc Ann-prettyExprC5 a0@(Combine _ _) =-    enclose' "" "  " (" " <> operator "∧" <> " ") (operator "∧" <> " ") (fmap duplicate (docs a0))-  where-    docs (Combine a b) = prettyExprC6 a : docs b-    docs (Note    _ b) = docs b-    docs            b  = [ prettyExprC6 b ]-prettyExprC5 (Note _ a) =-    prettyExprC5 a-prettyExprC5 a0 =-    prettyExprC6 a0--prettyExprC6 :: Pretty a => Expr s a -> Doc Ann-prettyExprC6 a0@(Prefer _ _) =-    enclose' "" "  " (" " <> operator "⫽" <> " ") (operator "⫽" <> " ") (fmap duplicate (docs a0))-  where-    docs (Prefer a b) = prettyExprC7 a : docs b-    docs (Note   _ b) = docs b-    docs           b  = [ prettyExprC7 b ]-prettyExprC6 (Note _ a) =-    prettyExprC6 a-prettyExprC6 a0 =-    prettyExprC7 a0--prettyExprC7 :: Pretty a => Expr s a -> Doc Ann-prettyExprC7 a0@(NaturalTimes _ _) =-    enclose' "" "  " (" " <> operator "*" <> " ") (operator "*" <> " ") (fmap duplicate (docs a0))-  where-    docs (NaturalTimes a b) = prettyExprC8 a : docs b-    docs (Note         _ b) = docs b-    docs                 b  = [ prettyExprC8 b ]-prettyExprC7 (Note _ a) =-    prettyExprC7 a-prettyExprC7 a0 =-    prettyExprC8 a0--prettyExprC8 :: Pretty a => Expr s a -> Doc Ann-prettyExprC8 a0@(BoolEQ _ _) =-    enclose' "" "    " (" " <> operator "==" <> " ") (operator "==" <> "  ") (fmap duplicate (docs a0))-  where-    docs (BoolEQ a b) = prettyExprC9 a : docs b-    docs (Note   _ b) = docs b-    docs           b  = [ prettyExprC9 b ]-prettyExprC8 (Note _ a) =-    prettyExprC8 a-prettyExprC8 a0 =-    prettyExprC9 a0--prettyExprC9 :: Pretty a => Expr s a -> Doc Ann-prettyExprC9 a0@(BoolNE _ _) =-    enclose' "" "    " (" " <> operator "!=" <> " ") (operator "!=" <> "  ") (fmap duplicate (docs a0))-  where-    docs (BoolNE a b) = prettyExprD a : docs b-    docs (Note   _ b) = docs b-    docs           b  = [ prettyExprD b ]-prettyExprC9 (Note _ a) =-    prettyExprC9 a-prettyExprC9 a0 =-    prettyExprD a0--prettyExprD :: Pretty a => Expr s a -> Doc Ann-prettyExprD a0 = case a0 of-    App _ _        -> result-    Constructors _ -> result-    Note _ b       -> prettyExprD b-    _              -> prettyExprE a0-  where-    result = enclose' "" "" " " "" (fmap duplicate (reverse (docs a0)))--    docs (App        a b) = prettyExprE b : docs a-    docs (Constructors b) = [ prettyExprE b , keyword "constructors" ]-    docs (Note       _ b) = docs b-    docs               b  = [ prettyExprE b ]--prettyExprE :: Pretty a => Expr s a -> Doc Ann-prettyExprE (Field a b) = prettyExprE a <> dot <> prettyLabel b-prettyExprE (Note  _ b) = prettyExprE b-prettyExprE  a          = prettyExprF a--prettyExprF :: Pretty a => Expr s a -> Doc Ann-prettyExprF (Var a) =-    prettyVar a-prettyExprF (Const k) =-    prettyConst k-prettyExprF Bool =-    builtin "Bool"-prettyExprF Natural =-    builtin "Natural"-prettyExprF NaturalFold =-    builtin "Natural/fold"-prettyExprF NaturalBuild =-    builtin "Natural/build"-prettyExprF NaturalIsZero =-    builtin "Natural/isZero"-prettyExprF NaturalEven =-    builtin "Natural/even"-prettyExprF NaturalOdd =-    builtin "Natural/odd"-prettyExprF NaturalToInteger =-    builtin "Natural/toInteger"-prettyExprF NaturalShow =-    builtin "Natural/show"-prettyExprF Integer =-    builtin "Integer"-prettyExprF IntegerShow =-    builtin "Integer/show"-prettyExprF Double =-    builtin "Double"-prettyExprF DoubleShow =-    builtin "Double/show"-prettyExprF Text =-    builtin "Text"-prettyExprF List =-    builtin "List"-prettyExprF ListBuild =-    builtin "List/build"-prettyExprF ListFold =-    builtin "List/fold"-prettyExprF ListLength =-    builtin "List/length"-prettyExprF ListHead =-    builtin "List/head"-prettyExprF ListLast =-    builtin "List/last"-prettyExprF ListIndexed =-    builtin "List/indexed"-prettyExprF ListReverse =-    builtin "List/reverse"-prettyExprF Optional =-    builtin "Optional"-prettyExprF OptionalFold =-    builtin "Optional/fold"-prettyExprF OptionalBuild =-    builtin "Optional/build"-prettyExprF (BoolLit True) =-    builtin "True"-prettyExprF (BoolLit False) =-    builtin "False"-prettyExprF (IntegerLit a) =-    prettyNumber a-prettyExprF (NaturalLit a) =-    literal "+" <> prettyNatural a-prettyExprF (DoubleLit a) =-    prettyScientific a-prettyExprF (TextLit a) =-    prettyChunks a-prettyExprF (Record a) =-    prettyRecord a-prettyExprF (RecordLit a) =-    prettyRecordLit a-prettyExprF (Union a) =-    prettyUnion a-prettyExprF (UnionLit a b c) =-    prettyUnionLit a b c-prettyExprF (ListLit Nothing b) =-    list (map prettyExprA (Data.Foldable.toList b))-prettyExprF (Embed a) =-    Pretty.pretty a-prettyExprF (Note _ b) =-    prettyExprF b-prettyExprF a =-    Pretty.group (Pretty.flatAlt long short)-  where-    long = Pretty.align (lparen <> space <> prettyExprA a <> Pretty.hardline <> rparen)--    short = lparen <> prettyExprA a <> rparen--prettyKeyValue :: Pretty a => Doc Ann -> (Text, Expr s a) -> (Doc Ann, Doc Ann)-prettyKeyValue separator (key, value) =-    (   prettyLabel key <> " " <> separator <> " " <> prettyExprA value-    ,       prettyLabel key-        <>  " "-        <>  separator-        <>  long-    )-  where-    long = Pretty.hardline <> "    " <> prettyExprA value--prettyRecord :: Pretty a => InsOrdHashMap Text (Expr s a) -> Doc Ann-prettyRecord =-    braces . map (prettyKeyValue colon) . Data.HashMap.Strict.InsOrd.toList--prettyRecordLit :: Pretty a => InsOrdHashMap Text (Expr s a) -> Doc Ann-prettyRecordLit a-    | Data.HashMap.Strict.InsOrd.null a =-        lbrace <> equals <> rbrace-    | otherwise-        = braces (map (prettyKeyValue equals) (Data.HashMap.Strict.InsOrd.toList a))--prettyUnion :: Pretty a => InsOrdHashMap Text (Expr s a) -> Doc Ann-prettyUnion =-    angles . map (prettyKeyValue colon) . Data.HashMap.Strict.InsOrd.toList--prettyUnionLit-    :: Pretty a => Text -> Expr s a -> InsOrdHashMap Text (Expr s a) -> Doc Ann-prettyUnionLit a b c =-    angles (front : map adapt (Data.HashMap.Strict.InsOrd.toList c))-  where-    front = prettyKeyValue equals (a, b)--    adapt = prettyKeyValue colon---- | Pretty-print a value-pretty :: Pretty a => a -> Text-pretty = Pretty.renderLazy . Pretty.layoutPretty options . Pretty.pretty-  where-   options = Pretty.LayoutOptions { Pretty.layoutPageWidth = Pretty.Unbounded }---- | Builder corresponding to the @label@ token in "Dhall.Parser"-buildLabel :: Text -> Builder-buildLabel l = case Text.uncons l of-    Just (h, t)-        | headCharacter h && Text.all tailCharacter t && not (Data.HashSet.member l reservedIdentifiers)-            -> build l-    _       -> "`" <> build l <> "`"----- | Builder corresponding to the @number@ token in "Dhall.Parser"-buildNumber :: Integer -> Builder-buildNumber a = build (show a)---- | Builder corresponding to the @natural@ token in "Dhall.Parser"-buildNatural :: Natural -> Builder-buildNatural a = build (show a)---- | Builder corresponding to the @double@ token in "Dhall.Parser"-buildScientific :: Scientific -> Builder-buildScientific = build . show---- | Builder corresponding to the @text@ token in "Dhall.Parser"-buildChunks :: Buildable a => Chunks s a -> Builder-buildChunks (Chunks a b) = "\"" <> foldMap buildChunk a <> escapeText b <> "\""-  where-    buildChunk (c, d) = escapeText c <> "${" <> buildExprA d <> "}"---- | Escape a `Builder` literal using Dhall's escaping rules for single-quoted---   @Text@-escapeSingleQuotedText :: Builder -> Builder-escapeSingleQuotedText inputBuilder = outputBuilder-  where-    inputText = Builder.toLazyText inputBuilder--    outputText = substitute "${" "''${" (substitute "''" "'''" inputText)--    outputBuilder = Builder.fromLazyText outputText--    substitute before after = Text.intercalate after . Text.splitOn before--{-| Escape a `Builder` literal using Dhall's escaping rules-  -    Note that the result does not include surrounding quotes--}-escapeText :: Builder -> Builder-escapeText a = Builder.fromLazyText (Text.concatMap adapt text)-  where-    adapt c-        | '\x20' <= c && c <= '\x21' = Text.singleton c-        -- '\x22' == '"'-        | '\x23' == c                = Text.singleton c-        -- '\x24' == '$'-        | '\x25' <= c && c <= '\x5B' = Text.singleton c-        -- '\x5C' == '\\'-        | '\x5D' <= c && c <= '\x7F' = Text.singleton c-        | c == '"'                   = "\\\""-        | c == '$'                   = "\\$"-        | c == '\\'                  = "\\\\"-        | c == '\b'                  = "\\b"-        | c == '\f'                  = "\\f"-        | c == '\n'                  = "\\n"-        | c == '\r'                  = "\\r"-        | c == '\t'                  = "\\t"-        | otherwise                  = "\\u" <> showDigits (Data.Char.ord c)--    showDigits r0 = Text.pack (map showDigit [q1, q2, q3, r3])-      where-        (q1, r1) = r0 `quotRem` 4096-        (q2, r2) = r1 `quotRem`  256-        (q3, r3) = r2 `quotRem`   16--    showDigit n-        | n < 10    = Data.Char.chr (Data.Char.ord '0' + n)-        | otherwise = Data.Char.chr (Data.Char.ord 'A' + n - 10)--    text = Builder.toLazyText a---- | Builder corresponding to the @expr@ parser in "Dhall.Parser"-buildExpr :: Buildable a => Expr s a -> Builder-buildExpr = buildExprA---- | Builder corresponding to the @exprA@ parser in "Dhall.Parser"-buildExprA :: Buildable a => Expr s a -> Builder-buildExprA (Annot a b) = buildExprB a <> " : " <> buildExprA b-buildExprA (Note  _ b) = buildExprA b-buildExprA a           = buildExprB a---- | Builder corresponding to the @exprB@ parser in "Dhall.Parser"-buildExprB :: Buildable a => Expr s a -> Builder-buildExprB (Lam a b c) =-        "λ("-    <>  buildLabel a-    <>  " : "-    <>  buildExprA b-    <>  ") → "-    <>  buildExprB c-buildExprB (BoolIf a b c) =-        "if "-    <>  buildExprA a-    <>  " then "-    <>  buildExprA b-    <>  " else "-    <>  buildExprA c-buildExprB (Pi "_" b c) =-        buildExprC b-    <>  " → "-    <>  buildExprB c-buildExprB (Pi a b c) =-        "∀("-    <>  buildLabel a-    <>  " : "-    <>  buildExprA b-    <>  ") → "-    <>  buildExprB c-buildExprB (Let a Nothing c d) =-        "let "-    <>  buildLabel a-    <>  " = "-    <>  buildExprA c-    <>  " in "-    <>  buildExprB d-buildExprB (Let a (Just b) c d) =-        "let "-    <>  buildLabel a-    <>  " : "-    <>  buildExprA b-    <>  " = "-    <>  buildExprA c-    <>  " in "-    <>  buildExprB d-buildExprB (ListLit Nothing b) =-    "[" <> buildElems (Data.Foldable.toList b) <> "]"-buildExprB (ListLit (Just a) b) =-    "[" <> buildElems (Data.Foldable.toList b) <> "] : List "  <> buildExprE a-buildExprB (OptionalLit a b) =-    "[" <> buildElems (Data.Foldable.toList b) <> "] : Optional "  <> buildExprE a-buildExprB (Merge a b (Just c)) =-    "merge " <> buildExprE a <> " " <> buildExprE b <> " : " <> buildExprD c-buildExprB (Merge a b Nothing) =-    "merge " <> buildExprE a <> " " <> buildExprE b-buildExprB (Note _ b) =-    buildExprB b-buildExprB a =-    buildExprC a---- | Builder corresponding to the @exprC@ parser in "Dhall.Parser"-buildExprC :: Buildable a => Expr s a -> Builder-buildExprC = buildExprC0---- | Builder corresponding to the @exprC0@ parser in "Dhall.Parser"-buildExprC0 :: Buildable a => Expr s a -> Builder-buildExprC0 (BoolOr a b) = buildExprC1 a <> " || " <> buildExprC0 b-buildExprC0 (Note   _ b) = buildExprC0 b-buildExprC0  a           = buildExprC1 a---- | Builder corresponding to the @exprC1@ parser in "Dhall.Parser"-buildExprC1 :: Buildable a => Expr s a -> Builder-buildExprC1 (TextAppend a b) = buildExprC2 a <> " ++ " <> buildExprC1 b-buildExprC1 (Note       _ b) = buildExprC1 b-buildExprC1  a               = buildExprC2 a---- | Builder corresponding to the @exprC2@ parser in "Dhall.Parser"-buildExprC2 :: Buildable a => Expr s a -> Builder-buildExprC2 (NaturalPlus a b) = buildExprC3 a <> " + " <> buildExprC2 b-buildExprC2 (Note        _ b) = buildExprC2 b-buildExprC2  a                = buildExprC3 a---- | Builder corresponding to the @exprC3@ parser in "Dhall.Parser"-buildExprC3 :: Buildable a => Expr s a -> Builder-buildExprC3 (ListAppend a b) = buildExprC4 a <> " # " <> buildExprC3 b-buildExprC3 (Note       _ b) = buildExprC3 b-buildExprC3  a               = buildExprC4 a---- | Builder corresponding to the @exprC4@ parser in "Dhall.Parser"-buildExprC4 :: Buildable a => Expr s a -> Builder-buildExprC4 (BoolAnd a b) = buildExprC5 a <> " && " <> buildExprC4 b-buildExprC4 (Note    _ b) = buildExprC4 b-buildExprC4  a            = buildExprC5 a---- | Builder corresponding to the @exprC5@ parser in "Dhall.Parser"-buildExprC5 :: Buildable a => Expr s a -> Builder-buildExprC5 (Combine   a b) = buildExprC6 a <> " ∧ " <> buildExprC5 b-buildExprC5 (Note      _ b) = buildExprC5 b-buildExprC5  a              = buildExprC6 a---- | Builder corresponding to the @exprC6@ parser in "Dhall.Parser"-buildExprC6 :: Buildable a => Expr s a -> Builder-buildExprC6 (Prefer a b) = buildExprC7 a <> " ⫽ " <> buildExprC6 b-buildExprC6 (Note   _ b) = buildExprC6 b-buildExprC6  a           = buildExprC7 a---- | Builder corresponding to the @exprC7@ parser in "Dhall.Parser"-buildExprC7 :: Buildable a => Expr s a -> Builder-buildExprC7 (NaturalTimes a b) = buildExprC8 a <> " * " <> buildExprC7 b-buildExprC7 (Note         _ b) = buildExprC7 b-buildExprC7  a                 = buildExprC8 a---- | Builder corresponding to the @exprC8@ parser in "Dhall.Parser"-buildExprC8 :: Buildable a => Expr s a -> Builder-buildExprC8 (BoolEQ a b) = buildExprC9 a <> " == " <> buildExprC8 b-buildExprC8 (Note   _ b) = buildExprC8 b-buildExprC8  a           = buildExprC9 a---- | Builder corresponding to the @exprC9@ parser in "Dhall.Parser"-buildExprC9 :: Buildable a => Expr s a -> Builder-buildExprC9 (BoolNE a b) = buildExprD  a <> " != " <> buildExprC9 b-buildExprC9 (Note   _ b) = buildExprC9 b-buildExprC9  a           = buildExprD  a---- | Builder corresponding to the @exprD@ parser in "Dhall.Parser"-buildExprD :: Buildable a => Expr s a -> Builder-buildExprD (App        a b) = buildExprD a <> " " <> buildExprE b-buildExprD (Constructors b) = "constructors " <> buildExprE b-buildExprD (Note       _ b) = buildExprD b-buildExprD  a               = buildExprE a---- | Builder corresponding to the @exprE@ parser in "Dhall.Parser"-buildExprE :: Buildable a => Expr s a -> Builder-buildExprE (Field a b) = buildExprE a <> "." <> buildLabel b-buildExprE (Note  _ b) = buildExprE b-buildExprE  a          = buildExprF a---- | Builder corresponding to the @exprF@ parser in "Dhall.Parser"-buildExprF :: Buildable a => Expr s a -> Builder-buildExprF (Var a) =-    buildVar a-buildExprF (Const k) =-    buildConst k-buildExprF Bool =-    "Bool"-buildExprF Natural =-    "Natural"-buildExprF NaturalFold =-    "Natural/fold"-buildExprF NaturalBuild =-    "Natural/build"-buildExprF NaturalIsZero =-    "Natural/isZero"-buildExprF NaturalEven =-    "Natural/even"-buildExprF NaturalOdd =-    "Natural/odd"-buildExprF NaturalToInteger =-    "Natural/toInteger"-buildExprF NaturalShow =-    "Natural/show"-buildExprF Integer =-    "Integer"-buildExprF IntegerShow =-    "Integer/show"-buildExprF Double =-    "Double"-buildExprF DoubleShow =-    "Double/show"-buildExprF Text =-    "Text"-buildExprF List =-    "List"-buildExprF ListBuild =-    "List/build"-buildExprF ListFold =-    "List/fold"-buildExprF ListLength =-    "List/length"-buildExprF ListHead =-    "List/head"-buildExprF ListLast =-    "List/last"-buildExprF ListIndexed =-    "List/indexed"-buildExprF ListReverse =-    "List/reverse"-buildExprF Optional =-    "Optional"-buildExprF OptionalFold =-    "Optional/fold"-buildExprF OptionalBuild =-    "Optional/build"-buildExprF (BoolLit True) =-    "True"-buildExprF (BoolLit False) =-    "False"-buildExprF (IntegerLit a) =-    buildNumber a-buildExprF (NaturalLit a) =-    "+" <> buildNatural a-buildExprF (DoubleLit a) =-    buildScientific a-buildExprF (TextLit a) =-    buildChunks a-buildExprF (Record a) =-    buildRecord a-buildExprF (RecordLit a) =-    buildRecordLit a-buildExprF (Union a) =-    buildUnion a-buildExprF (UnionLit a b c) =-    buildUnionLit a b c-buildExprF (ListLit Nothing b) =-    "[" <> buildElems (Data.Foldable.toList b) <> "]"-buildExprF (Embed a) =-    build a-buildExprF (Note _ b) =-    buildExprF b-buildExprF a =-    "(" <> buildExprA a <> ")"---- | Builder corresponding to the @const@ parser in "Dhall.Parser"-buildConst :: Const -> Builder-buildConst Type = "Type"-buildConst Kind = "Kind"---- | Builder corresponding to the @var@ parser in "Dhall.Parser"-buildVar :: Var -> Builder-buildVar (V x 0) = buildLabel x-buildVar (V x n) = buildLabel x <> "@" <> buildNumber n---- | Builder corresponding to the @elems@ parser in "Dhall.Parser"-buildElems :: Buildable a => [Expr s a] -> Builder-buildElems   []   = ""-buildElems   [a]  = buildExprA a-buildElems (a:bs) = buildExprA a <> ", " <> buildElems bs---- | Builder corresponding to the @recordLit@ parser in "Dhall.Parser"-buildRecordLit :: Buildable a => InsOrdHashMap Text (Expr s a) -> Builder-buildRecordLit a | Data.HashMap.Strict.InsOrd.null a =-    "{=}"-buildRecordLit a =-    "{ " <> buildFieldValues (Data.HashMap.Strict.InsOrd.toList a) <> " }"---- | Builder corresponding to the @fieldValues@ parser in "Dhall.Parser"-buildFieldValues :: Buildable a => [(Text, Expr s a)] -> Builder-buildFieldValues    []  = ""-buildFieldValues   [a]  = buildFieldValue a-buildFieldValues (a:bs) = buildFieldValue a <> ", " <> buildFieldValues bs---- | Builder corresponding to the @fieldValue@ parser in "Dhall.Parser"-buildFieldValue :: Buildable a => (Text, Expr s a) -> Builder-buildFieldValue (a, b) = buildLabel a <> " = " <> buildExprA b---- | Builder corresponding to the @record@ parser in "Dhall.Parser"-buildRecord :: Buildable a => InsOrdHashMap Text (Expr s a) -> Builder-buildRecord a | Data.HashMap.Strict.InsOrd.null a =-    "{}"-buildRecord a =-    "{ " <> buildFieldTypes (Data.HashMap.Strict.InsOrd.toList a) <> " }"---- | Builder corresponding to the @fieldTypes@ parser in "Dhall.Parser"-buildFieldTypes :: Buildable a => [(Text, Expr s a)] -> Builder-buildFieldTypes    []  = ""-buildFieldTypes   [a]  = buildFieldType a-buildFieldTypes (a:bs) = buildFieldType a <> ", " <> buildFieldTypes bs---- | Builder corresponding to the @fieldType@ parser in "Dhall.Parser"-buildFieldType :: Buildable a => (Text, Expr s a) -> Builder-buildFieldType (a, b) = buildLabel a <> " : " <> buildExprA b---- | Builder corresponding to the @union@ parser in "Dhall.Parser"-buildUnion :: Buildable a => InsOrdHashMap Text (Expr s a) -> Builder-buildUnion a | Data.HashMap.Strict.InsOrd.null a =-    "<>"-buildUnion a =-    "< " <> buildAlternativeTypes (Data.HashMap.Strict.InsOrd.toList a) <> " >"---- | Builder corresponding to the @alternativeTypes@ parser in "Dhall.Parser"-buildAlternativeTypes :: Buildable a => [(Text, Expr s a)] -> Builder-buildAlternativeTypes [] =-    ""-buildAlternativeTypes [a] =-    buildAlternativeType a-buildAlternativeTypes (a:bs) =-    buildAlternativeType a <> " | " <> buildAlternativeTypes bs---- | Builder corresponding to the @alternativeType@ parser in "Dhall.Parser"-buildAlternativeType :: Buildable a => (Text, Expr s a) -> Builder-buildAlternativeType (a, b) = buildLabel a <> " : " <> buildExprA b---- | Builder corresponding to the @unionLit@ parser in "Dhall.Parser"-buildUnionLit-    :: Buildable a-    => Text -> Expr s a -> InsOrdHashMap Text (Expr s a) -> Builder-buildUnionLit a b c-    | Data.HashMap.Strict.InsOrd.null c =-            "< "-        <>  buildLabel a-        <>  " = "-        <>  buildExprA b-        <>  " >"-    | otherwise =-            "< "-        <>  buildLabel a-        <>  " = "-        <>  buildExprA b-        <>  " | "-        <>  buildAlternativeTypes (Data.HashMap.Strict.InsOrd.toList c)-        <>  " >"+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE LambdaCase         #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE ViewPatterns       #-}++{-# OPTIONS_GHC -Wall #-}++{-| This module provides internal pretty-printing utilities which are used by+    other modules but are not part of the public facing API+-}++module Dhall.Pretty.Internal (+      Ann(..)+    , annToAnsiStyle+    , prettyExpr+    , prettySrcExpr++    , CharacterSet(..)+    , defaultCharacterSet+    , detectCharacterSet+    , prettyCharacterSet+    , prettyImportExpression++    , prettyVar+    , pretty_+    , escapeText_+    , escapeEnvironmentVariable+    , prettyEnvironmentVariable++    , prettyConst+    , UnescapedLabel(..)+    , escapeLabel+    , prettyLabel+    , prettyAnyLabel+    , prettyLabels+    , prettyNatural+    , prettyNumber+    , prettyInt+    , prettyDouble+    , prettyToStrictText+    , prettyToString+    , prettyBase16+    , layout+    , layoutOpts++    , docToStrictText++    , builtin+    , keyword+    , literal+    , operator++    , colon+    , comma+    , dot+    , equals+    , forall_+    , label+    , lambda+    , langle+    , lbrace+    , lbracket+    , lparen+    , pipe+    , rangle+    , rarrow+    , rbrace+    , rbracket+    , rparen++    , temporalToText+    ) where++import                Control.DeepSeq               (NFData)+import                Data.Aeson+    ( FromJSON (..)+    , Value (String)+    )+import                Data.Aeson.Types              (typeMismatch, unexpected)+import                Data.ByteString               (ByteString)+import                Data.Data                     (Data)+import                Data.Foldable+import                Data.List.NonEmpty            (NonEmpty (..))+import                Data.Text                     (Text)+import                Dhall.Map                     (Map)+import                Dhall.Src                     (Src (..))+import                Dhall.Syntax+import {-# SOURCE #-} Dhall.Syntax.Instances.Pretty ()+import                GHC.Generics                  (Generic)+import                Language.Haskell.TH.Syntax    (Lift)+import                Lens.Micro                    (cosmosOf, foldMapOf)+import                Numeric.Natural               (Natural)+import                Prettyprinter                 (Doc, Pretty, space)++import qualified Control.Exception             as Exception+import qualified Data.ByteString.Base16        as Base16+import qualified Data.Char+import qualified Data.HashSet+import qualified Data.List                     as List+import qualified Data.List.NonEmpty            as NonEmpty+import qualified Data.Maybe+import qualified Data.Text                     as Text+import qualified Data.Text.Encoding            as Encoding+import qualified Data.Time                     as Time+import qualified Dhall.Map                     as Map+import qualified Dhall.Syntax.Operations       as Operations+import qualified Prettyprinter                 as Pretty+import qualified Prettyprinter.Render.String   as Pretty+import qualified Prettyprinter.Render.Terminal as Terminal+import qualified Prettyprinter.Render.Text     as Pretty+import qualified Text.Printf                   as Printf++{-| Annotation type used to tag elements in a pretty-printed document for+    syntax highlighting purposes+-}+data Ann+  = Keyword     -- ^ Used for syntactic keywords+  | Syntax      -- ^ Syntax punctuation such as commas, parenthesis, and braces+  | Label       -- ^ Record labels+  | Literal     -- ^ Literals such as integers and strings+  | Builtin     -- ^ Builtin types and values+  | Operator    -- ^ Operators+  deriving Show++{-| Convert annotations to their corresponding color for syntax highlighting+    purposes+-}+annToAnsiStyle :: Ann -> Terminal.AnsiStyle+annToAnsiStyle Keyword  = Terminal.bold <> Terminal.colorDull Terminal.Green+annToAnsiStyle Syntax   = Terminal.bold <> Terminal.colorDull Terminal.Green+annToAnsiStyle Label    = mempty+annToAnsiStyle Literal  = Terminal.colorDull Terminal.Magenta+annToAnsiStyle Builtin  = Terminal.underlined+annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green++-- | This type determines whether to render code as `ASCII` or `Unicode`+data CharacterSet = ASCII | Unicode+    deriving (Eq, Ord, Show, Data, Generic, Lift, NFData)++-- | Since ASCII is a subset of Unicode, if either argument is Unicode, the+-- result is Unicode+instance Semigroup CharacterSet where+    Unicode <> _ = Unicode+    _ <> other = other++instance Monoid CharacterSet where+    mempty = ASCII++instance FromJSON CharacterSet where+  parseJSON (String "unicode") = pure Unicode+  parseJSON (String "ascii") = pure ASCII+  parseJSON v@(String _) = unexpected v+  parseJSON v = typeMismatch "String" v++-- | The character set used by default in functions throughout the Dhall code+-- base.+defaultCharacterSet :: CharacterSet+defaultCharacterSet = Unicode++-- | Detect which character set is used for the syntax of an expression+-- If any parts of the expression uses the Unicode syntax, the whole expression+-- is deemed to be using the Unicode syntax.+detectCharacterSet :: Expr Src a -> CharacterSet+detectCharacterSet = foldMapOf (cosmosOf subExpressions) exprToCharacterSet+  where+    exprToCharacterSet = \case+        Embed _ -> mempty -- Don't go down the embed route, otherwise: <<loop>>+        Lam (Just Unicode) _ _ -> Unicode+        Pi (Just Unicode) _ _ _ -> Unicode+        Combine (Just Unicode) _ _ _ -> Unicode+        CombineTypes (Just Unicode) _ _ -> Unicode+        Prefer (Just Unicode) _ _ _ -> Unicode+        Equivalent (Just Unicode) _ _ -> Unicode+        _ -> mempty++-- | Pretty print an expression+prettyExpr :: Pretty a => Expr s a -> Doc Ann+prettyExpr = prettySrcExpr . denote++prettySrcExpr :: Pretty a => Expr Src a -> Doc Ann+prettySrcExpr = prettyCharacterSet defaultCharacterSet++{-| Internal utility for pretty-printing, used when generating element lists+    to supply to `enclose` or `enclose'`.  This utility indicates that the+    compact represent is the same as the multi-line representation for each+    element+-}+duplicate :: a -> (a, a)+duplicate x = (x, x)++isWhitespace :: Char -> Bool+isWhitespace c =+    case c of+        ' '  -> True+        '\n' -> True+        '\t' -> True+        '\r' -> True+        _    -> False++{-| Used to render inline `Src` spans preserved by the syntax tree++    >>> let unusedSourcePos = Text.Megaparsec.SourcePos "" (Text.Megaparsec.mkPos 1) (Text.Megaparsec.mkPos 1)+    >>> let nonEmptySrc = Src unusedSourcePos unusedSourcePos "-- Documentation for x\n"+    >>> "let" <> " " <> renderSrc id (Just nonEmptySrc) <> "x = 1 in x"+    let -- Documentation for x+        x = 1 in x+    >>> let emptySrc = Src unusedSourcePos unusedSourcePos "      "+    >>> "let" <> " " <> renderSrc id (Just emptySrc) <> "x = 1 in x"+    let x = 1 in x+    >>> "let" <> " " <> renderSrc id Nothing <> "x = 1 in x"+    let x = 1 in x+-}+renderSrc+    :: (Text -> Text)+    -- ^ Used to preprocess the comment string (e.g. to strip whitespace)+    -> Maybe Src+    -- ^ Source span to render (if present)+    -> Doc Ann+renderSrc strip (Just (Src {..}))+    | not (Text.all isWhitespace srcText) =+        renderComment (strip srcText)+renderSrc _ _ =+    mempty++{-| Render a comment.++    Any preprocessing, such as whitespace stripping, needs to be handled by the+    caller, see e.g. 'renderSrc'.++    See the documentation for 'renderSrc' for examples.+-}+renderComment :: Text -> Doc Ann+renderComment text =+    Pretty.align (Pretty.concatWith f newLines <> suffix)+  where+    horizontalSpace c = c == ' ' || c == '\t'++    suffix =+        if Text.null text || Text.last text == '\n'+        then mempty+        else " "++    oldLines = Text.splitOn "\n" text++    spacePrefix = Text.takeWhile horizontalSpace++    commonPrefix a b = case Text.commonPrefixes a b of+        Nothing        -> ""+        Just (c, _, _) -> c++    sharedSpacePrefix []       = ""+    sharedSpacePrefix (l : ls) = foldl' commonPrefix (spacePrefix l) ls++    blank = Text.all horizontalSpace++    newLines =+        case oldLines of+            [] ->+               []+            l0 : ls ->+                let sharedPrefix =+                        sharedSpacePrefix (filter (not . blank) ls)++                    perLine l =+                        case Text.stripPrefix sharedPrefix l of+                            Nothing -> Pretty.pretty l+                            Just l' -> Pretty.pretty l'++                in  Pretty.pretty l0 : map perLine ls++    f x y = x <> Pretty.hardline <> y++{-| This is a variant of 'renderSrc' with the following differences:++      * The 'srcText' is stripped of all whitespace at the start and the end.+      * When the stripped 'srcText' is empty, the result is 'Nothing'.+-}+renderSrcMaybe :: Maybe Src -> Maybe (Doc Ann)+renderSrcMaybe (Just Src{..}) =+    case Text.dropAround isWhitespace srcText of+        "" -> Nothing+        t  -> Just (renderComment t)+renderSrcMaybe _ = Nothing++{-| @+    'containsComment' mSrc ≡ 'Data.Maybe.isJust' ('renderSrcMaybe' mSrc)+    @+-}+containsComment :: Maybe Src -> Bool+containsComment Nothing        = False+containsComment (Just Src{..}) = not (Text.all isWhitespace srcText)++-- Annotation helpers+keyword, syntax, label, literal, builtin, operator :: Doc Ann -> Doc Ann+keyword  = Pretty.annotate Keyword+syntax   = Pretty.annotate Syntax+label    = Pretty.annotate Label+literal  = Pretty.annotate Literal+builtin  = Pretty.annotate Builtin+operator = Pretty.annotate Operator++comma, lbracket, rbracket, langle, rangle, lbrace, rbrace, lparen, rparen, pipe, dollar, colon, equals, dot :: Doc Ann+comma    = syntax Pretty.comma+lbracket = syntax Pretty.lbracket+rbracket = syntax Pretty.rbracket+langle   = syntax Pretty.langle+rangle   = syntax Pretty.rangle+lbrace   = syntax Pretty.lbrace+rbrace   = syntax Pretty.rbrace+lparen   = syntax Pretty.lparen+rparen   = syntax Pretty.rparen+pipe     = syntax Pretty.pipe+dollar   = syntax "$"+colon    = syntax ":"+equals   = syntax "="+dot      = syntax "."++lambda :: CharacterSet -> Doc Ann+lambda Unicode = syntax "λ"+lambda ASCII   = syntax "\\"++forall_ :: CharacterSet -> Doc Ann+forall_ Unicode = syntax "∀"+forall_ ASCII   = syntax "forall "++rarrow :: CharacterSet -> Doc Ann+rarrow Unicode = syntax "→"+rarrow ASCII   = syntax "->"++doubleColon :: Doc Ann+doubleColon = syntax "::"++-- | Pretty-print a list+list :: [Doc Ann] -> Doc Ann+list   [] = lbracket <> rbracket+list docs =+    enclose+        (lbracket <> space)+        (lbracket <> space)+        (comma <> space)+        (comma <> space)+        (space <> rbracket)+        rbracket+        (fmap duplicate docs)++-- | Pretty-print union types and literals+angles :: [(Doc Ann, Doc Ann)] -> Doc Ann+angles   [] = langle <> rangle+angles docs =+    enclose+        (langle <> space)+        (langle <> space)+        (space <> pipe <> space)+        (pipe <> space)+        (space <> rangle)+        rangle+        docs++-- | Pretty-print record types and literals+braces :: [(Doc Ann, Doc Ann)] -> Doc Ann+braces   [] = lbrace <> rbrace+braces docs =+    enclose+        (lbrace <> space)+        (lbrace <> space)+        (comma <> space)+        (comma <> space)+        (space <> rbrace)+        rbrace+        docs++hangingBraces :: Int -> [(Doc Ann, Doc Ann)] -> Doc Ann+hangingBraces _ [] =+    lbrace <> rbrace+hangingBraces n docs =+    Pretty.group+        (Pretty.flatAlt+            (  lbrace+            <> Pretty.hardline+            <> Pretty.indent n+               ( mconcat (map (combineLong separator) docsLong)+               <> rbrace+               )+            )+            (mconcat (zipWith (<>) (beginShort : repeat separator) docsShort) <> space <> rbrace)+        )+  where+    separator = comma <> space++    docsShort = fmap fst docs++    docsLong = fmap snd docs++    beginShort = lbrace <> space++    combineLong x y = x <> y <> Pretty.hardline++unsnoc :: [a] -> Maybe ([a], a)+unsnoc       []   = Nothing+unsnoc (x0 : xs0) = Just (go id x0 xs0)+  where+    go diffXs x      []  = (diffXs [], x)+    go diffXs x (y : ys) = go (diffXs . (x:)) y ys++-- | Pretty-print anonymous functions and function types+arrows :: CharacterSet -> [ Doc Ann ] -> Doc Ann+arrows characterSet docs = Pretty.group (Pretty.flatAlt long short)+  where+    long = Pretty.align (mconcat (List.intersperse Pretty.hardline docs'))+      where+        docs' = case unsnoc docs of+            Nothing -> docs++            Just (init_, last_) -> init' ++ [ last' ]+              where+                 appendArrow doc = doc <> space <> rarrow characterSet++                 init' = map appendArrow init_++                 last' = space <> space <> last_++    short = mconcat (List.intersperse separator docs)+      where+        separator = space <> rarrow characterSet <> space++combine :: CharacterSet -> Text+combine ASCII   = "/\\"+combine Unicode = "∧"++combineTypes :: CharacterSet -> Text+combineTypes ASCII   = "//\\\\"+combineTypes Unicode = "⩓"++prefer :: CharacterSet -> Text+prefer ASCII   = "//"+prefer Unicode = "⫽"++equivalent :: CharacterSet -> Text+equivalent ASCII   = "==="+equivalent Unicode = "≡"++{-| Format an expression that holds a variable number of elements, such as a+    list, record, or union+-}+enclose+    :: Doc ann+    -- ^ Beginning document for compact representation+    -> Doc ann+    -- ^ Beginning document for multi-line representation+    -> Doc ann+    -- ^ Separator for compact representation+    -> Doc ann+    -- ^ Separator for multi-line representation+    -> Doc ann+    -- ^ Ending document for compact representation+    -> Doc ann+    -- ^ Ending document for multi-line representation+    -> [(Doc ann, Doc ann)]+    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@+    -> Doc ann+enclose beginShort _         _        _       endShort _       []   =+    beginShort <> endShort+enclose beginShort beginLong sepShort sepLong endShort endLong docs =+    Pretty.group+        (Pretty.flatAlt+            (Pretty.align+                (mconcat (zipWith combineLong (beginLong : repeat sepLong) docsLong) <> endLong)+            )+            (mconcat (zipWith combineShort (beginShort : repeat sepShort) docsShort) <> endShort)+        )+  where+    docsShort = fmap fst docs++    docsLong = fmap snd docs++    combineLong x y = x <> y <> Pretty.hardline++    combineShort x y = x <> y++{-| Format an expression that holds a variable number of elements without a+    trailing document such as nested @let@, nested lambdas, or nested @forall@s+-}+enclose'+    :: Doc ann+    -- ^ Beginning document for compact representation+    -> Doc ann+    -- ^ Beginning document for multi-line representation+    -> Doc ann+    -- ^ Separator for compact representation+    -> Doc ann+    -- ^ Separator for multi-line representation+    -> [(Doc ann, Doc ann)]+    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@+    -> Doc ann+enclose' beginShort beginLong sepShort sepLong docs =+    Pretty.group (Pretty.flatAlt long short)+  where+    longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong++    long =+        Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))++    short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort)++    docsShort = fmap fst docs++    docsLong = fmap snd docs++alpha :: Char -> Bool+alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')++digit :: Char -> Bool+digit c = '\x30' <= c && c <= '\x39'++alphaNum :: Char -> Bool+alphaNum c = alpha c || digit c++headCharacter :: Char -> Bool+headCharacter c = alpha c || c == '_'++tailCharacter :: Char -> Bool+tailCharacter c = alphaNum c || c == '_' || c == '-' || c == '/'++-- | The set of labels which do not need to be escaped+data UnescapedLabel+    = NonReservedLabel+    -- ^ This corresponds to the `nonreserved-label` rule in the grammar+    | AnyLabel+    -- ^ This corresponds to the `any-label` rule in the grammar+    | AnyLabelOrSome+    -- ^ This corresponds to the `any-label-or-some` rule in the grammar++-- | Escape a label if it is not valid when unquoted+escapeLabel :: UnescapedLabel -> Text -> Text+escapeLabel allowedLabel l =+    case Text.uncons l of+        Just (h, t)+            | headCharacter h && Text.all tailCharacter t && allowed && l /= "?"+                -> l+        _       -> "`" <> l <> "`"+  where+    allowed = case allowedLabel of+        NonReservedLabel -> notReservedIdentifier+        AnyLabel         -> notReservedKeyword+        AnyLabelOrSome   -> notReservedKeyword || l == "Some"++    notReservedIdentifier = not (Data.HashSet.member l reservedIdentifiers)++    notReservedKeyword = not (Data.HashSet.member l reservedKeywords)++prettyLabelShared :: UnescapedLabel -> Text -> Doc Ann+prettyLabelShared b l = label (Pretty.pretty (escapeLabel b l))++prettyLabel :: Text -> Doc Ann+prettyLabel = prettyLabelShared NonReservedLabel++prettyAnyLabel :: Text -> Doc Ann+prettyAnyLabel = prettyLabelShared AnyLabel++prettyAnyLabelOrSome :: Text -> Doc Ann+prettyAnyLabelOrSome = prettyLabelShared AnyLabelOrSome++prettyKeys+    :: Foldable list+    => (key -> Doc Ann)+    -> list (Maybe Src, key, Maybe Src)+    -> Doc Ann+prettyKeys prettyK keys = Pretty.group (Pretty.flatAlt long short)+  where+    short = (mconcat . Pretty.punctuate dot . map prettyKey . toList) keys++    long =+        case map prettyKey (toList keys) of+            []       -> mempty+            [doc]    -> doc+            doc:docs ->+                  Pretty.align+                . mconcat+                . Pretty.punctuate (Pretty.hardline <> ". ")+                $ Pretty.indent 2 doc : docs++    prettyKey (mSrc0, key, mSrc1) =+          Pretty.align+        . mconcat+        . Pretty.punctuate Pretty.hardline+        . Data.Maybe.catMaybes+        $ [ renderSrcMaybe mSrc0+          , Just (prettyK key)+          , renderSrcMaybe mSrc1+          ]++prettyLabels :: [Text] -> Doc Ann+prettyLabels a+    | null a    = lbrace <> rbrace+    | otherwise = braces (map (duplicate . prettyAnyLabelOrSome) a)++prettyNumber :: Integer -> Doc Ann+prettyNumber = literal . Pretty.pretty++prettyInt :: Int -> Doc Ann+prettyInt = literal . Pretty.pretty++prettyNatural :: Natural -> Doc Ann+prettyNatural = literal . Pretty.pretty++prettyDouble :: Double -> Doc Ann+prettyDouble = literal . Pretty.pretty++prettyConst :: Const -> Doc Ann+prettyConst Type = builtin "Type"+prettyConst Kind = builtin "Kind"+prettyConst Sort = builtin "Sort"++prettyVar :: Var -> Doc Ann+prettyVar (V x 0) = label (Pretty.unAnnotate (prettyLabel x))+prettyVar (V x n) = label (Pretty.unAnnotate (prettyLabel x <> "@" <> prettyInt n))++prettyEnvironmentVariable :: Text -> Doc ann+prettyEnvironmentVariable t = Pretty.pretty (escapeEnvironmentVariable t)++preserveSource :: Expr Src a -> Maybe (Doc Ann)+preserveSource (Note Src{..} (DoubleLit  {})) = Just (Pretty.pretty srcText)+preserveSource (Note Src{..} (IntegerLit {})) = Just (Pretty.pretty srcText)+preserveSource (Note Src{..} (NaturalLit {})) = Just (Pretty.pretty srcText)+preserveSource  _                             = Nothing++-- | Escape an environment variable if not a valid Bash environment variable+escapeEnvironmentVariable :: Text -> Text+escapeEnvironmentVariable t+  | validBashEnvVar t = t+  | otherwise         = "\"" <> escapeText_ t <> "\""+  where+    validBashEnvVar v = case Text.uncons v of+        Nothing      -> False+        Just (c, v') ->+                (alpha c || c == '_')+            &&  Text.all (\c' -> alphaNum c' || c' == '_') v'++{-  There is a close correspondence between the pretty-printers in 'prettyCharacterSet'+    and the sub-parsers in 'Dhall.Parser.Expression.parsers'.  Most pretty-printers are+    named after the corresponding parser and the relationship between pretty-printers+    exactly matches the relationship between parsers.  This leads to the nice emergent+    property of automatically getting all the parentheses and precedences right.++    This approach has one major disadvantage: you can get an infinite loop if+    you add a new constructor to the syntax tree without adding a matching+    case the corresponding builder.+-}++{-| Pretty-print an 'Expr' using the given 'CharacterSet'.++'prettyCharacterSet' largely ignores 'Note's. 'Note's do however matter for+the layout of let-blocks:++>>> let inner = Let (Binding Nothing "x" Nothing Nothing Nothing (NaturalLit 1)) (Var (V "x" 0)) :: Expr Src ()+>>> prettyCharacterSet ASCII (Let (Binding Nothing "y" Nothing Nothing Nothing (NaturalLit 2)) inner)+let y = 2 let x = 1 in x+>>> prettyCharacterSet ASCII (Let (Binding Nothing "y" Nothing Nothing Nothing (NaturalLit 2)) (Note (Src unusedSourcePos unusedSourcePos "") inner))+let y = 2 in let x = 1 in x++This means the structure of parsed let-blocks is preserved.+-}+prettyCharacterSet :: Pretty a => CharacterSet -> Expr Src a -> Doc Ann+prettyCharacterSet characterSet = prettyCompleteExpression+  where+    PrettyPrinters{..} = prettyPrinters characterSet++-- Mainly used by the `Pretty` instance for `Import`+prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann+prettyImportExpression = prettyImportExpression_+  where+    PrettyPrinters{..} = prettyPrinters Unicode++data PrettyPrinters a = PrettyPrinters+    { prettyCompleteExpression :: Expr Src a -> Doc Ann+    , prettyImportExpression_  :: Expr Src a -> Doc Ann+    }++prettyPrinters :: Pretty a => CharacterSet -> PrettyPrinters a+prettyPrinters characterSet =+    PrettyPrinters{..}+  where+    prettyCompleteExpression expression =+        Pretty.group (prettyExpression expression)++    prettyExpression a0@(Lam _ _ _) =+        arrows characterSet (docs a0)+      where+        docs (Lam _ (FunctionBinding { functionBindingVariable = a, functionBindingAnnotation = b }) c) =+            Pretty.group (Pretty.flatAlt long short) : docs c+          where+            long =  (lambda characterSet <> space)+                <>  Pretty.align+                    (   (lparen <> space)+                    <>  prettyLabel a+                    <>  Pretty.hardline+                    <>  (colon <> space)+                    <>  prettyExpression b+                    <>  Pretty.hardline+                    <>  rparen+                    )++            short = (lambda characterSet <> lparen)+                <>  prettyLabel a+                <>  (space <> colon <> space)+                <>  prettyExpression b+                <>  rparen+        docs c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docs d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression a0@(BoolIf _ _ _) =+        Pretty.group (Pretty.flatAlt long short)+      where+        prefixesLong =+                ""+            :   cycle+                    [ keyword "then" <> "  "+                    , keyword "else" <> "  "+                    ]++        prefixesShort =+                ""+            :   cycle+                    [ space <> keyword "then" <> space+                    , space <> keyword "else" <> space+                    ]++        longLines = zipWith (<>) prefixesLong (docsLong True a0)++        long =+            Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))++        short = mconcat (zipWith (<>) prefixesShort (docsShort a0))++        docsLong initial (BoolIf a b c) =+            docLong ++ docsLong False c+          where+            padding+                | initial   = "   "+                | otherwise = mempty++            docLong =+                [   keyword "if" <> padding <> " " <> prettyExpression a+                ,   prettyExpression b+                ]+        docsLong initial c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docsLong initial d+            | otherwise =+                [ prettyExpression c ]++        docsShort (BoolIf a b c) =+            docShort ++ docsShort c+          where+            docShort =+                [   keyword "if" <> " " <> prettyExpression a+                ,   prettyExpression b+                ]+        docsShort c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docsShort d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression (Let a0 b0) =+        enclose' "" "" space Pretty.hardline+            (fmap (duplicate . docA) (toList as) ++ [ docB ])+      where+        MultiLet as b = multiLet a0 b0++        isSpace c = c == ' ' || c == '\t'+        stripSpaces =+            Text.dropAround isSpace+          . Text.intercalate "\n"+          . map (Text.dropWhileEnd isSpace)+          . Text.splitOn "\n"++        -- Strip a single newline character. Needed to ensure idempotency in+        -- cases where we add hard line breaks.+        stripNewline t =+            case Text.uncons t' of+                Just ('\n', t'') -> stripSpaces t''+                _ -> t'+          where t' = stripSpaces t++        docA (Binding src0 c src1 Nothing src2 e) =+            Pretty.group (Pretty.flatAlt long short)+          where+            long =  keyword "let" <> space+                <>  Pretty.align+                    (   renderSrc stripSpaces src0+                    <>  prettyLabel c <> space <> renderSrc stripSpaces src1+                    <>  equals <> Pretty.hardline <> renderSrc stripNewline src2+                    <>  "  " <> prettyExpression e+                    )++            short = keyword "let" <> space <> renderSrc stripSpaces src0+                <>  prettyLabel c <> space <> renderSrc stripSpaces src1+                <>  equals <> space <> renderSrc stripSpaces src2+                <>  prettyExpression e+        docA (Binding src0 c src1 (Just (src3, d)) src2 e) =+                keyword "let" <> space+            <>  Pretty.align+                (   renderSrc stripSpaces src0+                <>  prettyLabel c <> Pretty.hardline <> renderSrc stripNewline src1+                <>  colon <> space <> renderSrc stripSpaces src3 <> prettyExpression d <> Pretty.hardline+                <>  equals <> space <> renderSrc stripSpaces src2+                <>  prettyExpression e+                )++        docB =+            ( keyword "in" <> " " <> prettyExpression b+            , keyword "in" <> "  "  <> prettyExpression b+            )+    prettyExpression a0@(Pi _ _ _ _) =+        arrows characterSet (docs a0)+      where+        docs (Pi _ "_" b c) = prettyOperatorExpression b : docs c+        docs (Pi _ a   b c) = Pretty.group (Pretty.flatAlt long short) : docs c+          where+            long =  forall_ characterSet <> space+                <>  Pretty.align+                    (   lparen <> space+                    <>  prettyLabel a+                    <>  Pretty.hardline+                    <>  colon <> space+                    <>  prettyExpression b+                    <>  Pretty.hardline+                    <>  rparen+                    )++            short = forall_ characterSet <> lparen+                <>  prettyLabel a+                <>  space <> colon <> space+                <>  prettyExpression b+                <>  rparen+        docs c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docs d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression (With (Dhall.Syntax.shallowDenote -> a) b c) =+            case a of+                With{} ->+                    -- Don't parenthesize an inner with-expression+                    prettyExpression a+                _ ->+                    prettyImportExpression_ a+        <>  Pretty.flatAlt long short+      where+        short = " " <> keyword "with" <> " " <> update++        long =  Pretty.hardline+            <>  "  "+            <>  Pretty.align (keyword "with" <> " " <> update)++        (update, _) =+            prettyKeyValue prettyKey prettyOperatorExpression equals+                (makeKeyValue b c)++        prettyKey (WithLabel text) = prettyAnyLabelOrSome text+        prettyKey  WithQuestion    = syntax "?"+    prettyExpression (Assert a) =+        Pretty.group (Pretty.flatAlt long short)+      where+        short = keyword "assert" <> " " <> colon <> " " <> prettyExpression a++        long =+            Pretty.align+            (  "  " <> keyword "assert"+            <> Pretty.hardline <> colon <> " " <> prettyExpression a+            )+    prettyExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyExpression b+        | otherwise =+            prettyAnnotatedExpression a++    prettyAnnotatedExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyAnnotatedExpression (Merge a b (Just c)) =+        Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   keyword "merge"+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ a)+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ b)+                <>  Pretty.hardline+                <>  colon <> space+                <>  prettyExpression c+                )++        short = keyword "merge" <> space+            <>  prettyImportExpression_ a+            <>  " "+            <>  prettyImportExpression_ b+            <>  space <> colon <> space+            <>  prettyExpression c+    prettyAnnotatedExpression (ToMap a (Just b)) =+        Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   keyword "toMap"+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ a)+                <>  Pretty.hardline+                <>  colon <> space+                <>  prettyExpression b+                )++        short = keyword "toMap" <> space+            <>  prettyImportExpression_ a+            <>  space <> colon <> space+            <>  prettyExpression b+    prettyAnnotatedExpression a0@(Annot _ _) =+        enclose'+            ""+            "  "+            (" " <> colon <> " ")+            (colon <> space)+            (fmap duplicate (docs a0))+      where+        docs (Annot a b) = prettyOperatorExpression a : docs b+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyExpression a ]+    prettyAnnotatedExpression (ListLit (Just a) b) =+            list (map prettyExpression (Data.Foldable.toList b))+        <>  " : "+        <>  prettyExpression a+    prettyAnnotatedExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyAnnotatedExpression b+        | otherwise =+            prettyOperatorExpression a++    prettyOperatorExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyOperatorExpression = prettyEquivalentExpression++    prettyOperator :: Text -> [Doc Ann] -> Doc Ann+    prettyOperator op docs =+        enclose'+            ""+            prefix+            (" " <> operator (Pretty.pretty op) <> " ")+            (operator (Pretty.pretty op) <> spacer)+            (reverse (fmap duplicate docs))+      where+        prefix = if Text.length op == 1 then "  " else "    "++        spacer = if Text.length op == 1 then " "  else "  "++    prettyEquivalentExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyEquivalentExpression a0@(Equivalent _ _ _) =+        prettyOperator (equivalent characterSet) (docs a0)+      where+        docs (Equivalent _ a b) = prettyImportAltExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyImportAltExpression a ]+    prettyEquivalentExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyEquivalentExpression b+        | otherwise =+            prettyImportAltExpression a++    prettyImportAltExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyImportAltExpression a0@(ImportAlt _ _) =+        prettyOperator "?" (docs a0)+      where+        docs (ImportAlt a b) = prettyOrExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyOrExpression a ]+    prettyImportAltExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyImportAltExpression b+        | otherwise =+            prettyOrExpression a++    prettyOrExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyOrExpression a0@(BoolOr _ _) =+        prettyOperator "||" (docs a0)+      where+        docs (BoolOr a b) = prettyPlusExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyPlusExpression a ]+    prettyOrExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyOrExpression b+        | otherwise =+            prettyPlusExpression a++    prettyPlusExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPlusExpression a0@(NaturalPlus _ _) =+        prettyOperator "+" (docs a0)+      where+        docs (NaturalPlus a b) = prettyTextAppendExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyTextAppendExpression a ]+    prettyPlusExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPlusExpression b+        | otherwise =+            prettyTextAppendExpression a++    prettyTextAppendExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyTextAppendExpression a0@(TextAppend _ _) =+        prettyOperator "++" (docs a0)+      where+        docs (TextAppend a b) = prettyListAppendExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyListAppendExpression a ]+    prettyTextAppendExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyTextAppendExpression b+        | otherwise =+            prettyListAppendExpression a++    prettyListAppendExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyListAppendExpression a0@(ListAppend _ _) =+        prettyOperator "#" (docs a0)+      where+        docs (ListAppend a b) = prettyAndExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyAndExpression a ]+    prettyListAppendExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyListAppendExpression b+        | otherwise =+            prettyAndExpression a++    prettyAndExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyAndExpression a0@(BoolAnd _ _) =+        prettyOperator "&&" (docs a0)+      where+        docs (BoolAnd a b) = prettyCombineExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyCombineExpression a ]+    prettyAndExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyAndExpression b+        | otherwise =+            prettyCombineExpression a++    prettyCombineExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCombineExpression a0@(Combine _ _ _ _) =+        prettyOperator (combine characterSet) (docs a0)+      where+        docs (Combine _ _ a b) = prettyPreferExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyPreferExpression a ]+    prettyCombineExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCombineExpression b+        | otherwise =+            prettyPreferExpression a++    prettyPreferExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPreferExpression a0@(Prefer {}) =+        prettyOperator (prefer characterSet) (docs a0)+      where+        docs (Prefer _ _ a b) = prettyCombineTypesExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyCombineTypesExpression a ]+    prettyPreferExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPreferExpression b+        | otherwise =+            prettyCombineTypesExpression a++    prettyCombineTypesExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCombineTypesExpression a0@(CombineTypes _ _ _) =+        prettyOperator (combineTypes characterSet) (docs a0)+      where+        docs (CombineTypes _ a b) = prettyTimesExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyTimesExpression a ]+    prettyCombineTypesExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCombineTypesExpression b+        | otherwise =+            prettyTimesExpression a++    prettyTimesExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyTimesExpression a0@(NaturalTimes _ _) =+        prettyOperator "*" (docs a0)+      where+        docs (NaturalTimes a b) = prettyEqualExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyEqualExpression a ]+    prettyTimesExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyTimesExpression b+        | otherwise =+            prettyEqualExpression a++    prettyEqualExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyEqualExpression a0@(BoolEQ _ _) =+        prettyOperator "==" (docs a0)+      where+        docs (BoolEQ a b) = prettyNotEqualExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyNotEqualExpression a ]+    prettyEqualExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyEqualExpression b+        | otherwise =+            prettyNotEqualExpression a++    prettyNotEqualExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyNotEqualExpression a0@(BoolNE _ _) =+        prettyOperator "!=" (docs a0)+      where+        docs (BoolNE a b) = prettyApplicationExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyApplicationExpression a ]+    prettyNotEqualExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyNotEqualExpression b+        | otherwise =+            prettyApplicationExpression a++    prettyApplicationExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyApplicationExpression = go []+      where+        go args = \case+            App a b           -> go (b : args) a+            Some a            -> app (builtin "Some") (a : args)+            Merge a b Nothing -> app (keyword "merge") (a : b : args)+            ToMap a Nothing   -> app (keyword "toMap") (a : args)+            ShowConstructor a -> app (keyword "showConstructor") (a : args)+            e | Note _ b <- e ->+                  go args b+              | null args ->+                  prettyImportExpression_ e -- just a performance optimization+              | Just doc <- preserveSource e ->+                  app doc args+              | otherwise ->+                  app (prettyImportExpression_ e) args++        app f args =+            enclose'+                "" "" " " ""+                ( duplicate f+                : map (fmap (Pretty.indent 2) . duplicate . prettyImportExpression_) args+                )++    prettyImportExpression_ :: Pretty a => Expr Src a -> Doc Ann+    prettyImportExpression_ (Embed a) =+        Pretty.pretty a+    prettyImportExpression_ a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyImportExpression_ b+        | otherwise =+            prettyCompletionExpression a++    prettyCompletionExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCompletionExpression (RecordCompletion a b) =+        case shallowDenote b of+            RecordLit kvs ->+                Pretty.align+                    (   prettySelectorExpression a+                    <>  doubleColon+                    <>  prettyCompletionLit 0 kvs+                    )+            _ ->    prettySelectorExpression a+                <>  doubleColon+                <>  prettySelectorExpression b+    prettyCompletionExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCompletionExpression b+        | otherwise =+            prettySelectorExpression a++    prettySelectorExpression :: Pretty a => Expr Src a -> Doc Ann+    prettySelectorExpression (Field a (Dhall.Syntax.fieldSelectionLabel -> b)) =+        prettySelectorExpression a <> dot <> prettyAnyLabel b+    prettySelectorExpression (Project a (Left b)) =+        prettySelectorExpression a <> dot <> prettyLabels b+    prettySelectorExpression (Project a (Right b)) =+            prettySelectorExpression a+        <>  dot+        <>  lparen+        <>  prettyExpression b+        <>  rparen+    prettySelectorExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettySelectorExpression b+        | otherwise =+            prettyPrimitiveExpression a++    prettyPrimitiveExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPrimitiveExpression (Var a) =+        prettyVar a+    prettyPrimitiveExpression (Const k) =+        prettyConst k+    prettyPrimitiveExpression Bool =+        builtin "Bool"+    prettyPrimitiveExpression Bytes =+        builtin "Bytes"+    prettyPrimitiveExpression Natural =+        builtin "Natural"+    prettyPrimitiveExpression NaturalFold =+        builtin "Natural/fold"+    prettyPrimitiveExpression NaturalBuild =+        builtin "Natural/build"+    prettyPrimitiveExpression NaturalIsZero =+        builtin "Natural/isZero"+    prettyPrimitiveExpression NaturalEven =+        builtin "Natural/even"+    prettyPrimitiveExpression NaturalOdd =+        builtin "Natural/odd"+    prettyPrimitiveExpression NaturalToInteger =+        builtin "Natural/toInteger"+    prettyPrimitiveExpression NaturalShow =+        builtin "Natural/show"+    prettyPrimitiveExpression NaturalSubtract =+        builtin "Natural/subtract"+    prettyPrimitiveExpression Integer =+        builtin "Integer"+    prettyPrimitiveExpression IntegerClamp =+        builtin "Integer/clamp"+    prettyPrimitiveExpression IntegerNegate =+        builtin "Integer/negate"+    prettyPrimitiveExpression IntegerShow =+        builtin "Integer/show"+    prettyPrimitiveExpression IntegerToDouble =+        builtin "Integer/toDouble"+    prettyPrimitiveExpression Double =+        builtin "Double"+    prettyPrimitiveExpression DoubleShow =+        builtin "Double/show"+    prettyPrimitiveExpression Text =+        builtin "Text"+    prettyPrimitiveExpression TextReplace =+        builtin "Text/replace"+    prettyPrimitiveExpression TextShow =+        builtin "Text/show"+    prettyPrimitiveExpression Date =+        builtin "Date"+    prettyPrimitiveExpression (DateLiteral day) =+        literal+            (   Pretty.pretty (Printf.printf "%04d" _HHHH :: String)+            <>  "-"+            <>  Pretty.pretty (Printf.printf "%02d" _MM :: String)+            <>  "-"+            <>  Pretty.pretty (Printf.printf "%02d" _DD :: String)+            )+      where+        (_HHHH, _MM, _DD) = Time.toGregorian day+    prettyPrimitiveExpression DateShow =+        builtin "Date/show"+    prettyPrimitiveExpression Time =+        builtin "Time"+    prettyPrimitiveExpression (TimeLiteral (Time.TimeOfDay hh mm seconds) precision) =+        literal+            (   Pretty.pretty (Printf.printf "%02d" hh :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" mm :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" ss :: String)+            <>  suffix+            )+      where+        magnitude :: Integer+        magnitude = 10 ^ precision++        (ss, fraction) = truncate (seconds * fromInteger magnitude) `divMod` magnitude++        suffix+            | precision == 0 = ""+            | otherwise      = "." <> Pretty.pretty (Printf.printf "%0*d" precision fraction :: String)+    prettyPrimitiveExpression TimeShow =+        builtin "Time/show"+    prettyPrimitiveExpression TimeZone =+        builtin "TimeZone"+    prettyPrimitiveExpression (TimeZoneLiteral (Time.TimeZone minutes _ _)) =+        literal+            (   sign+            <>  Pretty.pretty (Printf.printf "%02d" _HH :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" _MM :: String)+            )+      where+        sign = if 0 <= minutes then "+" else "-"++        (_HH, _MM) = abs minutes `divMod` 60+    prettyPrimitiveExpression TimeZoneShow =+        builtin "TimeZone/show"+    prettyPrimitiveExpression List =+        builtin "List"+    prettyPrimitiveExpression ListBuild =+        builtin "List/build"+    prettyPrimitiveExpression ListFold =+        builtin "List/fold"+    prettyPrimitiveExpression ListLength =+        builtin "List/length"+    prettyPrimitiveExpression ListHead =+        builtin "List/head"+    prettyPrimitiveExpression ListLast =+        builtin "List/last"+    prettyPrimitiveExpression ListIndexed =+        builtin "List/indexed"+    prettyPrimitiveExpression ListReverse =+        builtin "List/reverse"+    prettyPrimitiveExpression Optional =+        builtin "Optional"+    prettyPrimitiveExpression None =+        builtin "None"+    prettyPrimitiveExpression (BoolLit True) =+        builtin "True"+    prettyPrimitiveExpression (BoolLit False) =+        builtin "False"+    prettyPrimitiveExpression (IntegerLit a)+        | 0 <= a    = literal "+" <> prettyNumber a+        | otherwise = prettyNumber a+    prettyPrimitiveExpression (NaturalLit a) =+        prettyNatural a+    prettyPrimitiveExpression (DoubleLit (DhallDouble a)) =+        prettyDouble a+    prettyPrimitiveExpression (TextLit a) =+        prettyChunks a+    prettyPrimitiveExpression (BytesLit a) =+        prettyBytes a+    prettyPrimitiveExpression (Record a) =+        prettyRecord a+    prettyPrimitiveExpression (RecordLit a) =+        prettyRecordLit a+    prettyPrimitiveExpression (Union a) =+        prettyUnion a+    prettyPrimitiveExpression (ListLit Nothing b) =+        list (map prettyExpression (Data.Foldable.toList b))+    prettyPrimitiveExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPrimitiveExpression b+        | otherwise =+            Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (lparen <> space <> prettyExpression a <> Pretty.hardline <> rparen)++        short = lparen <> prettyExpression a <> rparen++    prettyKeyValue+        :: Pretty a+        => (key -> Doc Ann)+        -> (Expr Src a -> Doc Ann)+        -> Doc Ann+        -> KeyValue key Src a+        -> (Doc Ann, Doc Ann)+    prettyKeyValue prettyKey prettyValue separator (KeyValue key mSrc val) =+        duplicate (Pretty.group (Pretty.flatAlt long short))+      where+        completion _T r =+                prettySelectorExpression _T+            <>  doubleColon+            <>  case shallowDenote r of+                    RecordLit kvs ->+                        prettyCompletionLit 2 kvs+                    _ ->+                        prettySelectorExpression r++        short = prettyKeys prettyKey key+            <>  " "+            <>  separator+            <>  " "+            <>  case renderSrcMaybe mSrc of+                    Nothing  -> mempty+                    Just doc -> doc <> Pretty.hardline+            <>  prettyValue val++        long =  Pretty.align+                    (   prettyKeys prettyKey key+                    <>  preSeparator+                    )+            <>  separator+            <>  case renderSrcMaybe mSrc of+                    Just doc ->+                            preComment+                        <>  Pretty.align+                                (   doc+                                <>  Pretty.hardline+                                <>  prettyValue val+                                )+                    Nothing ->+                        case shallowDenote val of+                            Some val' ->+                                    " "+                                <>  builtin "Some"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r++                                        RecordLit _ ->+                                                Pretty.hardline+                                            <>  "  "+                                            <>  prettyImportExpression_ val'++                                        ListLit _ xs+                                            | not (null xs) ->+                                                    Pretty.hardline+                                                <>  "  "+                                                <>  prettyImportExpression_ val'++                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            ToMap val' Nothing ->+                                    " "+                                <>  keyword "toMap"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            ShowConstructor val' ->+                                    " "+                                <>  keyword "showConstructor"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            RecordCompletion _T r ->+                                " " <> completion _T r++                            RecordLit _ ->+                                    Pretty.hardline+                                <>  "  "+                                <>  prettyValue val++                            ListLit _ xs+                                | not (null xs) ->+                                        Pretty.hardline+                                    <>  "  "+                                    <>  prettyValue val++                            _ ->+                                Pretty.group+                                    (   Pretty.flatAlt (Pretty.hardline <> "    ") " "+                                    <>  prettyValue val+                                    )+          where+            (preSeparator, preComment) =+                case key of+                    (_, _, mSrc2) :| [] | not (containsComment mSrc2) ->+                        (" ", Pretty.hardline <> "    ")+                    _ ->+                        (Pretty.hardline, " ")+++    prettyRecord :: Pretty a => Map Text (RecordField Src a) -> Doc Ann+    prettyRecord =+        ( braces+        . map (prettyKeyValue prettyAnyLabelOrSome prettyExpression colon . adapt)+        . Map.toList+        )+      where+        adapt (key, RecordField mSrc0 val mSrc1 mSrc2) = KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val++    prettyRecordLit :: Pretty a => Map Text (RecordField Src a) -> Doc Ann+    prettyRecordLit m+        | [ ("date"    , field -> d@DateLiteral{})+          , ("time"    , field -> t@TimeLiteral{})+          , ("timeZone", field -> z@TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression d+                  <>  "T"+                  <>  prettyPrimitiveExpression t+                  <>  prettyPrimitiveExpression z+                  )+        | [ ("date"    , field -> d@DateLiteral{})+          , ("time"    , field -> t@TimeLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression d+                  <>  "T"+                  <>  prettyPrimitiveExpression t+                  )+        | [ ("time"    , field -> t@TimeLiteral{})+          , ("timeZone", field -> z@TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression t+                  <>  prettyPrimitiveExpression z+                  )+      where+        field = Dhall.Syntax.shallowDenote . recordFieldValue+    prettyRecordLit m = prettyRecordLike braces m++    prettyCompletionLit :: Pretty a => Int -> Map Text (RecordField Src a) -> Doc Ann+    prettyCompletionLit = prettyRecordLike . hangingBraces++    prettyRecordLike+        :: Pretty a+        => ([(Doc Ann, Doc Ann)] -> Doc Ann)+        -> Map Text (RecordField Src a)+        -> Doc Ann+    prettyRecordLike braceStyle a+        | Data.Foldable.null a =+            lbrace <> equals <> rbrace+        | otherwise =+            braceStyle (map prettyRecordEntry (consolidateRecordLiteral a))+      where+        prettyRecordEntry kv@(KeyValue keys mSrc2 val) =+            case keys of+                (mSrc0, key, mSrc1) :| []+                    | Var (V key' 0) <- Dhall.Syntax.shallowDenote val+                    , key == key'+                    , not (containsComment mSrc2) ->+                        duplicate (prettyKeys prettyAnyLabelOrSome [(mSrc0, key, mSrc1)])+                _ ->+                    prettyKeyValue prettyAnyLabelOrSome prettyExpression equals kv++    prettyAlternative (key, Just val) =+        prettyKeyValue prettyAnyLabelOrSome prettyExpression colon (makeKeyValue (pure key) val)+    prettyAlternative (key, Nothing) =+        duplicate (prettyAnyLabelOrSome key)++    prettyUnion :: Pretty a => Map Text (Maybe (Expr Src a)) -> Doc Ann+    prettyUnion =+        angles . map prettyAlternative . Map.toList++    prettyBytes :: ByteString -> Doc Ann+    prettyBytes bytes =+        literal (Pretty.pretty ("0x\"" <> prettyBase16 bytes <> "\""))++    prettyChunks :: Pretty a => Chunks Src a -> Doc Ann+    prettyChunks chunks@(Chunks a b)+        | anyText (== '\n') =+            if not (null a) || anyText (/= '\n')+            then long+            else Pretty.group (Pretty.flatAlt long short)+        | otherwise =+            short+      where+        long =+            Pretty.align+            (   literal "''" <> Pretty.hardline+            <>  Pretty.align+                (foldMap prettyMultilineChunk a' <> prettyMultilineText b')+            <>  literal "''"+            )+          where+            Chunks a' b' = multilineChunks chunks++        short =+            literal "\"" <> foldMap prettyChunk a <> literal (prettyText b <> "\"")++        anyText predicate = any (\(text, _) -> Text.any predicate text) a || Text.any predicate b++        prettyMultilineChunk (c, d) =+                prettyMultilineText c+            <>  dollar+            <>  lbrace+            <>  prettyExpression d+            <>  rbrace++        prettyMultilineText text = mconcat docs+          where+            lines_ = Text.splitOn "\n" text++            -- Annotate only non-empty lines so trailing whitespace can be+            -- removed on empty ones.+            prettyLine line =+                (if Text.null line then id else literal)+                    (Pretty.pretty line)++            docs = List.intersperse Pretty.hardline (map prettyLine lines_)++        prettyChunk (c, d) =+                prettyText c+            <>  syntax "${"+            <>  prettyExpression d+            <>  syntax rbrace++        prettyText t = literal (Pretty.pretty (escapeText_ t))+++-- | Prepare 'Chunks' for multi-line formatting by escaping problematic+-- character sequences via string interpolations+--+-- >>> multilineChunks (Chunks [] "\n \tx")+-- Chunks [("\n",TextLit (Chunks [] " \t"))] "x"+-- >>> multilineChunks (Chunks [] "\n\NUL\b\f\t")+-- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t"+multilineChunks :: Chunks s a -> Chunks s a+multilineChunks =+     escapeSingleQuotedText+   . escapeTrailingSingleQuote+   . escapeControlCharacters+   . escapeSingleQuoteBeforeInterpolation+   . escapeSharedWhitespacePrefix++-- | Escape any leading whitespace shared by all lines+--+-- This ensures that significant shared leading whitespace is not stripped+--+-- >>> escapeSharedWhitespacePrefix (Chunks [] "\n \tx")+-- Chunks [("\n",TextLit (Chunks [] " \t"))] "x"+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n",Var (V "x" 0))] " ")+-- Chunks [("\n",Var (V "x" 0))] " "+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n ",Var (V "x" 0))] "")+-- Chunks [("\n",TextLit (Chunks [] " ")),("",Var (V "x" 0))] ""+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n ",Var (V "x" 0))] "\n")+-- Chunks [("\n ",Var (V "x" 0))] "\n"+-- >>> escapeSharedWhitespacePrefix (Chunks [] " ")+-- Chunks [("",TextLit (Chunks [] " "))] ""+escapeSharedWhitespacePrefix :: Chunks s a -> Chunks s a+escapeSharedWhitespacePrefix literal_ = unlinesLiteral literals₁+  where+    literals₀ = linesLiteral literal_++    sharedPrefix = longestSharedWhitespacePrefix literals₀++    stripPrefix = Text.drop (Text.length sharedPrefix)++    escapeSharedPrefix (Chunks [] prefix₀)+        | Text.isPrefixOf sharedPrefix prefix₀ =+            Chunks [ ("", TextLit (Chunks [] sharedPrefix)) ] prefix₁+      where+        prefix₁ = stripPrefix prefix₀+    escapeSharedPrefix (Chunks ((prefix₀, y) : xys) z)+        | Text.isPrefixOf sharedPrefix prefix₀ =+            Chunks (("", TextLit (Chunks [] sharedPrefix)) : (prefix₁, y) : xys) z+      where+        prefix₁ = stripPrefix prefix₀+    escapeSharedPrefix line = line++    literals₁+        | not (Text.null sharedPrefix) = fmap escapeSharedPrefix literals₀+        | otherwise = literals₀++-- | Escape control characters by moving them into string interpolations+--+-- >>> escapeControlCharacters (Chunks [] "\n\NUL\b\f\t")+-- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t"+escapeControlCharacters :: Chunks s a -> Chunks s a+escapeControlCharacters = splitWith (splitOnPredicate predicate)+  where+    predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n'++-- | Escape @'${@ correctly+--+-- See: https://github.com/dhall-lang/dhall-haskell/issues/2078+escapeSingleQuoteBeforeInterpolation :: Chunks s a -> Chunks s a+escapeSingleQuoteBeforeInterpolation = splitWith f+  where+    f text =+        case Text.splitOn "'${" text of+            -- `splitOn` should never return an empty list, but just in case…+            []     -> mempty+            t : ts -> loop t ts++    loop head_ tail_ =+        case tail_ of+            [] ->+                Chunks [] head_+            newHead : newTail ->+                    Chunks [ (head_, TextLit (Chunks [] "'")) ] "${"+                <>  loop newHead newTail++{-| You can think of this as sort of like `concatMap` for `Chunks`++    Given a function that splits plain text into interpolated chunks, apply+    that function to each uninterpolated span to yield a new+    possibly-interpolated span, and flatten the results.+-}+splitWith :: (Text -> Chunks s a) -> Chunks s a -> Chunks s a+splitWith splitter (Chunks xys z) = mconcat (xys' ++ [ splitter z ])+  where+    xys' = do+        (x, y) <- xys++        [ splitter x, Chunks [ ("", y) ] "" ]++-- | Split `Data.Text.Text` into interpolated chunks, where all characters+-- matching the predicate are pushed into a string interpolation.+--+-- >>> splitOnPredicate (== 'x') ""+-- Chunks [] ""+-- >>> splitOnPredicate (== 'x') " xx "+-- Chunks [(" ",TextLit (Chunks [] "xx"))] " "+-- >>> splitOnPredicate (== 'x') "xx"+-- Chunks [("",TextLit (Chunks [] "xx"))] ""+--+-- prop> \(Fun _ p) s -> let {t = Text.pack s; Chunks xys z = splitOnPredicate p t} in foldMap (\(x, TextLit (Chunks [] y)) -> x <> y) xys <> z == t+splitOnPredicate :: (Char -> Bool) -> Text -> Chunks s a+splitOnPredicate predicate text+    | Text.null b =+        Chunks [] a+    | otherwise =+        Chunks ((a, TextLit (Chunks [] c)) : e) f+  where+    (a, b) = Text.break predicate text++    (c, d) = Text.span predicate b++    Chunks e f = splitOnPredicate predicate d++-- | Escape a trailing single quote by moving it into a string interpolation+--+-- Otherwise the multiline-string would end with @'''@, which would be parsed+-- as an escaped @''@.+--+-- >>> escapeTrailingSingleQuote (Chunks [] "\n'")+-- Chunks [("\n",TextLit (Chunks [] "'"))] ""+escapeTrailingSingleQuote :: Chunks s a -> Chunks s a+escapeTrailingSingleQuote chunks@(Chunks as b) =+    case Text.unsnoc b of+        Just (b', '\'') -> Chunks (as ++ [(b', TextLit (Chunks [] "'"))]) ""+        _               -> chunks++-- | Pretty-print a value+pretty_ :: Pretty a => a -> Text+pretty_ = prettyToStrictText++data KeyValue k s a = KeyValue+    { _keyValueKeys  :: NonEmpty (Maybe s, k , Maybe s)+    , _keyValueSrc   :: Maybe s+    , _keyValueValue :: Expr s a+    }++makeKeyValue :: NonEmpty key -> Expr s a -> KeyValue key s a+makeKeyValue keys expr = KeyValue (adapt <$> keys) Nothing expr+  where+    adapt key = (Nothing, key, Nothing)++{- This utility function converts+   `{ x = { y = { z = 1 } } }` to `{ x.y.z = 1 }`+-}+consolidateRecordLiteral+    :: Map Text (RecordField Src a) -> [KeyValue Text Src a]+consolidateRecordLiteral = concatMap adapt . Map.toList+  where+    adapt :: (Text, RecordField Src a) -> [KeyValue Text Src a]+    adapt (key, RecordField mSrc0 val mSrc1 mSrc2)+        | not (containsComment mSrc2)+        , RecordLit m <- e+        , [ KeyValue keys mSrc2' val' ] <- concatMap adapt (Map.toList m) =+            [ KeyValue (NonEmpty.cons (mSrc0, key, mSrc1) keys) mSrc2' val' ]++        | Combine _ (Just _) l r <- e =+            adapt (key, makeRecordField l) <> adapt (key, makeRecordField r)+        | otherwise =+            [ KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val ]+      where+        e = shallowDenote val++-- | Escape a `Data.Text.Text` literal using Dhall's escaping rules for+--   single-quoted @Text@+escapeSingleQuotedText :: Chunks s a -> Chunks s a+escapeSingleQuotedText = splitWith f+  where+    f inputText = Chunks [] outputText+      where+        outputText =+            Text.replace "${" "''${" (Text.replace "''" "'''" inputText)++{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules++    Note that the result does not include surrounding quotes+-}+escapeText_ :: Text -> Text+escapeText_ text = Text.concatMap adapt text+  where+    adapt c+        | '\x20' <= c && c <= '\x21'     = Text.singleton c+        -- '\x22' == '"'+        | '\x23' == c                    = Text.singleton c+        -- '\x24' == '$'+        | '\x25' <= c && c <= '\x5B'     = Text.singleton c+        -- '\x5C' == '\\'+        | '\x5D' <= c && c <= '\x10FFFF' = Text.singleton c+        | c == '"'                       = "\\\""+        | c == '$'                       = "\\$"+        | c == '\\'                      = "\\\\"+        | c == '\b'                      = "\\b"+        | c == '\f'                      = "\\f"+        | c == '\n'                      = "\\n"+        | c == '\r'                      = "\\r"+        | c == '\t'                      = "\\t"+        | otherwise                      = "\\u" <> showDigits (Data.Char.ord c)++    showDigits r0 = Text.pack (map showDigit [q1, q2, q3, r3])+      where+        (q1, r1) = r0 `quotRem` 4096+        (q2, r2) = r1 `quotRem`  256+        (q3, r3) = r2 `quotRem`   16++    showDigit n+        | n < 10    = Data.Char.chr (Data.Char.ord '0' + n)+        | otherwise = Data.Char.chr (Data.Char.ord 'A' + n - 10)++prettyToString :: Pretty a => a -> String+prettyToString =+    Pretty.renderString . layout . Pretty.pretty++docToStrictText :: Doc ann -> Text.Text+docToStrictText = Pretty.renderStrict . layout++prettyToStrictText :: Pretty a => a -> Text.Text+prettyToStrictText = docToStrictText . Pretty.pretty++-- | Layout using 'layoutOpts'+--+-- Tries hard to fit the document into 80 columns.+--+-- This also removes trailing space characters (@' '@) /unless/+-- they are enclosed in an annotation.+layout :: Pretty.Doc ann -> Pretty.SimpleDocStream ann+layout = Pretty.removeTrailingWhitespace . Pretty.layoutSmart layoutOpts++-- | Default layout options+layoutOpts :: Pretty.LayoutOptions+layoutOpts =+    Pretty.defaultLayoutOptions+        { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }++{-| Convert an expression representing a temporal value to `Data.Text.Text`, if+    possible++    This is used by downstream integrations (e.g. `dhall-json` for treating+    temporal values as strings+-}+temporalToText :: Pretty a => Expr s a -> Maybe Text+temporalToText e = case e of+    RecordLit m+        | [ ("date"    , field -> DateLiteral{})+          , ("time"    , field -> TimeLiteral{})+          , ("timeZone", field -> TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+        | [ ("date"    , field -> DateLiteral{})+          , ("time"    , field -> TimeLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+        | [ ("time"    , field -> TimeLiteral{})+          , ("timeZone", field -> TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+    DateLiteral{} -> rendered+    TimeLiteral{} -> rendered+    TimeZoneLiteral{} -> rendered+    _ -> Nothing+  where+    field = Dhall.Syntax.shallowDenote . recordFieldValue++    rendered = Just (prettyToStrictText e)++prettyBase16 :: ByteString -> Text+prettyBase16 bytes =+    case Encoding.decodeUtf8' (Base16.encode bytes) of+        Left exception ->+            Operations.internalError+                ("prettyBase16: base16-encoded bytes could not be decoded as UTF-8 text: " <> Text.pack (Exception.displayException exception))+        Right text ->+            Text.toUpper text++{- $setup+>>> import Test.QuickCheck (Fun(..))+-}
src/Dhall/Pretty/Internal.hs-boot view
@@ -1,31 +1,35 @@ module Dhall.Pretty.Internal where -import Data.Scientific (Scientific)-import Data.Text.Buildable (Buildable)-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-import Data.Text.Prettyprint.Doc (Pretty, Doc)-import Numeric.Natural (Natural)-import Prelude+import Control.DeepSeq            (NFData)+import Data.Data                  (Data)+import Data.Text                  (Text)+import Dhall.Src                  (Src)+import Language.Haskell.TH.Syntax (Lift)+import Prettyprinter              (Doc, Pretty) -import {-# SOURCE #-} Dhall.Core+import                Dhall.Syntax.Const+import {-# SOURCE #-} Dhall.Syntax.Expr+import                Dhall.Syntax.Var  data Ann -buildConst :: Const -> Builder--buildVar :: Var -> Builder--buildExpr :: Buildable a => Expr s a -> Builder+data CharacterSet = ASCII | Unicode -prettyExpr :: Pretty a => Expr s a -> Doc Ann+instance Eq CharacterSet+instance Ord CharacterSet+instance Show CharacterSet+instance Data CharacterSet+instance Lift CharacterSet+instance NFData CharacterSet+instance Semigroup CharacterSet+instance Monoid CharacterSet -buildNatural :: Natural -> Builder+prettyVar :: Var -> Doc Ann -buildNumber :: Integer -> Builder+prettyConst :: Const -> Doc Ann -buildScientific :: Scientific -> Builder+prettyExpr :: Pretty a => Expr s a -> Doc Ann -pretty :: Pretty a => a -> Text+prettyEnvironmentVariable :: Text -> Doc ann -escapeText :: Builder -> Builder+prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann
+ src/Dhall/Repl.hs view
@@ -0,0 +1,680 @@+-- | This module contains the implementation of the @dhall repl@ subcommand++{-# LANGUAGE CPP               #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}++module Dhall.Repl+    ( -- * Repl+      repl+    ) where++import Control.Exception+    ( SomeException (SomeException)+    , displayException+    , throwIO+    )+import Control.Monad     (forM_)+#if !(MIN_VERSION_base(4,13,0))+import Control.Monad.Fail (MonadFail)+#endif+import Control.Monad.IO.Class              (MonadIO, liftIO)+import Control.Monad.State.Class           (MonadState, get, modify)+import Control.Monad.State.Strict          (evalStateT)+import Data.Char                           (isSpace)+import Data.List+    ( dropWhileEnd+    , groupBy+    , isPrefixOf+    , nub+    )+import Data.Maybe                          (mapMaybe)+import Data.Text                           (Text)+import Data.Void                           (Void)+import Dhall.Context                       (Context)+import Dhall.Import                        (hashExpressionToCode)+import Dhall.Parser                        (Parser (..))+import Dhall.Pretty                        (CharacterSet (..))+import Dhall.Src                           (Src)+import System.Console.Haskeline            (Interrupt (..))+import System.Console.Haskeline.Completion (Completion, simpleCompletion)+import System.Directory                    (getDirectoryContents)+import System.Environment                  (getEnvironment)++import qualified Control.Monad.Fail                  as Fail+import qualified Control.Monad.Trans.State.Strict    as State+import qualified Data.HashSet+import qualified Data.Text                           as Text+import qualified Data.Text.IO                        as Text.IO+import qualified Dhall+import qualified Dhall.Context+import qualified Dhall.Core+import qualified Dhall.Core                          as Dhall+    ( Expr+    , Var (V)+    , normalize+    )+import qualified Dhall.Core                          as Expr (Expr (..))+import qualified Dhall.Import                        as Dhall+import qualified Dhall.Map                           as Map+import qualified Dhall.Parser                        as Dhall+import qualified Dhall.Parser.Expression             as Parser.Expression+import qualified Dhall.Pretty+import qualified Dhall.Pretty.Internal+import qualified Dhall.Syntax                        as Syntax+import qualified Dhall.TypeCheck                     as Dhall+import qualified Dhall.Version                       as Meta+import qualified Prettyprinter                       as Pretty+import qualified Prettyprinter.Render.Terminal       as Pretty (renderIO)+import qualified System.Console.ANSI+import qualified System.Console.Haskeline.Completion as Haskeline+import qualified System.Console.Repline              as Repline+import qualified System.IO+import qualified Text.Megaparsec                     as Megaparsec++#if MIN_VERSION_haskeline(0,8,0)+import qualified Control.Monad.Catch+#else+import qualified System.Console.Haskeline.MonadException+#endif++type Repl = Repline.HaskelineT (State.StateT Env IO)++-- | Implementation of the @dhall repl@ subcommand+repl :: CharacterSet -> Bool -> IO ()+repl characterSet explain =+    if explain then Dhall.detailed io else io+  where+    io =+      evalStateT+        ( Repline.evalRepl+            banner+            ( dontCrash . eval )+            options+            ( Just optionsPrefix )+            ( Just "paste" )+            completer+            greeter+            finaliser+        )+        (emptyEnv { characterSet, explain })++    banner = pure . \case+      Repline.SingleLine -> turnstile <> " "+      Repline.MultiLine  -> "| "++    turnstile =+      case characterSet of+        Unicode -> "⊢"+        ASCII   -> "|-"++data Env = Env+  { envBindings      :: Dhall.Context.Context Binding+  , envIt            :: Maybe Binding+  , explain          :: Bool+  , characterSet     :: CharacterSet+  , outputHandle     :: Maybe System.IO.Handle+  }+++emptyEnv :: Env+emptyEnv =+  Env+    { envBindings = Dhall.Context.empty+    , envIt = Nothing+    , explain = False+    , characterSet = Unicode+    , outputHandle = Just System.IO.stdout+    }+++data Binding = Binding+  { bindingExpr :: Dhall.Expr Dhall.Src Void+  , bindingType :: Dhall.Expr Dhall.Src Void+  }+++envToContext :: Env -> Dhall.Context.Context Binding+envToContext Env{ envBindings, envIt } =+  case envIt of+    Nothing ->+      envBindings++    Just it ->+      Dhall.Context.insert "it" it envBindings+++parseAndLoad+  :: MonadIO m => String -> m ( Dhall.Expr Dhall.Src Void) +parseAndLoad src = do+  parsed <-+    case Dhall.exprFromText "(input)" (Text.pack src <> "\n") of+      Left e ->+        liftIO ( throwIO e )++      Right a ->+        return a++  let status = Dhall.emptyStatus "."++  liftIO ( State.evalStateT (Dhall.loadWith parsed) status )+++eval :: ( MonadIO m, MonadState Env m ) => String -> m ()+eval src = do+  loaded <-+    parseAndLoad src++  exprType <-+    typeCheck loaded++  expr <-+    normalize loaded++  modify ( \e -> e { envIt = Just ( Binding expr exprType ) } )++  output expr++++typeOf :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+typeOf src = do+  loaded <-+    parseAndLoad src++  exprType <-+    typeCheck loaded++  output exprType+++applyContext+    :: Context Binding+    -> Dhall.Expr Dhall.Src Void+    -> Dhall.Expr Dhall.Src Void+applyContext context expression =+    Dhall.Core.wrapInLets bindings expression+  where+    definitions = reverse $ Dhall.Context.toList context++    convertBinding (variable, Binding expr _) =+        Dhall.Core.Binding Nothing variable Nothing Nothing Nothing expr++    bindings = fmap convertBinding definitions++normalize+  :: MonadState Env m+  => Dhall.Expr Dhall.Src Void -> m ( Dhall.Expr t Void )+normalize e = do+  env <- get++  return (Dhall.normalize (applyContext (envToContext env) e))+++typeCheck+  :: ( MonadIO m, MonadState Env m )+  => Dhall.Expr Dhall.Src Void -> m ( Dhall.Expr Dhall.Src Void )+typeCheck expression = do+  env <- get++  let wrap = if explain env then Dhall.detailed else id++  case Dhall.typeOf (applyContext (envToContext env) expression) of+    Left  e -> liftIO ( wrap (throwIO e) )+    Right a -> return a++-- Split on the first '=' if there is any+parseAssignment :: String -> Either String (String, String)+parseAssignment str+  | (var, '=' : expr) <- break (== '=') str+  = Right (trim var, expr)+  | otherwise+  = Left (trim str)++addBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+addBinding string = do+  let parseBinding =+          Parser.Expression.letBinding+              (Parser.Expression.parsers+                  (Megaparsec.try Parser.Expression.import_)+              )++  let input = "let " <> Text.pack string++  Syntax.Binding{ variable, annotation, value } <- case Megaparsec.parse (unParser parseBinding) "(input)" input of+      Left  _       -> Fail.fail ":let should be of the form `:let x [: T] = y`"+      Right binding -> return binding++  (resolved, bindingType) <- case annotation of+      Just (_, unresolvedType) -> do+          let annotated = Syntax.Annot value unresolvedType++          resolved <- liftIO (Dhall.load annotated)++          _ <- typeCheck resolved++          bindingType <- liftIO (Dhall.load unresolvedType)++          return (resolved, bindingType)+      _ -> do+          resolved <- liftIO (Dhall.load value)++          bindingType <- typeCheck resolved++          return (resolved, bindingType)++  bindingExpr <- normalize resolved++  modify+    ( \e ->+        e { envBindings =+              Dhall.Context.insert+                variable+                Binding{ bindingType, bindingExpr }+                ( envBindings e )+          }+    )++  output (Expr.Annot (Expr.Var (Dhall.V variable 0)) bindingType)++clearBindings :: (MonadFail m, MonadState Env m) => String -> m ()+clearBindings _ = modify adapt+  where+    adapt (Env {..}) = Env { envBindings = Dhall.Context.empty, ..}++hashBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+hashBinding src = do+  loadedExpression <- parseAndLoad src++  _ <- typeCheck loadedExpression++  normalizedExpression <- normalize loadedExpression++  writeOutputHandle+    (hashExpressionToCode (Dhall.Core.alphaNormalize normalizedExpression))++saveFilePrefix :: FilePath+saveFilePrefix = ".dhall-repl"++-- | Find the index for the current _active_ dhall save file+currentSaveFileIndex :: MonadIO m => m (Maybe Int)+currentSaveFileIndex = do+  files <- liftIO $ getDirectoryContents "."++  let parseIndex file+        | saveFilePrefix `isPrefixOf` file+        , '-':index <- drop (length saveFilePrefix) file+        , [(x, "")] <- reads index -- safe version of read+        = Just x++        | otherwise+        = Nothing++  pure $ case mapMaybe parseIndex files of+    [] -> Nothing+    xs -> Just $ maximum xs++-- | Find the name for the current _active_ dhall save file+currentSaveFile :: MonadIO m => m (Maybe FilePath)+currentSaveFile =+  (fmap . fmap) (\i -> saveFilePrefix <> "-" <> show i) currentSaveFileIndex++-- | Find the name for the next dhall save file+nextSaveFile :: MonadIO m => m FilePath+nextSaveFile = do+  mIndex <- currentSaveFileIndex++  let nextIndex = maybe 0 succ mIndex++  pure $ saveFilePrefix <> "-" <> show nextIndex++loadBinding :: String -> Repl ()+loadBinding "" = do+  mFile <- currentSaveFile++  case mFile of+    Just file -> loadBinding file+    Nothing   ->+      Fail.fail $ ":load couldn't find any `" <> saveFilePrefix <> "-*` files"++loadBinding file = do+  -- Read commands from the save file+  -- Some commands can span multiple lines, only the first line will start with+  -- the optionsPrefix+  loadedLines <- lines <$> liftIO (readFile file)++  let -- Group lines that belong to the same command+      commands = flip groupBy loadedLines $ \_prev next ->+        not $ [optionsPrefix] `isPrefixOf` next++      runCommand line@(words -> (c:cmd):_)+        | c == optionsPrefix+        = case lookup cmd options of+            Just action -> action (drop (1 + length cmd + 1) line)+            Nothing -> Fail.fail $+              ":load unexpected command `" <> cmd <> "` in file `" <> file <> "`"+      runCommand _ = Fail.fail $+        ":load expects `" <> file <> "` to contain a command"++  -- Keep current handle in scope+  Env { outputHandle } <- get++  -- Discard output+  modify (\e -> e { outputHandle = Nothing })++  -- Run all the commands+  forM_ commands (runCommand . unlines)++  -- Restore the previous handle+  modify (\e -> e { outputHandle = outputHandle })++  writeOutputHandle $ "Loaded `" <> Text.pack file <> "`\n"++saveBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => Either String (String, String) -> m ()+-- Save all the bindings into a context save file+saveBinding (Left "") = do+  file <- nextSaveFile++  saveBinding (Left file)++-- Save all the bindings into `file`+saveBinding (Left file) = do+  env <- get++  let bindings+        = reverse+        . (fmap . fmap) bindingExpr+        . Dhall.Context.toList+        $ envBindings env++      handler handle =+          State.evalStateT+            (forM_ bindings $ \(name, expr) -> do+              let doc = Dhall.Pretty.Internal.prettyLabel name++              let label = Dhall.Pretty.Internal.docToStrictText doc++              liftIO (System.IO.hPutStr handle $ ":let " <> Text.unpack label <> " = ")+              outputWithoutSpacing expr)+            (env { outputHandle = Just handle })++  liftIO (System.IO.withFile file System.IO.WriteMode handler)++  writeOutputHandle $ "Context saved to `" <> Text.pack file <> "`\n"++-- Save a single expression to `file`+saveBinding (Right (file, src)) = do+  loadedExpression <- parseAndLoad src++  _ <- typeCheck loadedExpression++  normalizedExpression <- normalize loadedExpression++  env <- get++  let handler handle =+          State.evalStateT+            (output normalizedExpression)+            (env { outputHandle = Just handle })++  liftIO (System.IO.withFile file System.IO.WriteMode handler)++  writeOutputHandle $ "Expression saved to `" <> Text.pack file <> "`\n"++setOption :: ( MonadIO m, MonadState Env m ) => String -> m ()+setOption "--explain" =+  modify (\e -> e { explain = True })+setOption _ =+  writeOutputHandle ":set should be of the form `:set <command line option>`"++unsetOption :: ( MonadIO m, MonadState Env m ) => String -> m ()+unsetOption "--explain" =+  modify (\e -> e { explain = False })+unsetOption _ =+  writeOutputHandle ":unset should be of the form `:unset <command line option>`"++quitMessage :: String+quitMessage = "Goodbye."++cmdQuit :: ( MonadIO m, MonadState Env m ) => String -> m ()+cmdQuit _ = do+  liftIO (putStrLn quitMessage)+  liftIO (throwIO Interrupt)++help+  :: ( MonadFail m, MonadIO m, MonadState Env m )+  => HelpOptions m -> String -> m ()+help hs _ = do+  liftIO (putStrLn "Type any expression to normalize it or use one of the following commands:")+  forM_ hs $ \h -> do+    let name = helpOptionName h+        syntax = helpOptionSyntax h+        doc = helpOptionDoc h+    liftIO (putStrLn (":" <> name <> " " <> syntax))+    liftIO (putStrLn ("    " <> doc))++optionsPrefix :: Char+optionsPrefix = ':'++trim :: String -> String+trim = dropWhile isSpace . dropWhileEnd isSpace++data HelpOption m = HelpOption+  { helpOptionName :: String+  , helpOptionSyntax :: String+  , helpOptionDoc :: String+  , helpOptionFunction :: Repline.Cmd m+  }++type HelpOptions m = [HelpOption m]++helpOptions :: HelpOptions Repl+helpOptions =+  [ HelpOption+      "help"+      ""+      "Print help text and describe options"+      (dontCrash . help helpOptions)+  , HelpOption+      "paste"+      ""+      "Start a multi-line input. Submit with <Ctrl-D>"+      (error "Dhall.Repl.helpOptions: Unreachable")+  , HelpOption+      "type"+      "EXPRESSION"+      "Infer the type of an expression"+      (dontCrash . typeOf)+  , HelpOption+      "hash"+      "EXPRESSION"+      "Hash the normalized value of an expression"+      (dontCrash . hashBinding)+  , HelpOption+      "let"+      "IDENTIFIER = EXPRESSION"+      "Assign an expression to a variable"+      (dontCrash . addBinding)+  , HelpOption+      "clear"+      ""+      "Clear all bound variables"+      (dontCrash . clearBindings)+  , HelpOption+      "load"+      "[FILENAME]"+      "Load bound variables from a file"+      (dontCrash . loadBinding . trim)+  , HelpOption+      "save"+      "[FILENAME | FILENAME = EXPRESSION]"+      "Save bound variables or a given expression to a file"+      (dontCrash . saveBinding . parseAssignment)+  , HelpOption+      "set"+      "OPTION"+      "Set an option. Currently supported: --explain"+      (dontCrash . setOption . trim)+  , HelpOption+      "unset"+      "OPTION"+      "Unset an option"+      (dontCrash . unsetOption . trim)+  , HelpOption+      "quit"+      ""+      "Exit the REPL"+      cmdQuit+  ]++options :: Repline.Options Repl+options = (\h -> (helpOptionName h, helpOptionFunction h)) <$> helpOptions++completer+  :: (Monad m, MonadFail m, MonadIO m, MonadState Env m)+  => Repline.CompleterStyle m+completer =+  Repline.Prefix+    (Haskeline.completeWordWithPrev (Just '\\') separators completeFunc)+    []+  where+    -- Separators that can be found on the left of something we want to+    -- autocomplete+    separators :: String+    separators = " \t[(,=+*&|}#?>:"++completeFunc+  :: (Monad m, MonadFail m, MonadIO m, MonadState Env m)+  => String -> String -> m [Completion]+completeFunc reversedPrev word++  -- Complete commands+  | reversedPrev == ":"+  = pure . listCompletion $ fst <$> (options :: Repline.Options Repl)++  -- Complete load command+  | reversedPrev == reverse ":load "+  = Haskeline.listFiles word++  -- Complete file paths+  | any (`isPrefixOf` word) [ "/", "./", "../", "~/" ]+  = Haskeline.listFiles word++  -- Complete environment variables+  | reverse "env:" `isPrefixOf` reversedPrev+  = listCompletion . fmap fst <$> liftIO getEnvironment++  -- Complete record fields and union alternatives+  | var : subFields <- Text.split (== '.') (Text.pack word)+  , not $ null subFields+  = do+    Env { envBindings } <- get++    case Dhall.Context.lookup var 0 envBindings of++      Nothing -> pure []++      Just binding -> do+        let candidates = algebraicComplete subFields (bindingExpr binding)+        pure $ listCompletion (Text.unpack . (var <>) <$> candidates)++  -- Complete variables in scope and all reserved identifiers+  | otherwise+  = do+    Env { envBindings } <- get++    let vars     = map fst $ Dhall.Context.toList envBindings+        reserved = Data.HashSet.toList Dhall.Core.reservedIdentifiers++    pure . listCompletion . map Text.unpack . nub $ vars ++ reserved++  where+    listCompletion = map simpleCompletion . filter (word `isPrefixOf`)++    algebraicComplete+        :: [Text.Text] -> Dhall.Expr Dhall.Src Void -> [Text.Text]+    algebraicComplete subFields expr =+      let keys = fmap ("." <>) . Map.keys++          withMap m =+              case subFields of+                  [] -> keys m+                  -- Stop on last subField (we care about the keys at this level)+                  [_] -> keys m+                  f:fs ->+                      case Map.lookup f m of+                          Nothing ->+                              []+                          Just Nothing ->+                              keys m+                          Just (Just e) ->+                              fmap (("." <> f) <>) (algebraicComplete fs e)++      in  case expr of+            Dhall.Core.RecordLit    m -> withMap (fmap (Just . Dhall.Core.recordFieldValue) m)+            Dhall.Core.Union        m -> withMap m+            _                         -> []+++greeter :: MonadIO m => m ()+greeter =+  let version = Meta.dhallVersionString+      message = "Welcome to the Dhall v" <> version <> " REPL! Type :help for more information."+  in liftIO (putStrLn message)++finaliser :: MonadIO m => m Repline.ExitDecision+finaliser = do+  liftIO (putStrLn quitMessage)+  pure Repline.Exit++dontCrash :: Repl () -> Repl ()+dontCrash m =+#if MIN_VERSION_haskeline(0,8,0)+  Control.Monad.Catch.catch+#else+  System.Console.Haskeline.MonadException.catch+#endif+    m+    ( \ e@SomeException{} -> liftIO ( putStrLn ( displayException e ) ) )++writeOutputHandle :: (MonadIO m, MonadState Env m) => Text -> m ()+writeOutputHandle txt = do+  Env { outputHandle } <- get++  case outputHandle of+    Just handle -> liftIO $ Text.IO.hPutStrLn handle txt+    Nothing     -> pure ()++output+  :: (Pretty.Pretty a, MonadState Env m, MonadIO m)+  => Dhall.Expr Src a -> m ()+output expr = do+  writeOutputHandle "" -- Visual spacing++  outputWithoutSpacing expr++  writeOutputHandle "" -- Visual spacing++outputWithoutSpacing+  :: (Pretty.Pretty a, MonadState Env m, MonadIO m)+  => Dhall.Expr Src a -> m ()+outputWithoutSpacing expr = do+  Env { characterSet, outputHandle } <- get++  case outputHandle of+    Nothing     -> pure ()+    Just handle -> do+      let stream = Dhall.Pretty.layout (Dhall.Pretty.prettyCharacterSet characterSet expr)++      supportsANSI <- liftIO (System.Console.ANSI.hSupportsANSI handle)+      let ansiStream =+              if supportsANSI+              then fmap Dhall.Pretty.annToAnsiStyle stream+              else Pretty.unAnnotateS stream++      liftIO (Pretty.renderIO handle ansiStream)+      liftIO (System.IO.hPutStrLn handle "") -- Pretty printing doesn't end with a new line
+ src/Dhall/Schemas.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++{-| This module contains the implementation of the @dhall rewrite-with-schemas@+    subcommand+-}++module Dhall.Schemas+    ( -- | Schemas+      schemasCommand+    , Schemas(..)+    , rewriteWithSchemas+    , SchemasError(..)+    ) where++import Control.Applicative (empty)+import Control.Exception   (Exception)+import Data.Maybe          (fromMaybe)+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Crypto        (SHA256Digest)+import Dhall.Map           (Map)+import Dhall.Pretty        (CharacterSet (..), detectCharacterSet)+import Dhall.Src           (Src)+import Dhall.Syntax        (Expr (..), Import, Var (..))+import Dhall.Util+    ( Censor (..)+    , Header (..)+    , Input (..)+    , MultipleCheckFailed (..)+    , OutputMode (..)+    )++import qualified Control.Exception                  as Exception+import qualified Data.Map+import qualified Data.Maybe                         as Maybe+import qualified Data.Text.IO                       as Text.IO+import qualified Data.Void                          as Void+import qualified Dhall.Core                         as Core+import qualified Dhall.Import                       as Import+import qualified Dhall.Map                          as Map+import qualified Dhall.Normalize                    as Normalize+import qualified Dhall.Parser                       as Parser+import qualified Dhall.Pretty+import qualified Dhall.Substitution                 as Substitution+import qualified Dhall.Syntax                       as Syntax+import qualified Dhall.TypeCheck                    as TypeCheck+import qualified Dhall.Util                         as Util+import qualified Lens.Micro                         as Lens+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty.Terminal+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite+import qualified System.Console.ANSI                as ANSI+import qualified System.IO                          as IO++-- | Arguments to the @rewrite-with-schemas@ subcommand+data Schemas = Schemas+    { chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor+    , input              :: Input+    , outputMode         :: OutputMode+    , schemas            :: Text+    }++-- | Implementation of the @dhall rewrite-with-schemas@ subcommand+schemasCommand :: Schemas -> IO ()+schemasCommand Schemas{..} = do+    (inputName, originalText) <- case input of+        InputFile file -> (,) file <$> Text.IO.readFile file+        StandardInput  -> (,) "(input)" <$> Text.IO.getContents++    (Header header, expression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText++    let characterSet = fromMaybe (detectCharacterSet expression) chosenCharacterSet++    schemasRecord <- Core.throws (Parser.exprFromText "(schemas)" schemas)++    schemasExpression <- rewriteWithSchemas schemasRecord expression++    let docStream =+            Dhall.Pretty.layout+                (   Pretty.pretty header+                <>  Dhall.Pretty.prettyCharacterSet characterSet schemasExpression+                <>  "\n"+                )++    let schemasText = Pretty.Text.renderStrict docStream++    case outputMode of+        Write ->+            case input of+                InputFile file ->+                    if originalText == schemasText+                        then return ()+                        else AtomicWrite.atomicWriteFile+                                file+                                (Pretty.Text.renderLazy docStream)+                StandardInput -> do+                    supportsANSI <- ANSI.hSupportsANSI IO.stdout++                    Pretty.Terminal.renderIO+                        IO.stdout+                        (if supportsANSI+                            then fmap Dhall.Pretty.annToAnsiStyle docStream+                            else Pretty.unAnnotateS docStream)++        Check ->+            if originalText == schemasText+                then return ()+                else do+                    let command = "rewrite-with-schemas"++                    let modified = "rewritten"++                    let inputs = pure input++                    Exception.throwIO MultipleCheckFailed{..}++decodeSchema :: Expr s Void -> Maybe (Expr s Void, Map Text (Expr s Void))+decodeSchema (RecordLit m)+        | Just  _Type               <- Core.recordFieldValue <$> Map.lookup "Type" m+        , Just (RecordLit _default) <- Core.recordFieldValue <$> Map.lookup "default" m =+            Just (_Type, Core.recordFieldValue <$> _default)+decodeSchema _ =+    Nothing++decodeSchemas+    :: Expr s Void+    -> Maybe (Data.Map.Map SHA256Digest (Text, Map Text (Expr s Void)))+decodeSchemas (RecordLit keyValues) = do+    m <- traverse (decodeSchema . Core.recordFieldValue) keyValues++    let typeMetadata = Data.Map.fromList $ do+            (name, (_Type, _default)) <- Map.toList m++            return (Import.hashExpression (Syntax.denote _Type), (name, _default))++    return typeMetadata+decodeSchemas  _ =+    empty++-- | Simplify a Dhall expression using a record of schemas+rewriteWithSchemas+    :: Expr Src Import+    -- ^ Record of schemas+    -> Expr Src Import+    -- ^ Expression to simplify using the supplied schemas+    -> IO (Expr Src Import)+rewriteWithSchemas _schemas expression = do+    resolvedSchemas    <- Import.load _schemas+    resolvedExpression <- Import.load expression++    _ <- Core.throws (TypeCheck.typeOf resolvedSchemas)+    _ <- Core.throws (TypeCheck.typeOf resolvedExpression)++    let normalizedSchemas    = Normalize.normalize resolvedSchemas+    let normalizedExpression = Normalize.normalize resolvedExpression++    typeMetadata <- case decodeSchemas normalizedSchemas of+        Just typeMetadata -> return typeMetadata+        Nothing           -> Exception.throwIO NotASchemaRecord++    let schemasRewrite subExpression@(RecordLit keyValues) =+            Maybe.fromMaybe subExpression $ do+                let substitutions = Map.singleton "schemas" normalizedSchemas++                let substitutedExpression =+                        Substitution.substitute subExpression substitutions++                hash <- case TypeCheck.typeOf substitutedExpression of+                    Left _ ->+                        empty+                    Right subExpressionType ->+                        return (Import.hashExpression (Syntax.denote subExpressionType))++                (name, _default) <- Data.Map.lookup hash typeMetadata++                let diff a b | a == b    = Nothing+                             | otherwise = Just a++                let defaultedKeyValues =+                        Core.makeRecordField <$>+                        Map.fromMap (+                            Data.Map.differenceWith diff+                                (Map.toMap $ Core.recordFieldValue <$> keyValues)+                                (Map.toMap _default))++                let defaultedRecord = RecordLit defaultedKeyValues++                return (RecordCompletion (Field "schemas" $ Core.makeFieldSelection name) defaultedRecord)+        schemasRewrite subExpression =+            subExpression++    let rewrittenExpression :: Expr Src Import+        rewrittenExpression =+            fmap Void.absurd (Lens.transformOf Syntax.subExpressions schemasRewrite normalizedExpression)++    if Normalize.freeIn (V "schemas" 0) rewrittenExpression+        then return (Let (Syntax.makeBinding "schemas" _schemas) rewrittenExpression)+        else return expression++-- | Errors that can be thrown by `rewriteWithSchemas`+data SchemasError = NotASchemaRecord+    deriving (Exception)++instance Show SchemasError where+    show NotASchemaRecord =+        Util._ERROR <> ": The --schemas argument is not a record of schemas"
+ src/Dhall/Set.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}++-- | This module only exports ways of constructing a Set,+-- retrieving List, Set, and Seq representations of the same data,+-- as well as a novel "difference" function.+-- Any other Set-like or List-like functionality+-- should be obtained through toSet and toList, respectively.+module Dhall.Set (+      Set(..)+    , toList+    , toAscList+    , toSet+    , toSeq+    , fromList+    , fromSet+    , append+    , empty+    , difference+    , sort+    , isSorted+    , null+    , size+    ) where++import Control.DeepSeq            (NFData)+import Data.Data                  (Data)+import Data.List                  (foldl')+import Data.Sequence              (Seq, (|>))+import GHC.Generics               (Generic)+import Instances.TH.Lift          ()+import Language.Haskell.TH.Syntax (Lift)+import Prelude                    hiding (null)++import qualified Data.Foldable+import qualified Data.Sequence+import qualified Data.Set++{-| This is a variation on @"Data.Set".`Data.Set.Set`@ that remembers the+    original order of elements.  This ensures that ordering is not lost when+    formatting Dhall code+-}+data Set a = Set (Data.Set.Set a) (Seq a)+    deriving (Generic, Show, Data, NFData, Lift)+-- Invariant: In @Set set seq@, @toAscList set == sort (toList seq)@.++instance Eq a => Eq (Set a) where+    (Set _ x) == (Set _ y) = x == y+    {-# INLINABLE (==) #-}++instance Ord a => Ord (Set a) where+    compare (Set _ x) (Set _ y) = compare x y+    {-# INLINABLE compare #-}++instance Foldable Set where+    foldMap f (Set _ x) = foldMap f x+    {-# INLINABLE foldMap #-}++    toList = Dhall.Set.toList+    {-# INLINABLE toList #-}++    null = Dhall.Set.null+    {-# INLINABLE null #-}++    length = Dhall.Set.size+    {-# INLINABLE length #-}++-- | Convert to an unordered @"Data.Set".`Data.Set.Set`@+toSet :: Set a -> Data.Set.Set a+toSet (Set s _) = s++-- | Convert to an ordered `Seq`+toSeq :: Set a -> Seq a+toSeq (Set _ xs) = xs++{-| Convert a `Dhall.Set.Set` to a list, preserving the original order of the+    elements+-}+toList :: Set a -> [a]+toList (Set _ xs) = Data.Foldable.toList xs++-- | Convert a `Dhall.Set.Set` to a list of ascending elements+toAscList :: Set a -> [a]+toAscList (Set s _) = Data.Set.toAscList s++-- | Convert a list to a `Dhall.Set.Set`, remembering the element order+fromList :: Ord a => [a] -> Set a+fromList = foldl' (flip append) empty+-- O(n log n) time complexity, O(n) space complexity.+-- Implementing it this way is a little silly, but is faster than (nub xs).+-- n.b. toList . fromList = id, only if the list elements are unique++-- | Convert a @"Data.Set".`Data.Set.Set`@ to a sorted `Dhall.Set.Set`+fromSet :: Data.Set.Set a -> Set a+fromSet s = Set s (Data.Sequence.fromList (Data.Set.elems s))++-- | Append an element to the end of a `Dhall.Set.Set`+append :: Ord a => a -> Set a -> Set a+append x os@(Set s xs)+    | Data.Set.member x s = os+    | otherwise = Set (Data.Set.insert x s) (xs |> x)+-- O(log n) time complexity.++-- | The empty `Dhall.Set.Set`+empty :: Set a+empty = Set Data.Set.empty Data.Sequence.empty++-- | Returns, in order, all elements of the first Set not present in the second.+-- (It doesn't matter in what order the elements appear in the second Set.)+difference :: Ord a => Set a -> Set a -> [a]+difference os (Set s _) =+    filter (\ x -> not (Data.Set.member x s)) (toList os)++{-| Sort the set elements, forgetting their original ordering.++>>> sort (fromList [2, 1]) == fromList [1, 2]+True+-}+sort :: Ord a => Set a -> Set a+sort (Set s _) = Set s (Data.Sequence.fromList (Data.Set.toList s))++{-|+>>> isSorted (fromList [2, 1])+False+>>> isSorted (fromList [1, 2])+True+-}+isSorted :: Ord a => Set a -> Bool+isSorted s = toList s == Data.Set.toList (toSet s)++{-|+>>> null (fromList [1])+False+>>> null (fromList [])+True+-}+null :: Set a -> Bool+null (Set s _) = Data.Set.null s++{-|+>>> size (fromList [1])+1+-}+size :: Set a -> Int+size (Set s _) = Data.Set.size s
+ src/Dhall/Src.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE TemplateHaskell    #-}++-- | This module provides the `Src` type used for source spans in error messages++module Dhall.Src+    ( -- * Type+      Src(..)+    ) where++import Control.DeepSeq            (NFData)+import Data.Data                  (Data)+import Data.Text                  (Text)+import GHC.Generics               (Generic)+import Instances.TH.Lift          ()+import Language.Haskell.TH.Syntax (Lift (..))+import Prettyprinter              (Pretty (..))+import Text.Megaparsec            (SourcePos (SourcePos), mkPos, unPos)++import {-# SOURCE #-} qualified Dhall.Util++import qualified Data.Text       as Text+import qualified Text.Megaparsec as Megaparsec+import qualified Text.Printf     as Printf++-- | Source code extract+data Src = Src+    { srcStart :: !SourcePos+    , srcEnd   :: !SourcePos+    , srcText  :: Text -- Text field is intentionally lazy+    } deriving (Data, Eq, Generic, Ord, Show, NFData)+++instance Lift Src where+#if MIN_VERSION_template_haskell(2,16,0)+    liftTyped (Src (SourcePos a b c) (SourcePos d e f) g) =+        [|| Src (SourcePos a (mkPos b') (mkPos c')) (SourcePos d (mkPos e') (mkPos f')) g ||]+#else+    lift (Src (SourcePos a b c) (SourcePos d e f) g) =+        [| Src (SourcePos a (mkPos b') (mkPos c')) (SourcePos d (mkPos e') (mkPos f')) g |]+#endif+      where+        b' = unPos b+        c' = unPos c+        e' = unPos e+        f' = unPos f+++instance Pretty Src where+    pretty (Src begin _ text) =+            pretty (Dhall.Util.snip numberedLines)+        <>  "\n"+        <>  pretty (Megaparsec.sourcePosPretty begin)+      where+        prefix = Text.replicate (n - 1) " "+          where+            n = Megaparsec.unPos (Megaparsec.sourceColumn begin)++        ls = Text.lines (prefix <> text)++        numberOfLines = length ls++        minimumNumber =+            Megaparsec.unPos (Megaparsec.sourceLine begin)++        maximumNumber = minimumNumber + numberOfLines - 1++        numberWidth :: Int+        numberWidth =+            truncate (logBase (10 :: Double) (fromIntegral maximumNumber)) + 1++        adapt n line = Text.pack outputString+          where+            inputString = Text.unpack line++            outputString =+                Printf.printf ("%" <> show numberWidth <> "d│ %s") n inputString++        numberedLines = Text.unlines (zipWith adapt [minimumNumber..] ls)
+ src/Dhall/Substitution.hs view
@@ -0,0 +1,34 @@+{- | This module provides types and functions used in the substitution step+     which is done before type checking and normalization.+-}++module Dhall.Substitution where++import Data.Text       (Text)+import Dhall.Normalize (subst)+import Dhall.Syntax    (Expr, Var (..))++import qualified Dhall.Map++{- | Substitutions map variables to arbitrary Dhall expressions.+     Note that we use "Dhall.Map.Map" as an underlying structure. Hence we respect insertion order.+-}+type Substitutions s a = Dhall.Map.Map Text (Expr s a)++{- | An empty substitution map.+-}+empty :: Substitutions s a+empty = Dhall.Map.empty++-- | @substitute expr s@ replaces all variables in @expr@ (or its subexpression) with their substitute.+--   For example, if the substitution map maps the variable @Foo@ to the text \"Foo\" all occurrences of @Foo@ with the text \"Foo\".+--+--   The substitutions will be done in the order they are inserted into the substitution map:+--+--   > {-# LANGUAGE OverloadedStrings #-}+--   >+--   > substitute (Dhall.Core.Var "Foo") (Dhall.Map.fromList [("Foo", Dhall.Core.Var "Bar"), ("Bar", Dhall.Core.Var "Baz")])+--+--   results in @Dhall.Core.Var \"Baz\"@ since we first substitute \"Foo\" with \"Bar\" and then the resulting \"Bar\" with the final \"Baz\".+substitute :: Expr s a -> Substitutions s a -> Expr s a+substitute expr = foldl (\memo (k, v) -> subst (V k 0) v memo) expr . Dhall.Map.toList
+ src/Dhall/Syntax.hs view
@@ -0,0 +1,31 @@+module Dhall.Syntax+    ( module Export+    ) where++import {-# SOURCE #-} Dhall.Pretty.Internal              as Export+    ( CharacterSet (..)+    )+import                Dhall.Syntax.Binding               as Export+import                Dhall.Syntax.Chunks                as Export+import                Dhall.Syntax.Const                 as Export+import                Dhall.Syntax.Expr                  as Export+import                Dhall.Syntax.FunctionBinding       as Export+import                Dhall.Syntax.Import                as Export+import                Dhall.Syntax.Instances.Applicative as Export ()+import                Dhall.Syntax.Instances.Bifunctor   as Export ()+import                Dhall.Syntax.Instances.Data        as Export ()+import                Dhall.Syntax.Instances.Eq          as Export ()+import                Dhall.Syntax.Instances.Foldable    as Export ()+import                Dhall.Syntax.Instances.Functor     as Export ()+import                Dhall.Syntax.Instances.Lift        as Export ()+import                Dhall.Syntax.Instances.Monad       as Export ()+import                Dhall.Syntax.Instances.NFData      as Export ()+import                Dhall.Syntax.Instances.Ord         as Export ()+import                Dhall.Syntax.Instances.Pretty      as Export+import                Dhall.Syntax.Instances.Show        as Export ()+import                Dhall.Syntax.Instances.Traversable as Export ()+import                Dhall.Syntax.MultiLet              as Export+import                Dhall.Syntax.Operations            as Export+import                Dhall.Syntax.RecordField           as Export+import                Dhall.Syntax.Types                 as Export+import                Dhall.Syntax.Var                   as Export
+ src/Dhall/Syntax/Binding.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Binding+    ( Binding(..)+    , makeBinding++      -- * Optics+    , bindingExprs+    ) where++import                Data.Text         (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the binding part of a @let@ expression.+--+-- For example,+--+-- > let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x+--+-- … will be instantiated as follows:+--+-- * @bindingSrc0@ corresponds to the @A@ comment.+-- * @variable@ is @"x"@+-- * @bindingSrc1@ corresponds to the @B@ comment.+-- * @annotation@ is 'Just' a pair, corresponding to the @C@ comment and @Bool@.+-- * @bindingSrc2@ corresponds to the @D@ comment.+-- * @value@ corresponds to @True@.+data Binding s a = Binding+    { bindingSrc0 :: Maybe s+    , variable    :: Text+    , bindingSrc1 :: Maybe s+    , annotation  :: Maybe (Maybe s, Expr s a)+    , bindingSrc2 :: Maybe s+    , value       :: Expr s a+    } deriving Generic++{-| Construct a 'Binding' with no source information and no type annotation.+-}+makeBinding :: Text -> Expr s a -> Binding s a+makeBinding name = Binding Nothing name Nothing Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'Binding'.+-}+bindingExprs+  :: (Applicative f)+  => (Expr s a -> f (Expr s b))+  -> Binding s a -> f (Binding s b)+bindingExprs f (Binding s0 n s1 t s2 v) =+  Binding+    <$> pure s0+    <*> pure n+    <*> pure s1+    <*> traverse (traverse f) t+    <*> pure s2+    <*> f v+{-# INLINABLE bindingExprs #-}
+ src/Dhall/Syntax/Chunks.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Syntax.Chunks+    ( Chunks(..)++      -- * Optics+    , chunkExprs++      -- * `Data.Text.Text` manipulation+    , toDoubleQuoted+    , longestSharedWhitespacePrefix+    , linesLiteral+    , unlinesLiteral+    ) where++import                Data.List.NonEmpty (NonEmpty (..))+import                Data.String        (IsString (..))+import                Data.Text          (Text)+import                Dhall.Src          (Src)+import {-# SOURCE #-} Dhall.Syntax.Expr  (Expr)+import                GHC.Generics       (Generic)++import qualified Data.Foldable+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text++-- | The body of an interpolated @Text@ literal+data Chunks s a = Chunks [(Text, Expr s a)] Text+    deriving Generic++instance IsString (Chunks s a) where+    fromString str = Chunks [] (fromString str)++instance Semigroup (Chunks s a) where+    Chunks xysL zL <> Chunks         []    zR =+        Chunks xysL (zL <> zR)+    Chunks xysL zL <> Chunks ((x, y):xysR) zR =+        Chunks (xysL ++ (zL <> x, y):xysR) zR++instance Monoid (Chunks s a) where+    mempty = Chunks [] mempty++-- | A traversal over the immediate sub-expressions in 'Chunks'.+chunkExprs+  :: Applicative f+  => (Expr s a -> f (Expr t b))+  -> Chunks s a -> f (Chunks t b)+chunkExprs f (Chunks chunks final) =+  flip Chunks final <$> traverse (traverse f) chunks+{-# INLINABLE chunkExprs #-}++-- | Same as @Data.Text.splitOn@, except always returning a `NonEmpty` result+splitOn :: Text -> Text -> NonEmpty Text+splitOn needle haystack =+    case Data.Text.splitOn needle haystack of+        []     -> "" :| []+        t : ts -> t  :| ts++-- | Split `Chunks` by lines+linesLiteral :: Chunks s a -> NonEmpty (Chunks s a)+linesLiteral (Chunks [] suffix) =+    fmap (Chunks []) (splitOn "\n" suffix)+linesLiteral (Chunks ((prefix, interpolation) : pairs₀) suffix₀) =+    foldr+        NonEmpty.cons+        (Chunks ((lastLine, interpolation) : pairs₁) suffix₁ :| chunks)+        (fmap (Chunks []) initLines)+  where+    splitLines = splitOn "\n" prefix++    initLines = NonEmpty.init splitLines+    lastLine  = NonEmpty.last splitLines++    Chunks pairs₁ suffix₁ :| chunks = linesLiteral (Chunks pairs₀ suffix₀)++-- | Flatten several `Chunks` back into a single `Chunks` by inserting newlines+unlinesLiteral :: NonEmpty (Chunks s a) -> Chunks s a+unlinesLiteral chunks =+    Data.Foldable.fold (NonEmpty.intersperse "\n" chunks)++-- | Returns `True` if the `Chunks` represents a blank line+emptyLine :: Chunks s a -> Bool+emptyLine (Chunks [] ""  ) = True+emptyLine (Chunks [] "\r") = True  -- So that `\r\n` is treated as a blank line+emptyLine  _               = False++-- | Return the leading whitespace for a `Chunks` literal+leadingSpaces :: Chunks s a -> Text+leadingSpaces chunks = Data.Text.takeWhile isSpace firstText+  where+    isSpace c = c == ' ' || c == '\t'++    firstText =+        case chunks of+            Chunks                []  suffix -> suffix+            Chunks ((prefix, _) : _ ) _      -> prefix++{-| Compute the longest shared whitespace prefix for the purposes of stripping+    leading indentation+-}+longestSharedWhitespacePrefix :: NonEmpty (Chunks s a) -> Text+longestSharedWhitespacePrefix literals =+    case fmap leadingSpaces filteredLines of+        l : ls -> Data.Foldable.foldl' sharedPrefix l ls+        []     -> ""+  where+    sharedPrefix ab ac =+        case Data.Text.commonPrefixes ab ac of+            Just (a, _b, _c) -> a+            Nothing          -> ""++    -- The standard specifies to filter out blank lines for all lines *except*+    -- for the last line+    filteredLines = newInit <> pure oldLast+      where+        oldInit = NonEmpty.init literals++        oldLast = NonEmpty.last literals++        newInit = filter (not . emptyLine) oldInit++-- | Drop the first @n@ characters for a `Chunks` literal+dropLiteral :: Int -> Chunks s a -> Chunks s a+dropLiteral n (Chunks [] suffix) =+    Chunks [] (Data.Text.drop n suffix)+dropLiteral n (Chunks ((prefix, interpolation) : rest) suffix) =+    Chunks ((Data.Text.drop n prefix, interpolation) : rest) suffix++{-| Convert a single-quoted `Chunks` literal to the equivalent double-quoted+    `Chunks` literal+-}+toDoubleQuoted :: Chunks Src a -> Chunks Src a+toDoubleQuoted literal =+    unlinesLiteral (fmap (dropLiteral indent) literals)+  where+    literals = linesLiteral literal++    longestSharedPrefix = longestSharedWhitespacePrefix literals++    indent = Data.Text.length longestSharedPrefix
+ src/Dhall/Syntax/Chunks.hs-boot view
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Chunks where++import Data.Kind (Type)++type Chunks :: Type -> Type -> Type+data Chunks s a
+ src/Dhall/Syntax/Const.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Const+    ( Const(..)+    ) where++import GHC.Generics (Generic)++{-| Constants for a pure type system++    The axioms are:++> ⊦ Type : Kind+> ⊦ Kind : Sort++    ... and the valid rule pairs are:++> ⊦ Type ↝ Type : Type  -- Functions from terms to terms (ordinary functions)+> ⊦ Kind ↝ Type : Type  -- Functions from types to terms (type-polymorphic functions)+> ⊦ Sort ↝ Type : Type  -- Functions from kinds to terms+> ⊦ Kind ↝ Kind : Kind  -- Functions from types to types (type-level functions)+> ⊦ Sort ↝ Kind : Sort  -- Functions from kinds to types (kind-polymorphic functions)+> ⊦ Sort ↝ Sort : Sort  -- Functions from kinds to kinds (kind-level functions)++    Note that Dhall does not support functions from terms to types and therefore+    Dhall is not a dependently typed language+-}+data Const = Type | Kind | Sort+    deriving (Bounded, Enum, Generic)
+ src/Dhall/Syntax/Expr.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE DeriveGeneric            #-}+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr+    ( Expr(..)+    ) where++import                Data.ByteString              (ByteString)+import                Data.Kind                    (Type)+import                Data.List.NonEmpty           (NonEmpty (..))+import                Data.Sequence                (Seq)+import                Data.String                  (IsString (..))+import                Data.Text                    (Text)+import                Data.Traversable             ()+import                Dhall.Map                    (Map)+import {-# SOURCE #-} Dhall.Pretty.Internal        (CharacterSet (..))+import                Dhall.Syntax.Binding+import                Dhall.Syntax.Chunks+import                Dhall.Syntax.Const+import                Dhall.Syntax.FunctionBinding+import                Dhall.Syntax.RecordField+import                Dhall.Syntax.Types+import                Dhall.Syntax.Var+import                GHC.Generics                 (Generic)+import                Numeric.Natural              (Natural)++import qualified Data.Time as Time++{-| Syntax tree for expressions++    The @s@ type parameter is used to track the presence or absence of+    `Dhall.Src.Src` spans:++    * If @s = `Dhall.Src.Src`@ then the code may contains `Dhall.Src.Src` spans+      (either in a `Note` constructor or inline within another constructor, like+      `Let`)+    * If @s = `Data.Void.Void`@ then the code has no `Dhall.Src.Src` spans++    The @a@ type parameter is used to track the presence or absence of imports++    * If @a = `Dhall.Syntax.Import.Import`@ then the code may contain unresolved+      `Dhall.Syntax.Import.Import`s+    * If @a = `Data.Void.Void`@ then the code has no+      `Dhall.Syntax.Import.Import`s+-}+type Expr :: Type -> Type -> Type+data Expr s a+    -- | > Const c                                  ~  c+    = Const Const+    -- | > Var (V x 0)                              ~  x+    --   > Var (V x n)                              ~  x@n+    | Var Var+    -- | > Lam _ (FunctionBinding _ "x" _ _ A) b    ~  λ(x : A) -> b+    | Lam (Maybe CharacterSet) (FunctionBinding s a) (Expr s a)+    -- | > Pi _ "_" A B                               ~        A  -> B+    --   > Pi _ x   A B                               ~  ∀(x : A) -> B+    | Pi  (Maybe CharacterSet) Text (Expr s a) (Expr s a)+    -- | > App f a                                  ~  f a+    | App (Expr s a) (Expr s a)+    -- | > Let (Binding _ x _  Nothing  _ r) e      ~  let x     = r in e+    --   > Let (Binding _ x _ (Just t ) _ r) e      ~  let x : t = r in e+    --+    -- The difference between+    --+    -- > let x = a    let y = b in e+    --+    -- and+    --+    -- > let x = a in let y = b in e+    --+    -- is only an additional 'Note' around @'Let' "y" …@ in the second+    -- example.+    --+    -- See `Dhall.Syntax.MultiLet.MultiLet` for a representation of let-blocks+    -- that mirrors the source code more closely.+    | Let (Binding s a) (Expr s a)+    -- | > Annot x t                                ~  x : t+    | Annot (Expr s a) (Expr s a)+    -- | > Bool                                     ~  Bool+    | Bool+    -- | > BoolLit b                                ~  b+    | BoolLit Bool+    -- | > BoolAnd x y                              ~  x && y+    | BoolAnd (Expr s a) (Expr s a)+    -- | > BoolOr  x y                              ~  x || y+    | BoolOr  (Expr s a) (Expr s a)+    -- | > BoolEQ  x y                              ~  x == y+    | BoolEQ  (Expr s a) (Expr s a)+    -- | > BoolNE  x y                              ~  x != y+    | BoolNE  (Expr s a) (Expr s a)+    -- | > BoolIf x y z                             ~  if x then y else z+    | BoolIf (Expr s a) (Expr s a) (Expr s a)+    -- | > Bytes                                    ~ Bytes+    | Bytes+    -- | > BytesLit "\x00\xFF"                      ~ 0x"00FF"+    | BytesLit ByteString+    -- | > Natural                                  ~  Natural+    | Natural+    -- | > NaturalLit n                             ~  n+    | NaturalLit Natural+    -- | > NaturalFold                              ~  Natural/fold+    | NaturalFold+    -- | > NaturalBuild                             ~  Natural/build+    | NaturalBuild+    -- | > NaturalIsZero                            ~  Natural/isZero+    | NaturalIsZero+    -- | > NaturalEven                              ~  Natural/even+    | NaturalEven+    -- | > NaturalOdd                               ~  Natural/odd+    | NaturalOdd+    -- | > NaturalToInteger                         ~  Natural/toInteger+    | NaturalToInteger+    -- | > NaturalShow                              ~  Natural/show+    | NaturalShow+    -- | > NaturalSubtract                          ~  Natural/subtract+    | NaturalSubtract+    -- | > NaturalPlus x y                          ~  x + y+    | NaturalPlus (Expr s a) (Expr s a)+    -- | > NaturalTimes x y                         ~  x * y+    | NaturalTimes (Expr s a) (Expr s a)+    -- | > Integer                                  ~  Integer+    | Integer+    -- | > IntegerLit n                             ~  ±n+    | IntegerLit Integer+    -- | > IntegerClamp                             ~  Integer/clamp+    | IntegerClamp+    -- | > IntegerNegate                            ~  Integer/negate+    | IntegerNegate+    -- | > IntegerShow                              ~  Integer/show+    | IntegerShow+    -- | > IntegerToDouble                          ~  Integer/toDouble+    | IntegerToDouble+    -- | > Double                                   ~  Double+    | Double+    -- | > DoubleLit n                              ~  n+    | DoubleLit DhallDouble+    -- | > DoubleShow                               ~  Double/show+    | DoubleShow+    -- | > Text                                     ~  Text+    | Text+    -- | > TextLit (Chunks [(t1, e1), (t2, e2)] t3) ~  "t1${e1}t2${e2}t3"+    | TextLit (Chunks s a)+    -- | > TextAppend x y                           ~  x ++ y+    | TextAppend (Expr s a) (Expr s a)+    -- | > TextReplace                              ~ Text/replace+    | TextReplace+    -- | > TextShow                                 ~  Text/show+    | TextShow+    -- | > Date                                     ~  Date+    | Date+    -- | > DateLiteral (fromGregorian _YYYY _MM _DD) ~ YYYY-MM-DD+    | DateLiteral Time.Day+    -- | > DateShow                                 ~  Date/show+    | DateShow+    -- | > Time                                     ~  Time+    | Time+    -- | > TimeLiteral (TimeOfDay hh mm ss) _       ~  hh:mm:ss+    | TimeLiteral+        Time.TimeOfDay+        Word+        -- ^ Precision+    -- | > TimeShow                                 ~  Time/show+    | TimeShow+    -- | > TimeZone                                 ~  TimeZone+    | TimeZone+    -- | > TimeZoneLiteral (TimeZone ( 60 * _HH + _MM) _ _) ~ +HH:MM+    -- | > TimeZoneLiteral (TimeZone (-60 * _HH + _MM) _ _) ~ -HH:MM+    | TimeZoneLiteral Time.TimeZone+    -- | > TimeZoneShow                             ~  TimeZone/Show+    | TimeZoneShow+    -- | > List                                     ~  List+    | List+    -- | > ListLit (Just t ) []                     ~  [] : t+    --   > ListLit  Nothing  [x, y, z]              ~  [x, y, z]+    --+    --   Invariant: A non-empty list literal is always represented as+    --   @ListLit Nothing xs@.+    --+    --   When an annotated, non-empty list literal is parsed, it is represented+    --   as+    --+    --   > Annot (ListLit Nothing [x, y, z]) t      ~ [x, y, z] : t++    -- Eventually we should have separate constructors for empty and non-empty+    -- list literals. For now it's easier to check the invariant in @infer@.+    -- See https://github.com/dhall-lang/dhall-haskell/issues/1359#issuecomment-537087234.+    | ListLit (Maybe (Expr s a)) (Seq (Expr s a))+    -- | > ListAppend x y                           ~  x # y+    | ListAppend (Expr s a) (Expr s a)+    -- | > ListBuild                                ~  List/build+    | ListBuild+    -- | > ListFold                                 ~  List/fold+    | ListFold+    -- | > ListLength                               ~  List/length+    | ListLength+    -- | > ListHead                                 ~  List/head+    | ListHead+    -- | > ListLast                                 ~  List/last+    | ListLast+    -- | > ListIndexed                              ~  List/indexed+    | ListIndexed+    -- | > ListReverse                              ~  List/reverse+    | ListReverse+    -- | > Optional                                 ~  Optional+    | Optional+    -- | > Some e                                   ~  Some e+    | Some (Expr s a)+    -- | > None                                     ~  None+    | None+    -- | > Record [ (k1, RecordField _ t1)          ~  { k1 : t1, k2 : t1 }+    --   >        , (k2, RecordField _ t2)+    --   >        ]+    | Record    (Map Text (RecordField s a))+    -- | > RecordLit [ (k1, RecordField _ v1)       ~  { k1 = v1, k2 = v2 }+    --   >           , (k2, RecordField _ v2)+    --   >           ]+    | RecordLit (Map Text (RecordField s a))+    -- | > Union        [(k1, Just t1), (k2, Nothing)] ~  < k1 : t1 | k2 >+    | Union     (Map Text (Maybe (Expr s a)))+    -- | > Combine _ Nothing x y                    ~  x ∧ y+    --+    -- The first field is a `Just` when the `Combine` operator is introduced+    -- as a result of desugaring duplicate record fields:+    --+    --   > RecordLit [ ( k                          ~ { k = x, k = y }+    --   >           , RecordField+    --   >              _+    --   >              (Combine (Just k) x y)+    --   >            )]+    | Combine (Maybe CharacterSet) (Maybe Text) (Expr s a) (Expr s a)+    -- | > CombineTypes _ x y                       ~  x ⩓ y+    | CombineTypes (Maybe CharacterSet) (Expr s a) (Expr s a)+    -- | > Prefer _ _ x y                           ~  x ⫽ y+    | Prefer (Maybe CharacterSet) PreferAnnotation (Expr s a) (Expr s a)+    -- | > RecordCompletion x y                     ~  x::y+    | RecordCompletion (Expr s a) (Expr s a)+    -- | > Merge x y (Just t )                      ~  merge x y : t+    --   > Merge x y  Nothing                       ~  merge x y+    | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))+    -- | > ToMap x (Just t)                         ~  toMap x : t+    --   > ToMap x  Nothing                         ~  toMap x+    | ToMap (Expr s a) (Maybe (Expr s a))+    -- | > ShowConstructor x                        ~  showConstructor x+    | ShowConstructor (Expr s a)+    -- | > Field e (FieldSelection _ x _)              ~  e.x+    | Field (Expr s a) (FieldSelection s)+    -- | > Project e (Left xs)                      ~  e.{ xs }+    --   > Project e (Right t)                      ~  e.(t)+    | Project (Expr s a) (Either [Text] (Expr s a))+    -- | > Assert e                                 ~  assert : e+    | Assert (Expr s a)+    -- | > Equivalent _ x y                           ~  x ≡ y+    | Equivalent (Maybe CharacterSet) (Expr s a) (Expr s a)+    -- | > With x y e                               ~  x with y = e+    | With (Expr s a) (NonEmpty WithComponent) (Expr s a)+    -- | > Note s x                                 ~  e+    | Note s (Expr s a)+    -- | > ImportAlt                                ~  e1 ? e2+    | ImportAlt (Expr s a) (Expr s a)+    -- | > Embed import                             ~  import+    | Embed a+    deriving (Generic)+-- NB: If you add a constructor to Expr, please also update the Arbitrary+-- instance in Dhall.Test.QuickCheck.++instance IsString (Expr s a) where+    fromString str = Var (fromString str)
+ src/Dhall/Syntax/Expr.hs-boot view
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr where++import Data.Kind (Type)++type Expr :: Type -> Type -> Type+data Expr s a
+ src/Dhall/Syntax/FunctionBinding.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.FunctionBinding+    ( FunctionBinding(..)+    , makeFunctionBinding++      -- * Optics+    , functionBindingExprs+    ) where++import                Data.Text         (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the label of a function or a function-type expression+--+-- For example,+--+-- > λ({- A -} a {- B -} : {- C -} T) -> e+--+-- … will be instantiated as follows:+--+-- * @functionBindingSrc0@ corresponds to the @A@ comment+-- * @functionBindingVariable@ is @a@+-- * @functionBindingSrc1@ corresponds to the @B@ comment+-- * @functionBindingSrc2@ corresponds to the @C@ comment+-- * @functionBindingAnnotation@ is @T@+data FunctionBinding s a = FunctionBinding+    { functionBindingSrc0 :: Maybe s+    , functionBindingVariable :: Text+    , functionBindingSrc1 :: Maybe s+    , functionBindingSrc2 :: Maybe s+    , functionBindingAnnotation :: Expr s a+    } deriving Generic++-- | Smart constructor for 'FunctionBinding' with no src information+makeFunctionBinding :: Text -> Expr s a -> FunctionBinding s a+makeFunctionBinding l t = FunctionBinding Nothing l Nothing Nothing t++{-| Traverse over the immediate 'Expr' children in a 'FunctionBinding'.+-}+functionBindingExprs+    :: Applicative f+    => (Expr s a -> f (Expr s b))+    -> FunctionBinding s a -> f (FunctionBinding s b)+functionBindingExprs f (FunctionBinding s0 label s1 s2 type_) =+    FunctionBinding+        <$> pure s0+        <*> pure label+        <*> pure s1+        <*> pure s2+        <*> f type_+{-# INLINABLE functionBindingExprs #-}
+ src/Dhall/Syntax/Import.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}++module Dhall.Syntax.Import+    ( Directory(..)+    , File(..)+    , FilePrefix(..)+    , Import(..)+    , ImportHashed(..)+    , ImportMode(..)+    , ImportType(..)+    , URL(..)+    , Scheme(..)+    ) where++import Data.Data                      (Data)+import Data.Text                      (Text)+import Dhall.Src                      (Src (..))+import Dhall.Syntax.Expr              (Expr (..))+import Dhall.Syntax.Instances.Data    ()+import Dhall.Syntax.Instances.Functor ()+import GHC.Generics                   (Generic)++import qualified Dhall.Crypto++{-| Internal representation of a directory that stores the path components in+    reverse order++    In other words, the directory @\/foo\/bar\/baz@ is encoded as+    @Directory { components = [ "baz", "bar", "foo" ] }@+-}+newtype Directory = Directory { components :: [Text] }+    deriving (Data, Generic)++{-| A `File` is a `directory` followed by one additional path component+    representing the `file` name+-}+data File = File+    { directory :: Directory+    , file      :: Text+    } deriving (Data, Generic)++-- | The beginning of a file path which anchors subsequent path components+data FilePrefix+    = Absolute+    -- ^ Absolute path+    | Here+    -- ^ Path relative to @.@+    | Parent+    -- ^ Path relative to @..@+    | Home+    -- ^ Path relative to @~@+    deriving (Data, Generic)++-- | The URI scheme+data Scheme = HTTP | HTTPS+    deriving (Data, Generic)++-- | This type stores all of the components of a remote import+data URL = URL+    { scheme    :: Scheme+    , authority :: Text+    , path      :: File+    , query     :: Maybe Text+    , headers   :: Maybe (Expr Src Import)+    } deriving (Data, Generic)++-- | The type of import (i.e. local vs. remote vs. environment)+data ImportType+    = Local FilePrefix File+    -- ^ Local path+    | Remote URL+    -- ^ URL of remote resource and optional headers stored in an import+    | Env  Text+    -- ^ Environment variable+    | Missing+    deriving (Data, Generic)++-- | How to interpret the import's contents (i.e. as Dhall code or raw text)+data ImportMode = Code | RawText | Location | RawBytes+  deriving (Data, Generic)++-- | A `ImportType` extended with an optional hash for semantic integrity checks+data ImportHashed = ImportHashed+    { hash       :: Maybe Dhall.Crypto.SHA256Digest+    , importType :: ImportType+    } deriving (Data, Generic)++-- | Reference to an external resource+data Import = Import+    { importHashed :: ImportHashed+    , importMode   :: ImportMode+    } deriving (Data, Generic)+++++instance Semigroup Directory where+    Directory components0 <> Directory components1 =+        Directory (components1 <> components0)++instance Semigroup File where+    File directory0 _ <> File directory1 file =+        File (directory0 <> directory1) file++instance Semigroup ImportType where+    Local prefix file0 <> Local Here file1 = Local prefix (file0 <> file1)++    Remote (URL { path = path0, ..}) <> Local Here path1 =+        Remote (URL { path = path0 <> path1, ..})++    Local prefix file0 <> Local Parent file1 =+        Local prefix (file0 <> parent <> file1)++    Remote (URL { path = path0, .. }) <> Local Parent path1 =+        Remote (URL { path = path0 <> parent <> path1, .. })++    import0 <> Remote (URL { headers = headers0, .. }) =+        Remote (URL { headers = headers1, .. })+      where+        importHashed0 = Import (ImportHashed Nothing import0) Code++        headers1 = fmap (fmap (importHashed0 <>)) headers0++    _ <> import1 =+        import1++instance Semigroup ImportHashed where+    ImportHashed _ importType0 <> ImportHashed hash importType1 =+        ImportHashed hash (importType0 <> importType1)++instance Semigroup Import where+    Import importHashed0 _ <> Import importHashed1 code =+        Import (importHashed0 <> importHashed1) code++parent :: File+parent = File { directory = Directory { components = [ ".." ] }, file = "" }
+ src/Dhall/Syntax/Instances/Applicative.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Applicative () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Applicative (Expr s) where+    pure = Embed++    expression <*> k = case expression of+        Embed a     -> a <$> k+        Let a b     -> Let (adaptBinding a) (b <*> k)+        Note a b    -> Note a (b <*> k)+        Record a    -> Record $ adaptRecordField <$> a+        RecordLit a -> RecordLit $ adaptRecordField <$> a+        Lam cs a b  -> Lam cs (adaptFunctionBinding a) (b <*> k)+        Field a b   -> Field (a <*> k) b+        _ -> Lens.over unsafeSubExpressions (<*> k) expression+      where+        adaptRecordField (RecordField s0 e s1 s2) =+            RecordField s0 (e <*> k) s1 s2++        adaptBinding (Binding src0 c src1 d src2 e) =+            Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e <*> k)++        adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+            FunctionBinding src0 label src1 src2 (type_ <*> k)++        adaptBindingAnnotation (src3, f) = (src3, f <*> k)
+ src/Dhall/Syntax/Instances/Bifunctor.hs view
@@ -0,0 +1,44 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Bifunctor () where++import Data.Bifunctor                 (Bifunctor (..))+import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Bifunctor Binding where+    first k (Binding src0 a src1 b src2 c) =+        Binding (fmap k src0) a (fmap k src1) (fmap adapt0 b) (fmap k src2) (first k c)+      where+        adapt0 (src3, d) = (fmap k src3, first k d)++    second = fmap++instance Bifunctor RecordField where+    first k (RecordField s0 value' s1 s2) =+        RecordField (k <$> s0) (first k value') (k <$> s1) (k <$> s2)+    second = fmap++instance Bifunctor FunctionBinding where+    first k (FunctionBinding src0 label src1 src2 type_) =+        FunctionBinding (k <$> src0) label (k <$> src1) (k <$> src2) (first k type_)++    second = fmap++instance Bifunctor Expr where+    first k (Note a b   ) = Note (k a) (first k b)+    first _ (Embed a    ) = Embed a+    first k (Let a b    ) = Let (first k a) (first k b)+    first k (Record a   ) = Record $ first k <$> a+    first k (RecordLit a) = RecordLit $ first k <$> a+    first k (Lam cs a b ) = Lam cs (first k a) (first k b)+    first k (Field a b  ) = Field (first k a) (k <$> b)+    first k  expression  = Lens.over unsafeSubExpressions (first k) expression++    second = fmap
+ src/Dhall/Syntax/Instances/Data.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Data () where++import Data.Data                    (Data)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Data Const+deriving instance Data Var+deriving instance (Data a, Data s) => Data (Binding s a)+deriving instance Data DhallDouble+deriving instance (Data a, Data s) => Data (Chunks s a)+deriving instance Data PreferAnnotation+deriving instance (Data a, Data s) => Data (RecordField s a)+deriving instance (Data a, Data s) => Data (FunctionBinding s a)+deriving instance Data s => Data (FieldSelection s)+deriving instance Data WithComponent+deriving instance (Data a, Data s) => Data (Expr s a)
+ src/Dhall/Syntax/Instances/Eq.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Eq () where++import Data.Bits                    (xor)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++-- $setup+-- >>> import Data.Void (Void)+-- >>> import Dhall.Binary () -- For the orphan instance for `Serialise (Expr Void Import)`++deriving instance Eq Const+deriving instance Eq Var+deriving instance (Eq s, Eq a) => Eq (Binding s a)+deriving instance (Eq s, Eq a) => Eq (Chunks s a)+deriving instance Eq PreferAnnotation+deriving instance (Eq s, Eq a) => Eq (RecordField s a)+deriving instance (Eq s, Eq a) => Eq (FunctionBinding s a)+deriving instance Eq s => Eq (FieldSelection s)+deriving instance Eq WithComponent+-- | This instance encodes what the Dhall standard calls an \"exact match\"+-- between two expressions.+--+-- Note that+--+-- >>> nan = DhallDouble (0/0)+-- >>> DoubleLit nan == DoubleLit nan+-- True+deriving instance (Eq s, Eq a) => Eq (Expr s a)+deriving instance Eq Directory+deriving instance Eq File+deriving instance Eq FilePrefix+deriving instance Eq Scheme+deriving instance Eq URL+deriving instance Eq ImportType+deriving instance Eq ImportMode+deriving instance Eq ImportHashed+deriving instance Eq Import++-- | This instance satisfies all the customary 'Eq' laws except substitutivity.+--+-- In particular:+--+-- >>> nan = DhallDouble (0/0)+-- >>> nan == nan+-- True+--+-- This instance is also consistent with with the binary encoding of Dhall @Double@s:+--+-- >>> toBytes n = Dhall.Binary.encodeExpression (DoubleLit n :: Expr Void Import)+--+-- prop> \a b -> (a == b) == (toBytes a == toBytes b)+instance Eq DhallDouble where+    DhallDouble a == DhallDouble b+        | isNaN a && isNaN b                      = True+        | isNegativeZero a `xor` isNegativeZero b = False+        | otherwise                               = a == b
+ src/Dhall/Syntax/Instances/Foldable.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveFoldable     #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Foldable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Foldable (Binding s)+deriving instance Foldable (Chunks s)+deriving instance Foldable (RecordField s)+deriving instance Foldable (FunctionBinding s)+deriving instance Foldable FieldSelection+deriving instance Foldable (Expr s)
+ src/Dhall/Syntax/Instances/Functor.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE DeriveFunctor      #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Functor () where++import                Dhall.Syntax.Binding+import                Dhall.Syntax.Chunks+import                Dhall.Syntax.Expr+import                Dhall.Syntax.FunctionBinding+import {-# SOURCE #-} Dhall.Syntax.Operations      (unsafeSubExpressions)+import                Dhall.Syntax.RecordField+import                Dhall.Syntax.Types++import qualified Lens.Micro as Lens++deriving instance Functor (Binding s)+deriving instance Functor (Chunks s)+deriving instance Functor (RecordField s)+deriving instance Functor (FunctionBinding s)+deriving instance Functor FieldSelection++-- This instance is hand-written due to the fact that deriving+-- it does not give us an INLINABLE pragma. We annotate this fmap+-- implementation with this pragma below to allow GHC to, possibly,+-- inline the implementation for performance improvements.+instance Functor (Expr s) where+  fmap f (Embed a) = Embed (f a)+  fmap f (Let b e2) = Let (fmap f b) (fmap f e2)+  fmap f (Note s e1) = Note s (fmap f e1)+  fmap f (Record a) = Record $ fmap f <$> a+  fmap f (RecordLit a) = RecordLit $ fmap f <$> a+  fmap f (Lam cs fb e) = Lam cs (f <$> fb) (f <$> e)+  fmap f (Field a b) = Field (f <$> a) b+  fmap f expression = Lens.over unsafeSubExpressions (fmap f) expression+  {-# INLINABLE fmap #-}
+ src/Dhall/Syntax/Instances/Lift.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Lift () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Language.Haskell.TH.Syntax   (Lift)++#if !MIN_VERSION_template_haskell(2,21,0)+import qualified Data.Fixed as Fixed+#endif+import qualified Data.Time as Time++#if !MIN_VERSION_time(1,14,0)+deriving instance Lift Time.Day+#endif+deriving instance Lift Time.TimeOfDay+deriving instance Lift Time.TimeZone+#if !MIN_VERSION_template_haskell(2,21,0)+deriving instance Lift (Fixed.Fixed a)+#endif+deriving instance Lift Const+deriving instance Lift Var+deriving instance (Lift s, Lift a) => Lift (Binding s a)+deriving instance Lift DhallDouble+deriving instance (Lift s, Lift a) => Lift (Chunks s a)+deriving instance Lift PreferAnnotation+deriving instance (Lift s, Lift a) => Lift (RecordField s a)+deriving instance (Lift s, Lift a) => Lift (FunctionBinding s a)+deriving instance Lift s => Lift (FieldSelection s)+deriving instance Lift WithComponent+deriving instance (Lift s, Lift a) => Lift (Expr s a)
+ src/Dhall/Syntax/Instances/Monad.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Monad () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Applicative ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Monad (Expr s) where+    return = pure++    expression >>= k = case expression of+        Embed a     -> k a+        Let a b     -> Let (adaptBinding a) (b >>= k)+        Note a b    -> Note a (b >>= k)+        Record a    -> Record $ bindRecordKeyValues <$> a+        RecordLit a -> RecordLit $ bindRecordKeyValues <$> a+        Lam cs a b  -> Lam cs (adaptFunctionBinding a) (b >>= k)+        Field a b   -> Field (a >>= k) b+        _ -> Lens.over unsafeSubExpressions (>>= k) expression+      where+        bindRecordKeyValues (RecordField s0 e s1 s2) =+            RecordField s0 (e >>= k) s1 s2++        adaptBinding (Binding src0 c src1 d src2 e) =+            Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e >>= k)++        adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+            FunctionBinding src0 label src1 src2 (type_ >>= k)++        adaptBindingAnnotation (src3, f) = (src3, f >>= k)
+ src/Dhall/Syntax/Instances/NFData.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.NFData () where++import Control.DeepSeq              (NFData)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++instance NFData Const+instance NFData Var+instance (NFData s, NFData a) => NFData (Binding s a)+instance NFData DhallDouble+instance (NFData s, NFData a) => NFData (Chunks s a)+instance NFData PreferAnnotation+instance (NFData s, NFData a) => NFData (RecordField s a)+instance (NFData s, NFData a) => NFData (FunctionBinding s a)+instance NFData s => NFData (FieldSelection s)+instance NFData WithComponent+instance (NFData s, NFData a) => NFData (Expr s a)+instance NFData Directory+instance NFData File+instance NFData FilePrefix+instance NFData Scheme+instance NFData URL+instance NFData ImportType+instance NFData ImportMode+instance NFData ImportHashed+instance NFData Import
+ src/Dhall/Syntax/Instances/Ord.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Ord () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.Instances.Eq    ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Ord Const+deriving instance Ord Var+deriving instance (Ord s, Ord a) => Ord (Binding s a)+deriving instance (Ord s, Ord a) => Ord (Chunks s a)+deriving instance Ord PreferAnnotation+deriving instance (Ord s, Ord a) => Ord (RecordField s a)+deriving instance (Ord s, Ord a) => Ord (FunctionBinding s a)+deriving instance Ord s => Ord (FieldSelection s)+deriving instance Ord WithComponent+-- | Note that this 'Ord' instance inherits `DhallDouble`'s defects.+deriving instance (Ord s, Ord a) => Ord (Expr s a)+deriving instance Ord Directory+deriving instance Ord File+deriving instance Ord FilePrefix+deriving instance Ord Scheme+deriving instance Ord URL+deriving instance Ord ImportType+deriving instance Ord ImportMode+deriving instance Ord ImportHashed+deriving instance Ord Import++-- | This instance relies on the 'Eq' instance for 'DhallDouble' but cannot+-- satisfy the customary 'Ord' laws when @NaN@ is involved.+instance Ord DhallDouble where+    compare a@(DhallDouble a') b@(DhallDouble b') =+        if a == b+            then EQ+            else compare a' b'
+ src/Dhall/Syntax/Instances/Pretty.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty+    ( pathCharacter+    ) where++import                Data.Text             (Text)+import {-# SOURCE #-} Dhall.Pretty.Internal+import                Dhall.Syntax.Const+import                Dhall.Syntax.Expr+import                Dhall.Syntax.Import+import                Dhall.Syntax.Var+import                Prettyprinter         (Doc, Pretty)++import qualified Data.Text+import qualified Network.URI   as URI+import qualified Prettyprinter as Pretty++instance Pretty Const where+    pretty = Pretty.unAnnotate . prettyConst++instance Pretty Var where+    pretty = Pretty.unAnnotate . prettyVar++-- | Generates a syntactically valid Dhall program+instance Pretty a => Pretty (Expr s a) where+    pretty = Pretty.unAnnotate . prettyExpr++instance Pretty Directory where+    pretty (Directory {..}) = foldMap prettyPathComponent (reverse components)++prettyPathComponent :: Text -> Doc ann+prettyPathComponent text+    | Data.Text.all pathCharacter text =+        "/" <> Pretty.pretty text+    | otherwise =+        "/\"" <> Pretty.pretty text <> "\""++instance Pretty File where+    pretty (File {..}) =+            Pretty.pretty directory+        <>  prettyPathComponent file++instance Pretty FilePrefix where+    pretty Absolute = ""+    pretty Here     = "."+    pretty Parent   = ".."+    pretty Home     = "~"++instance Pretty URL where+    pretty (URL {..}) =+            schemeDoc+        <>  "://"+        <>  Pretty.pretty authority+        <>  pathDoc+        <>  queryDoc+        <>  foldMap prettyHeaders headers+      where+        prettyHeaders h =+          " using (" <> Pretty.unAnnotate (Pretty.pretty h) <> ")"++        File {..} = path++        Directory {..} = directory++        pathDoc =+                foldMap prettyURIComponent (reverse components)+            <>  prettyURIComponent file++        schemeDoc = case scheme of+            HTTP  -> "http"+            HTTPS -> "https"++        queryDoc = case query of+            Nothing -> ""+            Just q  -> "?" <> Pretty.pretty q++prettyURIComponent :: Text -> Doc ann+prettyURIComponent text =+        Pretty.pretty $ URI.normalizeCase $ URI.normalizeEscape $ "/" <> Data.Text.unpack text++instance Pretty ImportType where+    pretty (Local prefix file) =+        Pretty.pretty prefix <> Pretty.pretty file++    pretty (Remote url) = Pretty.pretty url++    pretty (Env env) = "env:" <> prettyEnvironmentVariable env++    pretty Missing = "missing"++instance Pretty ImportHashed where+    pretty (ImportHashed  Nothing p) =+      Pretty.pretty p+    pretty (ImportHashed (Just h) p) =+      Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   Pretty.pretty p <> Pretty.hardline+                <>  "  sha256:" <> Pretty.pretty (show h)+                )++        short = Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)++instance Pretty Import where+    pretty (Import {..}) = Pretty.pretty importHashed <> Pretty.pretty suffix+      where+        suffix :: Text+        suffix = case importMode of+            RawText  -> " as Text"+            Location -> " as Location"+            Code     -> ""+            RawBytes -> " as Bytes"++{-| Returns `True` if the given `Char` is valid within an unquoted path+    component++    This is exported for reuse within the @"Dhall.Parser.Token"@ module+-}+pathCharacter :: Char -> Bool+pathCharacter c =+         '\x21' == c+    ||  ('\x24' <= c && c <= '\x27')+    ||  ('\x2A' <= c && c <= '\x2B')+    ||  ('\x2D' <= c && c <= '\x2E')+    ||  ('\x30' <= c && c <= '\x3B')+    ||  c == '\x3D'+    ||  ('\x40' <= c && c <= '\x5A')+    ||  ('\x5E' <= c && c <= '\x7A')+    ||  c == '\x7C'+    ||  c == '\x7E'
+ src/Dhall/Syntax/Instances/Pretty.hs-boot view
@@ -0,0 +1,8 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty where++import Dhall.Syntax.Expr (Expr)+import Prettyprinter     (Pretty)++instance Pretty a => Pretty (Expr s a)
+ src/Dhall/Syntax/Instances/Show.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Show () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Show Const+deriving instance Show Var+deriving instance (Show s, Show a) => Show (Binding s a)+deriving instance Show DhallDouble+deriving instance (Show s, Show a) => Show (Chunks s a)+deriving instance Show PreferAnnotation+deriving instance (Show s, Show a) => Show (RecordField s a)+deriving instance (Show s, Show a) => Show (FunctionBinding s a)+deriving instance Show s => Show (FieldSelection s)+deriving instance Show WithComponent+deriving instance (Show s, Show a) => Show (Expr s a)+deriving instance Show Directory+deriving instance Show File+deriving instance Show FilePrefix+deriving instance Show Scheme+deriving instance Show URL+deriving instance Show ImportType+deriving instance Show ImportMode+deriving instance Show ImportHashed+deriving instance Show Import
+ src/Dhall/Syntax/Instances/Traversable.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE DeriveTraversable  #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Traversable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Foldable ()+import Dhall.Syntax.Instances.Functor  ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Traversable (Binding s)+deriving instance Traversable (Chunks s)+deriving instance Traversable (RecordField s)+deriving instance Traversable (FunctionBinding s)+deriving instance Traversable FieldSelection+deriving instance Traversable (Expr s)
+ src/Dhall/Syntax/MultiLet.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE LambdaCase #-}++{- | Instead of converting explicitly between 'Expr's and 'MultiLet', it might+be nicer to use a pattern synonym:++> pattern MultiLet' :: NonEmpty (Binding s a) -> Expr s a -> Expr s a+> pattern MultiLet' as b <- (multiLetFromExpr -> Just (MultiLet as b)) where+>   MultiLet' as b = wrapInLets as b+>+> multiLetFromExpr :: Expr s a -> Maybe (MultiLet s a)+> multiLetFromExpr = \case+>     Let x mA a b -> Just (multiLet x mA a b)+>     _ -> Nothing++This works in principle, but GHC as of v8.8.1 doesn't handle it well:+https://gitlab.haskell.org/ghc/ghc/issues/17096++This should be fixed by GHC-8.10, so it might be worth revisiting then.+-}++module Dhall.Syntax.MultiLet+    ( MultiLet(..)+    , multiLet+    , wrapInLets+    ) where++import Data.List.NonEmpty   (NonEmpty (..))+import Dhall.Syntax.Binding (Binding)+import Dhall.Syntax.Expr    (Expr (..))++import qualified Data.List.NonEmpty as NonEmpty++{-| Generate a 'MultiLet' from the contents of a 'Let'.++    In the resulting @'MultiLet' bs e@, @e@ is guaranteed not to be a 'Let',+    but it might be a @('Note' … ('Let' …))@.++    Given parser output, 'multiLet' consolidates @let@s that formed a+    let-block in the original source.+-}+multiLet :: Binding s a -> Expr s a -> MultiLet s a+multiLet b0 = \case+    Let b1 e1 ->+        let MultiLet bs e = multiLet b1 e1+        in  MultiLet (NonEmpty.cons b0 bs) e+    e -> MultiLet (b0 :| []) e++{-| Wrap let-'Binding's around an 'Expr'.++'wrapInLets' can be understood as an inverse for 'multiLet':++> let MultiLet bs e1 = multiLet b e0+>+> wrapInLets bs e1 == Let b e0+-}+wrapInLets :: Foldable f => f (Binding s a) -> Expr s a -> Expr s a+wrapInLets bs e = foldr Let e bs++{-| This type represents 1 or more nested `Let` bindings that have been+    coalesced together for ease of manipulation+-}+data MultiLet s a = MultiLet (NonEmpty (Binding s a)) (Expr s a)
+ src/Dhall/Syntax/Operations.hs view
@@ -0,0 +1,394 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}++module Dhall.Syntax.Operations+    ( -- * Optics+      subExpressions+    , subExpressionsWith+    , unsafeSubExpressions++      -- * Handling 'Note's+    , denote+    , renote+    , shallowDenote++      -- * Reserved identifiers+    , reservedIdentifiers+    , reservedKeywords++      -- * Utilities+    , internalError+      -- `shift` should really be in `Dhall.Normalize`, but it's here to avoid a+      -- module cycle+    , shift+    ) where++import Data.HashSet                 (HashSet)+import Data.Text                    (Text)+import Data.Void                    (Void)+import Dhall.Syntax.Binding         (Binding (..), bindingExprs)+import Dhall.Syntax.Chunks          (chunkExprs)+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField     (RecordField (..), recordFieldExprs)+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Unsafe.Coerce                (unsafeCoerce)++import qualified Data.HashSet+import qualified Data.Text+import qualified Lens.Micro   as Lens+++-- | A traversal over the immediate sub-expressions of an expression.+subExpressions+    :: Applicative f => (Expr s a -> f (Expr s a)) -> Expr s a -> f (Expr s a)+subExpressions = subExpressionsWith (pure . Embed)+{-# INLINABLE subExpressions #-}++{-| A traversal over the immediate sub-expressions of an expression which+    allows mapping embedded values+-}+subExpressionsWith+    :: Applicative f => (a -> f (Expr s b)) -> (Expr s a -> f (Expr s b)) -> Expr s a -> f (Expr s b)+subExpressionsWith h _ (Embed a) = h a+subExpressionsWith _ f (Note a b) = Note a <$> f b+subExpressionsWith _ f (Let a b) = Let <$> bindingExprs f a <*> f b+subExpressionsWith _ f (Record a) = Record <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (RecordLit a) = RecordLit <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (Lam cs fb e) = Lam cs <$> functionBindingExprs f fb <*> f e+subExpressionsWith _ f (Field a b) = Field <$> f a <*> pure b+subExpressionsWith _ f expression = unsafeSubExpressions f expression+{-# INLINABLE subExpressionsWith #-}++{-| An internal utility used to implement transformations that require changing+    one of the type variables of the `Expr` type++    This utility only works because the implementation is partial, not+    handling the `Let`, `Note`, or `Embed` cases, which need to be handled by+    the caller.+-}+unsafeSubExpressions+    :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)+unsafeSubExpressions _ (Const c) = pure (Const c)+unsafeSubExpressions _ (Var v) = pure (Var v)+unsafeSubExpressions f (Pi cs a b c) = Pi cs a <$> f b <*> f c+unsafeSubExpressions f (App a b) = App <$> f a <*> f b+unsafeSubExpressions f (Annot a b) = Annot <$> f a <*> f b+unsafeSubExpressions _ Bool = pure Bool+unsafeSubExpressions _ (BoolLit b) = pure (BoolLit b)+unsafeSubExpressions f (BoolAnd a b) = BoolAnd <$> f a <*> f b+unsafeSubExpressions f (BoolOr a b) = BoolOr <$> f a <*> f b+unsafeSubExpressions f (BoolEQ a b) = BoolEQ <$> f a <*> f b+unsafeSubExpressions f (BoolNE a b) = BoolNE <$> f a <*> f b+unsafeSubExpressions f (BoolIf a b c) = BoolIf <$> f a <*> f b <*> f c+unsafeSubExpressions _ Bytes = pure Bytes+unsafeSubExpressions _ (BytesLit a) = pure (BytesLit a)+unsafeSubExpressions _ Natural = pure Natural+unsafeSubExpressions _ (NaturalLit n) = pure (NaturalLit n)+unsafeSubExpressions _ NaturalFold = pure NaturalFold+unsafeSubExpressions _ NaturalBuild = pure NaturalBuild+unsafeSubExpressions _ NaturalIsZero = pure NaturalIsZero+unsafeSubExpressions _ NaturalEven = pure NaturalEven+unsafeSubExpressions _ NaturalOdd = pure NaturalOdd+unsafeSubExpressions _ NaturalToInteger = pure NaturalToInteger+unsafeSubExpressions _ NaturalShow = pure NaturalShow+unsafeSubExpressions _ NaturalSubtract = pure NaturalSubtract+unsafeSubExpressions f (NaturalPlus a b) = NaturalPlus <$> f a <*> f b+unsafeSubExpressions f (NaturalTimes a b) = NaturalTimes <$> f a <*> f b+unsafeSubExpressions _ Integer = pure Integer+unsafeSubExpressions _ (IntegerLit n) = pure (IntegerLit n)+unsafeSubExpressions _ IntegerClamp = pure IntegerClamp+unsafeSubExpressions _ IntegerNegate = pure IntegerNegate+unsafeSubExpressions _ IntegerShow = pure IntegerShow+unsafeSubExpressions _ IntegerToDouble = pure IntegerToDouble+unsafeSubExpressions _ Double = pure Double+unsafeSubExpressions _ (DoubleLit n) = pure (DoubleLit n)+unsafeSubExpressions _ DoubleShow = pure DoubleShow+unsafeSubExpressions _ Text = pure Text+unsafeSubExpressions f (TextLit chunks) = TextLit <$> chunkExprs f chunks+unsafeSubExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b+unsafeSubExpressions _ TextReplace = pure TextReplace+unsafeSubExpressions _ TextShow = pure TextShow+unsafeSubExpressions _ Date = pure Date+unsafeSubExpressions _ (DateLiteral a) = pure (DateLiteral a)+unsafeSubExpressions _ DateShow = pure DateShow+unsafeSubExpressions _ Time = pure Time+unsafeSubExpressions _ (TimeLiteral a b) = pure (TimeLiteral a b)+unsafeSubExpressions _ TimeShow = pure TimeShow+unsafeSubExpressions _ TimeZone = pure TimeZone+unsafeSubExpressions _ (TimeZoneLiteral a) = pure (TimeZoneLiteral a)+unsafeSubExpressions _ TimeZoneShow = pure TimeZoneShow+unsafeSubExpressions _ List = pure List+unsafeSubExpressions f (ListLit a b) = ListLit <$> traverse f a <*> traverse f b+unsafeSubExpressions f (ListAppend a b) = ListAppend <$> f a <*> f b+unsafeSubExpressions _ ListBuild = pure ListBuild+unsafeSubExpressions _ ListFold = pure ListFold+unsafeSubExpressions _ ListLength = pure ListLength+unsafeSubExpressions _ ListHead = pure ListHead+unsafeSubExpressions _ ListLast = pure ListLast+unsafeSubExpressions _ ListIndexed = pure ListIndexed+unsafeSubExpressions _ ListReverse = pure ListReverse+unsafeSubExpressions _ Optional = pure Optional+unsafeSubExpressions f (Some a) = Some <$> f a+unsafeSubExpressions _ None = pure None+unsafeSubExpressions f (Union a) = Union <$> traverse (traverse f) a+unsafeSubExpressions f (Combine cs a b c) = Combine cs a <$> f b <*> f c+unsafeSubExpressions f (CombineTypes cs a b) = CombineTypes cs <$> f a <*> f b+unsafeSubExpressions f (Prefer cs a b c) = Prefer cs <$> pure a <*> f b <*> f c+unsafeSubExpressions f (RecordCompletion a b) = RecordCompletion <$> f a <*> f b+unsafeSubExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t+unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t+unsafeSubExpressions f (ShowConstructor a) = ShowConstructor <$> f a+unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b+unsafeSubExpressions f (Assert a) = Assert <$> f a+unsafeSubExpressions f (Equivalent cs a b) = Equivalent cs <$> f a <*> f b+unsafeSubExpressions f (With a b c) = With <$> f a <*> pure b <*> f c+unsafeSubExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r+unsafeSubExpressions _ (Let {}) = unhandledConstructor "Let"+unsafeSubExpressions _ (Note {}) = unhandledConstructor "Note"+unsafeSubExpressions _ (Embed {}) = unhandledConstructor "Embed"+unsafeSubExpressions _ (Record {}) = unhandledConstructor "Record"+unsafeSubExpressions _ (RecordLit {}) = unhandledConstructor "RecordLit"+unsafeSubExpressions _ (Lam {}) = unhandledConstructor "Lam"+unsafeSubExpressions _ (Field {}) = unhandledConstructor "Field"+{-# INLINABLE unsafeSubExpressions #-}++unhandledConstructor :: Text -> a+unhandledConstructor constructor =+    internalError+        (   "Dhall.Syntax.unsafeSubExpressions: Unhandled "+        <>  constructor+        <>  " construtor"+        )++-- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)+--+-- This also remove CharacterSet annotations.+denote :: Expr s a -> Expr t a+denote = \case+    Note _ b -> denote b+    Let a b -> Let (denoteBinding a) (denote b)+    Embed a -> Embed a+    Combine _ _ b c -> Combine Nothing Nothing (denote b) (denote c)+    CombineTypes _ b c -> CombineTypes Nothing (denote b) (denote c)+    Prefer _ a b c -> Lens.over unsafeSubExpressions denote $ Prefer Nothing a b c+    Record a -> Record $ denoteRecordField <$> a+    RecordLit a -> RecordLit $ denoteRecordField <$> a+    Lam _ a b -> Lam Nothing (denoteFunctionBinding a) (denote b)+    Pi _ t a b -> Pi Nothing t (denote a) (denote b)+    Field a (FieldSelection _ b _) -> Field (denote a) (FieldSelection Nothing b Nothing)+    Equivalent _ a b -> Equivalent Nothing (denote a) (denote b)+    expression -> Lens.over unsafeSubExpressions denote expression+  where+    denoteRecordField (RecordField _ e _ _) = RecordField Nothing (denote e) Nothing Nothing++    denoteBinding (Binding _ c _ d _ e) =+        Binding Nothing c Nothing (fmap denoteBindingAnnotation d) Nothing (denote e)++    denoteBindingAnnotation (_, f) = (Nothing, denote f)++    denoteFunctionBinding (FunctionBinding _ l _ _ t) =+        FunctionBinding Nothing l Nothing Nothing (denote t)++-- | The \"opposite\" of `denote`, like @first absurd@ but faster+renote :: Expr Void a -> Expr s a+renote = unsafeCoerce+{-# INLINE renote #-}++{-| Remove any outermost `Note` constructors++    This is typically used when you want to get the outermost non-`Note`+    constructor without removing internal `Note` constructors+-}+shallowDenote :: Expr s a -> Expr s a+shallowDenote (Note _ e) = shallowDenote e+shallowDenote         e  = e++-- | The set of reserved keywords according to the @keyword@ rule in the grammar+reservedKeywords :: HashSet Text+reservedKeywords =+    Data.HashSet.fromList+        [ "if"+        , "then"+        , "else"+        , "let"+        , "in"+        , "using"+        , "missing"+        , "as"+        , "Infinity"+        , "NaN"+        , "merge"+        , "Some"+        , "toMap"+        , "assert"+        , "forall"+        , "with"+        ]++-- | The set of reserved identifiers for the Dhall language+-- | Contains also all keywords from "reservedKeywords"+reservedIdentifiers :: HashSet Text+reservedIdentifiers = reservedKeywords <>+    Data.HashSet.fromList+        [ -- Builtins according to the `builtin` rule in the grammar+          "Natural/fold"+        , "Natural/build"+        , "Natural/isZero"+        , "Natural/even"+        , "Natural/odd"+        , "Natural/toInteger"+        , "Natural/show"+        , "Natural/subtract"+        , "Integer"+        , "Integer/clamp"+        , "Integer/negate"+        , "Integer/show"+        , "Integer/toDouble"+        , "Integer/show"+        , "Natural/subtract"+        , "Double/show"+        , "List/build"+        , "List/fold"+        , "List/length"+        , "List/head"+        , "List/last"+        , "List/indexed"+        , "List/reverse"+        , "Text/replace"+        , "Text/show"+        , "Date/show"+        , "Time/show"+        , "TimeZone/show"+        , "Bool"+        , "Bytes"+        , "True"+        , "False"+        , "Optional"+        , "None"+        , "Natural"+        , "Integer"+        , "Double"+        , "Text"+        , "Date"+        , "Time"+        , "TimeZone"+        , "List"+        , "Type"+        , "Kind"+        , "Sort"+        ]++{-| `shift` is used by both normalization and type-checking to avoid variable+    capture by shifting variable indices++    For example, suppose that you were to normalize the following expression:++> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x++    If you were to substitute @y@ with @x@ without shifting any variable+    indices, then you would get the following incorrect result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x  -- Incorrect normalized form++    In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in+    order to avoid being misinterpreted as the @x@ bound by the innermost+    lambda.  If we perform that `shift` then we get the correct result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x@1++    As a more worked example, suppose that you were to normalize the following+    expression:++>     λ(a : Type)+> →   λ(f : a → a → a)+> →   λ(x : a)+> →   λ(x : a)+> →   (λ(x : a) → f x x@1) x@1++    The correct normalized result would be:++>     λ(a : Type)+> →   λ(f : a → a → a)+> →   λ(x : a)+> →   λ(x : a)+> →   f x@1 x++    The above example illustrates how we need to both increase and decrease+    variable indices as part of substitution:++    * We need to increase the index of the outer @x\@1@ to @x\@2@ before we+      substitute it into the body of the innermost lambda expression in order+      to avoid variable capture.  This substitution changes the body of the+      lambda expression to @(f x\@2 x\@1)@++    * We then remove the innermost lambda and therefore decrease the indices of+      both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one+      less @x@ variable is now bound within that scope++    Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to+    the indices of all variables named @x@ whose indices are greater than+    @(n + m)@, where @m@ is the number of bound variables of the same name+    within that scope++    In practice, @d@ is always @1@ or @-1@ because we either:++    * increment variables by @1@ to avoid variable capture during substitution+    * decrement variables by @1@ when deleting lambdas after substitution++    @n@ starts off at @0@ when substitution begins and increments every time we+    descend into a lambda or let expression that binds a variable of the same+    name in order to avoid shifting the bound variables by mistake.+-}+shift :: Int -> Var -> Expr s a -> Expr s a+shift d (V x n) (Var (V x' n')) = Var (V x' n'')+  where+    n'' = if x == x' && n <= n' then n' + d else n'+shift d (V x n) (Lam cs (FunctionBinding src0 x' src1 src2 _A) b) =+    Lam cs (FunctionBinding src0 x' src1 src2 _A') b'+  where+    _A' = shift d (V x n ) _A+    b'  = shift d (V x n') b+      where+        n' = if x == x' then n + 1 else n+shift d (V x n) (Pi cs x' _A _B) = Pi cs x' _A' _B'+  where+    _A' = shift d (V x n ) _A+    _B' = shift d (V x n') _B+      where+        n' = if x == x' then n + 1 else n+shift d (V x n) (Let (Binding src0 f src1 mt src2 r) e) =+    Let (Binding src0 f src1 mt' src2 r') e'+  where+    e' = shift d (V x n') e+      where+        n' = if x == f then n + 1 else n++    mt' = fmap (fmap (shift d (V x n))) mt+    r'  =             shift d (V x n)  r+shift d v expression = Lens.over subExpressions (shift d v) expression++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"++{-| Utility function used to throw internal errors that should never happen+    (in theory) but that are not enforced by the type system+-}+internalError :: Data.Text.Text -> forall b . b+internalError text = error (unlines+    [ _ERROR <> ": Compiler bug                                                        "+    , "                                                                                "+    , "Explanation: This error message means that there is a bug in the Dhall compiler."+    , "You didn't do anything wrong, but if you would like to see this problem fixed   "+    , "then you should report the bug at:                                              "+    , "                                                                                "+    , "https://github.com/dhall-lang/dhall-haskell/issues                              "+    , "                                                                                "+    , "Please include the following text in your bug report:                           "+    , "                                                                                "+    , "```                                                                             "+    , Data.Text.unpack text <> "                                                       "+    , "```                                                                             "+    ] )
+ src/Dhall/Syntax/Operations.hs-boot view
@@ -0,0 +1,5 @@+module Dhall.Syntax.Operations where++import Dhall.Syntax.Expr (Expr)++unsafeSubExpressions :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)
+ src/Dhall/Syntax/RecordField.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.RecordField+    ( RecordField(..)+    , makeRecordField++      -- * Optics+    , recordFieldExprs+    ) where++import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the field of a record-type and record-literal expression.+-- The reason why we use the same ADT for both of them is because they store+-- the same information.+--+-- For example,+--+-- > { {- A -} x {- B -} : {- C -} T }+--+-- ... or+--+-- > { {- A -} x {- B -} = {- C -} T }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ is @"T"@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ corresponds to the @C@ comment.+--+-- Although the @A@ comment isn't annotating the @"T"@ Record Field,+-- this is the best place to keep these comments.+--+-- Note that @recordFieldSrc2@ is always 'Nothing' when the 'RecordField' is for+-- a punned entry, because there is no @=@ sign. For example,+--+-- > { {- A -} x {- B -} }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ corresponds to @(Var "x")@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ will be 'Nothing'+--+-- The labels involved in a record using dot-syntax like in this example:+--+-- > { {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }+--+-- will be instantiated as follows:+--+-- * For both the @a@ and @b@ field, @recordfieldSrc2@ is 'Nothing'+-- * For the @a@ field:+--   * @recordFieldSrc0@ corresponds to the @A@ comment+--   * @recordFieldSrc1@ corresponds to the @B@ comment+-- * For the @b@ field:+--   * @recordFieldSrc0@ corresponds to the @C@ comment+--   * @recordFieldSrc1@ corresponds to the @D@ comment+-- * For the @c@ field:+--   * @recordFieldSrc0@ corresponds to the @E@ comment+--   * @recordFieldSrc1@ corresponds to the @F@ comment+--   * @recordFieldSrc2@ corresponds to the @G@ comment+--+-- That is, for every label except the last one the semantics of+-- @recordFieldSrc0@ and @recordFieldSrc1@ are the same from a regular record+-- label but @recordFieldSrc2@ is always 'Nothing'. For the last keyword, all+-- srcs are 'Just'+data RecordField s a = RecordField+    { recordFieldSrc0  :: Maybe s+    , recordFieldValue :: Expr s a+    , recordFieldSrc1  :: Maybe s+    , recordFieldSrc2  :: Maybe s+    } deriving Generic++-- | Construct a 'RecordField' with no src information+makeRecordField :: Expr s a -> RecordField s a+makeRecordField e = RecordField Nothing e Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'RecordField'.+-}+recordFieldExprs+    :: Applicative f+    => (Expr s a -> f (Expr s b))+    -> RecordField s a -> f (RecordField s b)+recordFieldExprs f (RecordField s0 e s1 s2) =+    RecordField+        <$> pure s0+        <*> f e+        <*> pure s1+        <*> pure s2+{-# INLINABLE recordFieldExprs #-}
+ src/Dhall/Syntax/Types.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Types+    ( DhallDouble(..)+    , PreferAnnotation(..)+    , FieldSelection(..)+    , makeFieldSelection+    , WithComponent(..)+    ) where++import Data.Text    (Text)+import GHC.Generics (Generic)++-- | This wrapper around 'Prelude.Double' exists for its 'Eq' instance which is+-- defined via the binary encoding of Dhall @Double@s.+newtype DhallDouble = DhallDouble { getDhallDouble :: Double }+    deriving Generic++-- | Used to record the origin of a @//@ operator (i.e. from source code or a+-- product of desugaring)+data PreferAnnotation+    = PreferFromSource+    | PreferFromCompletion+    deriving Generic++-- | Record the field on a selector-expression+--+-- For example,+--+-- > e . {- A -} x {- B -}+--+-- … will be instantiated as follows:+--+-- * @fieldSelectionSrc0@ corresponds to the @A@ comment+-- * @fieldSelectionLabel@ corresponds to @x@+-- * @fieldSelectionSrc1@ corresponds to the @B@ comment+--+-- Given our limitation that not all expressions recover their whitespaces, the+-- purpose of @fieldSelectionSrc1@ is to save the 'Text.Megaparsec.SourcePos'+-- where the @fieldSelectionLabel@ ends, but we /still/ use a+-- 'Maybe Dhall.Src.Src' (@s = 'Dhall.Src.Src'@) to be consistent with similar+-- data types such as 'Dhall.Syntax.Binding.Binding', for example.+data FieldSelection s = FieldSelection+    { fieldSelectionSrc0 :: Maybe s+    , fieldSelectionLabel :: !Text+    , fieldSelectionSrc1 :: Maybe s+    } deriving Generic++-- | Smart constructor for 'FieldSelection' with no src information+makeFieldSelection :: Text -> FieldSelection s+makeFieldSelection t = FieldSelection Nothing t Nothing++-- | A path component for a @with@ expression+data WithComponent = WithLabel Text | WithQuestion+    deriving Generic
+ src/Dhall/Syntax/Types.hs-boot view
@@ -0,0 +1,14 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Types where++import Data.Kind (Type)++data DhallDouble++data PreferAnnotation++type FieldSelection :: Type -> Type+data FieldSelection s++data WithComponent
+ src/Dhall/Syntax/Var.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Var+    ( Var(..)+    ) where++import Data.String  (IsString (..))+import Data.Text    (Text)+import GHC.Generics (Generic)++{-| Label for a bound variable++    The `Data.Text.Text` field is the variable's name (i.e. \"@x@\").++    The `Int` field disambiguates variables with the same name if there are+    multiple bound variables of the same name in scope.  Zero refers to the+    nearest bound variable and the index increases by one for each bound+    variable of the same name going outward.  The following diagram may help:++>                               ┌──refers to──┐+>                               │             │+>                               v             │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0+>+> ┌─────────────────refers to─────────────────┐+> │                                           │+> v                                           │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1++    This `Int` behaves like a De Bruijn index in the special case where all+    variables have the same name.++    You can optionally omit the index if it is @0@:++>                               ┌─refers to─┐+>                               │           │+>                               v           │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x++    Zero indices are omitted when pretty-printing @Var@s and non-zero indices+    appear as a numeric suffix.+-}+data Var = V Text !Int+    deriving Generic++instance IsString Var where+    fromString str = V (fromString str) 0
+ src/Dhall/TH.hs view
@@ -0,0 +1,635 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TemplateHaskell   #-}++-- | Template Haskell utilities+module Dhall.TH+    ( -- * Embedding Dhall in Haskell+      staticDhallExpression+    , dhall+      -- * Generating Haskell from Dhall expressions+    , makeHaskellTypeFromUnion+    , makeHaskellTypes+    , makeHaskellTypesWith+    , HaskellType(..)+    , GenerateOptions(..)+    , defaultGenerateOptions+    ) where++import Control.Monad             (forM_)+import Data.Bifunctor            (first)+import Data.Text                 (Text)+import Dhall                     (FromDhall, ToDhall)+import Dhall.Syntax              (Expr (..), FunctionBinding (..), Var (..))+import GHC.Generics              (Generic)+import Language.Haskell.TH.Quote (QuasiQuoter (..), dataToExpQ)+import Lens.Micro.Extras         (view)+import Prettyprinter             (Pretty)++import Language.Haskell.TH.Syntax+    ( Bang (..)+    , Body (..)+    , Con (..)+    , Dec (..)+    , Exp (..)+    , Match (..)+    , Pat (..)+    , Q+    , SourceStrictness (..)+    , SourceUnpackedness (..)+    , Type (..)+    )++import Language.Haskell.TH.Syntax (DerivClause (..), DerivStrategy (..))++import qualified Data.List                   as List+import qualified Data.Map                    as Map+import qualified Data.Set                    as Set+import qualified Data.Text                   as Text+import qualified Data.Time                   as Time+import qualified Data.Typeable               as Typeable+import qualified Dhall+import qualified Dhall.Core                  as Core+import qualified Dhall.Import+import qualified Dhall.Map+import qualified Dhall.Pretty+import qualified Dhall.Util+import qualified GHC.IO.Encoding+import qualified Language.Haskell.TH.Syntax  as TH+import qualified Numeric.Natural+import qualified Prettyprinter.Render.String as Pretty+import qualified System.IO+++{-| This fully resolves, type checks, and normalizes the expression, so the+    resulting AST is self-contained.++    This can be used to resolve all of an expression’s imports at compile time,+    allowing one to reference Dhall expressions from Haskell without having a+    runtime dependency on the location of Dhall files.++    For example, given a file @".\/Some\/Type.dhall"@ containing++    > < This : Natural | Other : ../Other/Type.dhall >++    ... rather than duplicating the AST manually in a Haskell `Dhall.Type`, you+    can do:++    > Dhall.Type+    > (\case+    >     UnionLit "This" _ _  -> ...+    >     UnionLit "Other" _ _ -> ...)+    > $(staticDhallExpression "./Some/Type.dhall")++    This would create the Dhall Expr AST from the @".\/Some\/Type.dhall"@ file+    at compile time with all imports resolved, making it easy to keep your Dhall+    configs and Haskell interpreters in sync.+-}+staticDhallExpression :: Text -> Q Exp+staticDhallExpression text = do+    TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)++    (expression, status) <- TH.runIO $ do+        parsed <- Dhall.parseWithSettings Dhall.defaultInputSettings text++        (resolved, status) <- Dhall.resolveAndStatusWithSettings Dhall.defaultInputSettings parsed++        _ <- Dhall.typecheckWithSettings Dhall.defaultInputSettings resolved++        let normalized = Dhall.normalizeWithSettings Dhall.defaultInputSettings resolved++        pure (normalized, status)++    forM_ (Dhall.Map.keys (view Dhall.Import.cache status)) $ \chained ->+        case Dhall.Import.chainedImport chained of+            Core.Import+                { importHashed = Core.ImportHashed+                    { importType = Core.Local prefix file+                    }+                } -> do+                    fp <- Dhall.Import.localToPath prefix file+                    TH.addDependentFile fp+            _ -> return ()++    dataToExpQ (fmap liftText . Typeable.cast) expression+  where+    -- A workaround for a problem in TemplateHaskell (see+    -- https://stackoverflow.com/questions/38143464/cant-find-inerface-file-declaration-for-variable)+    liftText = fmap (AppE (VarE 'Text.pack)) . TH.lift . Text.unpack++{-| A quasi-quoter for Dhall expressions.++    This quoter is build on top of 'staticDhallExpression'. Therefore consult the+    documentation of that function for further information.++    This quoter is meant to be used in expression context only; Other contexts+    like pattern contexts or declaration contexts are not supported and will+    result in an error.+-}+dhall :: QuasiQuoter+dhall = QuasiQuoter+    { quoteExp = staticDhallExpression . Text.pack+    , quotePat = const $ error "dhall quasi-quoter: Quoting patterns is not supported!"+    , quoteType = const $ error "dhall quasi-quoter: Quoting types is not supported!"+    , quoteDec = const $ error "dhall quasi-quoter: Quoting declarations is not supported!"+    }++{-| Convert a Dhall type to a Haskell type that does not require any new+    data declarations beyond the data declarations supplied as the first+    argument+-}+toNestedHaskellType+    :: (Eq a, Pretty a)+    => [Var]+    -> [HaskellType (Expr s a)]+    -- ^ All Dhall-derived data declarations+    --+    -- Used to replace complex types with references to one of these+    -- data declarations when the types match+    -> Expr s a+    -- ^ Dhall expression to convert to a simple Haskell type+    -> Q Type+toNestedHaskellType typeParams haskellTypes = loop+  where+    predicate dhallType haskellType = Core.judgmentallyEqual (code haskellType) dhallType++    document dhallType =+      mconcat+      [ "Unsupported nested type\n"+      , "                                                                                \n"+      , "Explanation: Not all Dhall types can be nested within Haskell datatype          \n"+      , "declarations.  Specifically, only the following simple Dhall types are supported\n"+      , "as a nested type inside of a data declaration:                                  \n"+      , "                                                                                \n"+      , "• ❰Bool❱                                                                        \n"+      , "• ❰Double❱                                                                      \n"+      , "• ❰Integer❱                                                                     \n"+      , "• ❰Natural❱                                                                     \n"+      , "• ❰Text❱                                                                        \n"+      , "• ❰Date❱                                                                        \n"+      , "• ❰TimeOfDay❱                                                                   \n"+      , "• ❰TimeZone❱                                                                    \n"+      , "• ❰List a❱     (where ❰a❱ is also a valid nested type)                          \n"+      , "• ❰Optional a❱ (where ❰a❱ is also a valid nested type)                          \n"+      , "• Another matching datatype declaration                                         \n"+      , "• A bound type variable                                                         \n"+      , "                                                                                \n"+      , "The Haskell datatype generation logic encountered the following Dhall type:     \n"+      , "                                                                                \n"+      , " " <> Dhall.Util.insert dhallType <> "\n"+      , "                                                                                \n"+      , "... which did not fit any of the above criteria."+      ]++    message dhallType = Pretty.renderString (Dhall.Pretty.layout (document dhallType))++    loop dhallType = case dhallType of+        Bool ->+            return (ConT ''Bool)++        Double ->+            return (ConT ''Double)++        Integer ->+            return (ConT ''Integer)++        Natural ->+            return (ConT ''Numeric.Natural.Natural)++        Text ->+            return (ConT ''Text)++        Date ->+            return (ConT ''Time.Day)++        Time ->+            return (ConT ''Time.TimeOfDay)++        TimeZone ->+            return (ConT ''Time.TimeZone)++        App List dhallElementType -> do+            haskellElementType <- loop dhallElementType++            return (AppT (ConT ''[]) haskellElementType)++        App Optional dhallElementType -> do+            haskellElementType <- loop dhallElementType++            return (AppT (ConT ''Maybe) haskellElementType)++        App dhallAppType dhallElementType -> do+            haskellAppType <- loop dhallAppType+            haskellElementType <- loop dhallElementType++            return (AppT haskellAppType haskellElementType)++        Var v+            | Just (V param index) <- List.find (v ==) typeParams -> do+                let name = TH.mkName $ (Text.unpack param) ++ (show index)++                return (VarT name)++            | otherwise -> fail $ message v++        _   | Just haskellType <- List.find (predicate dhallType) haskellTypes -> do+                let name = TH.mkName (Text.unpack (typeName haskellType))++                return (ConT name)+            | otherwise -> fail $ message dhallType++-- | A deriving clause for `Generic`.+derivingGenericClause :: DerivClause+derivingGenericClause = DerivClause (Just StockStrategy) [ ConT ''Generic ]++-- | Generates a `FromDhall` instances.+fromDhallInstance+    :: TH.Name -- ^ The name of the type the instances is for+    -> Q Exp       -- ^ A TH splice generating some `Dhall.InterpretOptions`+    -> Q [Dec]+fromDhallInstance n interpretOptions = [d|+    instance FromDhall $(pure $ ConT n) where+        autoWith = Dhall.genericAutoWithInputNormalizer $(interpretOptions)+    |]++-- | Generates a `ToDhall` instances.+toDhallInstance+    :: TH.Name -- ^ The name of the type the instances is for+    -> Q Exp       -- ^ A TH splice generating some `Dhall.InterpretOptions`+    -> Q [Dec]+toDhallInstance n interpretOptions = [d|+    instance ToDhall $(pure $ ConT n) where+        injectWith = Dhall.genericToDhallWithInputNormalizer $(interpretOptions)+    |]++-- | Convert a Dhall type to the corresponding Haskell datatype declaration+toDeclaration+    :: (Eq a, Pretty a)+    => GenerateOptions+    -> [HaskellType (Expr s a)]+    -> HaskellType (Expr s a)+    -> Q [Dec]+toDeclaration generateOptions@GenerateOptions{..} haskellTypes typ =+    case typ of+        SingleConstructor{..} -> uncurry (fromSingle typeName constructorName) $ getTypeParams code+        MultipleConstructors{..} -> uncurry (fromMulti typeName) $ getTypeParams code+    where+        getTypeParams = first numberConsecutive .  getTypeParams_ []++        getTypeParams_ acc (Lam _ (FunctionBinding _ v _ _ _) rest) = getTypeParams_ (v:acc) rest+        getTypeParams_ acc rest = (acc, rest)++        derivingClauses = [ derivingGenericClause | generateFromDhallInstance || generateToDhallInstance ]++        interpretOptions = generateToInterpretOptions generateOptions typ++#if MIN_VERSION_template_haskell(2,21,0)+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) TH.BndrReq+#elif MIN_VERSION_template_haskell(2,17,0)+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) ()+#else+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i))+#endif++        toDataD typeName typeParams constructors = do+            let name = TH.mkName (Text.unpack typeName)++            let params = fmap toTypeVar typeParams++            fmap concat . sequence $+                [pure [DataD [] name params Nothing constructors derivingClauses]] <>+                [ fromDhallInstance name interpretOptions | generateFromDhallInstance ] <>+                [ toDhallInstance name interpretOptions | generateToDhallInstance ]++        fromSingle typeName constructorName typeParams dhallType = do+            constructor <- toConstructor typeParams generateOptions haskellTypes typeName (constructorName, Just dhallType)++            toDataD typeName typeParams [constructor]++        fromMulti typeName typeParams dhallType = case dhallType of+            Union kts -> do+                constructors <- traverse (toConstructor typeParams generateOptions haskellTypes typeName) (Dhall.Map.toList kts)++                toDataD typeName typeParams constructors++            _ -> fail $ message dhallType++        message dhallType = Pretty.renderString (Dhall.Pretty.layout $ document dhallType)++        document dhallType =+            mconcat+                [ "Dhall.TH.makeHaskellTypes: Not a union type\n"+                , "                                                                                \n"+                , "Explanation: This function expects the ❰code❱ field of ❰MultipleConstructors❱ to\n"+                , "evaluate to a union type.                                                       \n"+                , "                                                                                \n"+                , "For example, this is a valid Dhall union type that this function would accept:  \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌──────────────────────────────────────────────────────────────────┐        \n"+                , "    │ Dhall.TH.makeHaskellTypes (MultipleConstructors \"T\" \"< A | B >\") │        \n"+                , "    └──────────────────────────────────────────────────────────────────┘        \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "... which corresponds to this Haskell type declaration:                         \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌────────────────┐                                                          \n"+                , "    │ data T = A | B │                                                          \n"+                , "    └────────────────┘                                                          \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "... but the following Dhall type is rejected due to being a bare record type:   \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌──────────────────────────────────────────────┐                            \n"+                , "    │ Dhall.TH.makeHaskellTypes \"T\" \"{ x : Bool }\" │  Not valid                 \n"+                , "    └──────────────────────────────────────────────┘                            \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "The Haskell datatype generation logic encountered the following Dhall type:     \n"+                , "                                                                                \n"+                , " " <> Dhall.Util.insert dhallType <> "\n"+                , "                                                                                \n"+                , "... which is not a union type."+                ]++-- | Number each variable, starting at 0+numberConsecutive :: [Text.Text] -> [Var]+numberConsecutive = snd . List.mapAccumR go Map.empty . reverse+  where+      go m k =+          let (i, m') = Map.updateLookupWithKey (\_ j -> Just $ j + 1) k m+          in maybe ((Map.insert k 0 m'), (V k 0)) (\i' -> (m', (V k i'))) i++-- | Convert a Dhall type to the corresponding Haskell constructor+toConstructor+    :: (Eq a, Pretty a)+    => [Var]+    -> GenerateOptions+    -> [HaskellType (Expr s a)]+    -> Text+    -- ^ typeName+    -> (Text, Maybe (Expr s a))+    -- ^ @(constructorName, fieldType)@+    -> Q Con+toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do+    let name = TH.mkName (Text.unpack $ constructorModifier constructorName)++    let strictness = if makeStrict then SourceStrict else NoSourceStrictness++    let bang = Bang NoSourceUnpackedness strictness++    case maybeAlternativeType of+        Just dhallType+            | let predicate haskellType =+                    Core.judgmentallyEqual (code haskellType) dhallType+                    && typeName haskellType /= outerTypeName+            , Just haskellType <- List.find predicate haskellTypes -> do+                let innerName =+                        TH.mkName (Text.unpack (typeName haskellType))++                return (NormalC name [ (bang, ConT innerName) ])++        Just (Record kts) -> do+            let process (key, dhallFieldType) = do+                    haskellFieldType <- toNestedHaskellType typeParams haskellTypes dhallFieldType++                    return (TH.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType)++            varBangTypes <- traverse process (Dhall.Map.toList $ Core.recordFieldValue <$> kts)++            return (RecC name varBangTypes)++        Just dhallAlternativeType -> do+            haskellAlternativeType <- toNestedHaskellType typeParams haskellTypes dhallAlternativeType++            return (NormalC name [ (bang, haskellAlternativeType) ])++        Nothing ->+            return (NormalC name [])++-- | Generate a Haskell datatype declaration from a Dhall union type where+-- each union alternative corresponds to a Haskell constructor+--+-- For example, this Template Haskell splice:+--+-- > Dhall.TH.makeHaskellTypeFromUnion "T" "< A : { x : Bool } | B >"+--+-- ... generates this Haskell code:+--+-- > data T = A {x :: GHC.Types.Bool} | B+--+-- This is a special case of `Dhall.TH.makeHaskellTypes`:+--+-- > makeHaskellTypeFromUnion typeName code =+-- >     makeHaskellTypes [ MultipleConstructors{..} ]+makeHaskellTypeFromUnion+    :: Text+    -- ^ Name of the generated Haskell type+    -> Text+    -- ^ Dhall code that evaluates to a union type+    -> Q [Dec]+makeHaskellTypeFromUnion typeName code =+    makeHaskellTypes [ MultipleConstructors{..} ]++-- | Used by `makeHaskellTypes` and `makeHaskellTypesWith` to specify how to+-- generate Haskell types.+data HaskellType code+    -- | Generate a Haskell type with more than one constructor from a Dhall+    -- union type.+    = MultipleConstructors+        { typeName :: Text+        -- ^ Name of the generated Haskell type+        , code :: code+        -- ^ Dhall code that evaluates to a union type+        }+    -- | Generate a Haskell type with one constructor from any Dhall type.+    --+    -- To generate a constructor with multiple named fields, supply a Dhall+    -- record type.  This does not support more than one anonymous field.+    | SingleConstructor+        { typeName :: Text+        -- ^ Name of the generated Haskell type+        , constructorName :: Text+        -- ^ Name of the constructor+        , code :: code+        -- ^ Dhall code that evaluates to a type+        }+    deriving (Functor, Foldable, Traversable)++-- | This data type holds various options that let you control several aspects+-- how Haskell code is generated. In particular you can+--+--   * disable the generation of `FromDhall`/`ToDhall` instances.+--   * modify how a Dhall union field translates to a Haskell data constructor.+data GenerateOptions = GenerateOptions+    { constructorModifier :: Text -> Text+    -- ^ How to map a Dhall union field name to a Haskell constructor.+    -- Note: The `constructorName` of `SingleConstructor` will be passed to this function, too.+    , fieldModifier :: Text -> Text+    -- ^ How to map a Dhall record field names to a Haskell record field names.+    , generateFromDhallInstance :: Bool+    -- ^ Generate a `FromDhall` instance for the Haskell type+    , generateToDhallInstance :: Bool+    -- ^ Generate a `ToDhall` instance for the Haskell type+    , makeStrict :: Bool+    -- ^ Make all fields strict.+    }++-- | A default set of options used by `makeHaskellTypes`. That means:+--+--     * Constructors and fields are passed unmodified.+--     * Both `FromDhall` and `ToDhall` instances are generated.+--+--   Note: `From/ToDhall` should be `False` if importing higher-kinded types.+--   In these cases one should use a standalone declaration.+defaultGenerateOptions :: GenerateOptions+defaultGenerateOptions = GenerateOptions+    { constructorModifier = id+    , fieldModifier = id+    , generateFromDhallInstance = True+    , generateToDhallInstance = True+    , makeStrict = False+    }++-- | This function generates `Dhall.InterpretOptions` that can be used for the+--   marshalling of the Haskell type generated according to the `GenerateOptions`.+--   I.e. those `Dhall.InterpretOptions` reflect the mapping done by+--   `constructorModifier` and `fieldModifier` on the value level.+generateToInterpretOptions :: GenerateOptions -> HaskellType (Expr s a) -> Q Exp+generateToInterpretOptions GenerateOptions{..} haskellType = [| Dhall.InterpretOptions+    { Dhall.fieldModifier = \ $(pure nameP) ->+        $(toCases fieldModifier $ fields haskellType)+    , Dhall.constructorModifier = \ $(pure nameP) ->+        $(toCases constructorModifier $ constructors haskellType)+    , Dhall.singletonConstructors = Dhall.singletonConstructors Dhall.defaultInterpretOptions+    }|]+    where+        constructors :: HaskellType (Expr s a) -> [Text]+        constructors SingleConstructor{..} = [constructorName]+        constructors MultipleConstructors{..} | Union kts <- code = Dhall.Map.keys kts+        constructors _ = []++        fields :: HaskellType (Expr s a) -> [Text]+        fields SingleConstructor{..} | Record kts <- code = Dhall.Map.keys kts+        fields MultipleConstructors{..} | Union kts <- code = Set.toList $ mconcat+            [ Dhall.Map.keysSet kts'+            | (_, Just (Record kts')) <- Dhall.Map.toList kts+            ]+        fields _ = []++        toCases :: (Text -> Text) -> [Text] -> Q Exp+        toCases f xs = do+            err <- [| Core.internalError $ "Unmatched " <> Text.pack (show $(pure nameE)) |]+            pure $ CaseE nameE $ map mkMatch xs <> [Match WildP (NormalB err) []]+            where+                mkMatch n = Match (textToPat $ f n) (NormalB $ textToExp n) []++        nameE :: Exp+        nameE = TH.VarE $ TH.mkName "n"++        nameP :: Pat+        nameP = TH.VarP $ TH.mkName "n"++        textToExp :: Text -> Exp+        textToExp = TH.LitE . TH.StringL . Text.unpack++        textToPat :: Text -> Pat+        textToPat = TH.LitP . TH.StringL . Text.unpack++-- | Generate a Haskell datatype declaration with one constructor from a Dhall+-- type.+--+-- This comes in handy if you need to keep Dhall types and Haskell types in+-- sync.  You make the Dhall types the source of truth and use Template Haskell+-- to generate the matching Haskell type declarations from the Dhall types.+--+-- For example, given this Dhall code:+--+-- > -- ./Department.dhall+-- > < Sales | Engineering | Marketing >+--+-- > -- ./Employee.dhall+-- > { name : Text, department : ./Department.dhall }+--+-- ... this Template Haskell splice:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE DerivingStrategies #-}+-- > {-# LANGUAGE OverloadedStrings  #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > Dhall.TH.makeHaskellTypes+-- >     [ MultipleConstructors "Department" "./tests/th/Department.dhall"+-- >     , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+-- >     ]+--+-- ... generates this Haskell code:+--+-- > data Department = Engineering | Marketing | Sales+-- >   deriving stock (GHC.Generics.Generic)+-- >   deriving anyclass (Dhall.FromDhall, Dhall.ToDhall)+-- >+-- > data Employee+-- >   = MakeEmployee {department :: Department,+-- >                   name :: Data.Text.Internal.Text}+-- >   deriving stock (GHC.Generics.Generic)+-- >   deriving anyclass (Dhall.FromDhall, Dhall.ToDhall)+--+-- Carefully note that the conversion makes a best-effort attempt to+-- auto-detect when a Dhall type (like @./Employee.dhall@) refers to another+-- Dhall type (like @./Department.dhall@) and replaces that reference with the+-- corresponding Haskell type.+--+-- This Template Haskell splice requires you to enable the following extensions:+--+-- * @DeriveGeneric@+-- * @DerivingAnyClass@+-- * @DerivingStrategies@+--+-- By default, the generated types only derive `GHC.Generics.Generic`,+-- `Dhall.FromDhall`, and `Dhall.ToDhall`.  To add any desired instances (such+-- as `Eq`\/`Ord`\/`Show`), you can use the @StandaloneDeriving@ language+-- extension, like this:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE DerivingStrategies #-}+-- > {-# LANGUAGE OverloadedStrings  #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > Dhall.TH.makeHaskellTypes+-- >     [ MultipleConstructors "Department" "./tests/th/Department.dhall"+-- >     , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+-- >     ]+-- >+-- > deriving instance Eq   Department+-- > deriving instance Ord  Department+-- > deriving instance Show Department+-- >+-- > deriving instance Eq   Employee+-- > deriving instance Ord  Employee+-- > deriving instance Show Employee+makeHaskellTypes :: [HaskellType Text] -> Q [Dec]+makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions++-- | Like `makeHaskellTypes`, but with the ability to customize the generated+-- Haskell code by passing `GenerateOptions`.+--+-- For instance, `makeHaskellTypes` is implemented using this function:+--+-- > makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions+makeHaskellTypesWith :: GenerateOptions -> [HaskellType Text] -> Q [Dec]+makeHaskellTypesWith generateOptions haskellTypes = do+    TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)++    haskellTypes' <- traverse (traverse (TH.runIO . Dhall.inputExpr)) haskellTypes++    concat <$> traverse (toDeclaration generateOptions haskellTypes') haskellTypes'
+ src/Dhall/Tags.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}++-- | This module contains the implementation of the @dhall tags@ command++module Dhall.Tags+    ( generate+    ) where++import Control.Exception  (SomeException (..), handle)+import Data.List          (foldl', isSuffixOf)+import Data.Maybe         (fromMaybe)+import Data.Text          (Text)+import Data.Text.Encoding (encodeUtf8)+import Dhall.Map          (foldMapWithKey)+import Dhall.Parser       (exprFromText)+import Dhall.Src          (Src (srcStart))+import Dhall.Syntax       (Binding (..), Expr (..), RecordField (..))+import Dhall.Util         (Input (..))+import System.FilePath    (takeFileName, (</>))+import Text.Megaparsec    (sourceColumn, sourceLine, unPos)++import qualified Data.ByteString  as BS (length)+import qualified Data.Map         as M+import qualified Data.Text        as T+import qualified Data.Text.IO     as TIO+import qualified System.Directory as SD++{-+    Documentation for the etags format is not very informative and not very correct.+    You can find some documentation here:+    https://en.wikipedia.org/wiki/Ctags#Etags_2+    and you can also check the source code here:+    http://cvs.savannah.gnu.org/viewvc/vtags/vtags/vtags.el?view=markup+-}++data LineColumn = LC+    { _lcLine :: Int+      -- ^ line number, starting from 1, where to find the tag+    , _lcColumn :: Int+      -- ^ column of line where tag is+    } deriving (Eq, Ord, Show)++data LineOffset = LO+    { loLine :: Int+      -- ^ line number, starting from 1, where to find the tag+    , loOffset :: Int+      -- ^ byte offset from start of file. Not sure if any editor uses it+    } deriving (Eq, Ord, Show)++newtype Tags = Tags (M.Map FilePath [(LineOffset, Tag)])++instance Semigroup Tags where+    (Tags ts1) <> (Tags ts2) = Tags (M.unionWith (<>) ts1 ts2)++instance Monoid Tags where+    mempty = Tags M.empty++{-| For example, for the line: @let foo = \"foo\"@ the tag is:+    > Tag "let " "foo"+-}+data Tag = Tag+    { tagPattern :: Text+      -- ^ In vtags source code this field is named \"pattern\" and EMacs used it as+      --   a regex pattern to locate line with tag. It's looking for ^<tag pattern>.+      --   Looks like vi is not using it.+    , tagName :: Text+      -- ^ text, that editor compare with selected text. So it's really name of entity+    } deriving (Show)++type LineNumber = Int++type ByteOffset = Int++{-| Generate etags for Dhall expressions+-}+generate+    :: Input+    -- ^ Where to look for files. This can be a directory name (@.@ for example),+    --   a file name or `StandardInput`. If `StandardInput`, then this will wait for+    --   file names from @STDIN@.+    --   This way someone can combine tools in @bash@ to send, for example, output from+    --   @find@ to the input of @dhall tags@.+    -> Maybe [Text]+    -- ^ List of suffixes for dhall files or Nothing to check all files+    -> Bool+    -- ^ Flag if `generate` should follow symlinks+    -> IO Text+    -- ^ Content for tags file+generate inp sxs followSyms = do+    files <- inputToFiles followSyms (map T.unpack <$> sxs) inp+    tags <- traverse (\f -> handle (\(SomeException _) -> return mempty)+                                   (fileTags f <$> TIO.readFile f)) files+    return (showTags . mconcat $ tags)++{-| Find tags in Text (second argument) and generates a list of them+    To make tags for filenames that works in both emacs and vi, add two initial tags.+    First for @filename@ for vi and second with @/filename@ for emacs.+    Other tags are working for both.+-}+fileTags :: FilePath -> Text -> Tags+fileTags f t = Tags (M.singleton f+                    (initialMap <> getTagsFromText t))+    where initialViTag = (LO 1 1, Tag "" (T.pack . takeFileName $ f))+          initialEmacsTag = (LO 1 1, Tag "" ("/" <> (T.pack . takeFileName) f))+          initialMap = [initialViTag, initialEmacsTag]++getTagsFromText :: Text -> [(LineOffset, Tag)]+getTagsFromText t = case exprFromText "" t of+    Right expr -> fixPosAndDefinition t (getTagsFromExpr expr)+    _ -> mempty++{-| Used to update tag position and to build tag from term.+    After getTagsFromExpr line and column in line are in @LineColumn@ for each tag.+    And tagPattern is not added.+    Emacs use tag pattern to check if tag is on line. It compares line from start+    with tag pattern and in case they are the same, relocate user.+    fixPosAndDefinition change position to line and byte offset (@LineOffset@) and+    add tag pattern. For example, for Dhall string:++    >>> let dhallSource = "let foo = \"bar\"\nlet baz = \"qux\""++    Input for this function is:++    >>> foundTerms = [(LC 1 4, "foo"), (LC 2 4, "baz")]++    And:++    >>> fixPosAndDefinition dhallSource foundTerms+    [(LO {loLine = 1, loOffset = 5},Tag {tagPattern = "let foo ", tagName = "foo"}),(LO {loLine = 2, loOffset = 21},Tag {tagPattern = "let baz ", tagName = "baz"})]++    where 21 is byte offset from file start.+-}+fixPosAndDefinition :: Text -> [(LineColumn, Text)] -> [(LineOffset, Tag)]+fixPosAndDefinition t = foldMap (\(LC ln c, term) ->+             let (ln', offset, tPattern) = fromMaybe (fallbackInfoForText ln c)+                                                     (infoForText term ln)+             in [(LO ln' offset, Tag tPattern term)])+    where mls :: M.Map Int (Text, Int)+          -- ^ mls is map that for each line has length of file before this map and line content.+          --   In example above, first line is 15 bytes long and '\n', mls contain:+          --   (1, (16, "let foo = "bar"")+          --   That allow us to get byte offset easier.+          mls = M.fromList . fst . foldl' processLine ([], 0) . zip [1..] $ T.lines t++          {-| processLine is a worker for `foldl` that generates the list of lines with+              byte offsets from the start of the first line from a list of lines+          -}+          processLine+              :: ([(LineNumber, (Text, ByteOffset))], ByteOffset)+              -- ^ previous result and byte offset for the start of current line+              -> (LineNumber, Text)+              -> ([(LineNumber, (Text, ByteOffset))], ByteOffset)+              -- ^ next result, where new line was added and byte offset for next line+          processLine (numberedLinesWithSizes, bytesBeforeLine) (n, line) =+              ((n, (line, bytesBeforeLine)): numberedLinesWithSizes, bytesBeforeNextLine)+              where bytesBeforeNextLine = bytesBeforeLine + lengthInBytes line + 1++          lineFromMap ln = fromMaybe ("", 0) (ln `M.lookup` mls)++          lengthInBytes = BS.length . encodeUtf8++          {-| get information about term from map of lines+              In most cases, @LineColumn@ after `getTagsFromExpr` points to byte before term.+              It's better to have term in term pattern, so this function finds and updates+              line number and byte offset and generate pattern.+          -}+          infoForText+              :: Text+              -- ^ term to find+              -> Int+              -- ^ line where to start+              -> Maybe (Int, Int, Text)+              -- ^ (Line number, byte offset, pattern to find term in file)+          infoForText term ln+              | ln <= 0 = Nothing+              | T.null part2 = infoForText term (ln - 1)+              | otherwise = Just (ln, lsl + 1 + lengthInBytes part1, part1 <> termAndNext)+              where (l, lsl) = lineFromMap ln+                    (part1, part2) = T.breakOn term l+                    termAndNext = T.take (T.length term + 1) part2++          fallbackInfoForText ln c = (ln, lsl + 1 + lengthInBytes pat, pat)+              where (l, lsl) = lineFromMap ln+                    pat = T.take c l++getTagsFromExpr :: Expr Src a -> [(LineColumn, Text)]+getTagsFromExpr = go (LC 0 0) []+    where go lpos mts = \case+              (Let b e) -> go lpos (mts <> parseBinding lpos b) e+              (Annot e1 e2) -> go lpos (go lpos mts e1) e2+              (Record mr) -> mts <> tagsFromDhallMap lpos (recordFieldValue <$> mr)+              (RecordLit mr) -> mts <> tagsFromDhallMap lpos (recordFieldValue <$> mr)+              (Union mmr) -> mts <> tagsFromDhallMapMaybe lpos mmr+              (Note s e) -> go (srcToLineColumn s) mts e+              _ -> mts++          tagsFromDhallMap lpos = foldMapWithKey (tagsFromDhallMapElement lpos)++          tagsFromDhallMapMaybe lpos = foldMapWithKey (\k -> \case+              Just e -> tagsFromDhallMapElement lpos k e+              _ -> [(lpos, k)])++          tagsFromDhallMapElement lpos k e = go pos [(pos, k)] e+              where pos = firstPosFromExpr lpos e++          parseBinding :: LineColumn -> Binding Src a -> [(LineColumn, Text)]+          parseBinding lpos b = go p2 [(p0, variable b)] (value b)+              where p0 = posFromBinding (bindingSrc0 b) lpos+                    p1 = posFromBinding (bindingSrc1 b) p0+                    p2 = posFromBinding (bindingSrc2 b) p1+          posFromBinding src startPos = maybe startPos srcToLineColumn src++srcToLineColumn :: Src -> LineColumn+srcToLineColumn s = LC line column+    where ssp = srcStart s+          line = unPos . sourceLine $ ssp+          column = unPos . sourceColumn $ ssp++firstPosFromExpr :: LineColumn -> Expr Src a -> LineColumn+firstPosFromExpr lpos = \case+    (Note s _) -> srcToLineColumn s+    _ -> lpos++showTags :: Tags -> Text+showTags (Tags ts) = T.concat . map (uncurry showFileTags) . M.toList $ ts++showFileTags :: FilePath -> [(LineOffset, Tag)] -> T.Text+showFileTags f ts = "\x0c\n" <> T.pack f <> "," <> (showInt . T.length) cs <> "\n" <> cs+    where cs = T.concat . map (uncurry showPosTag) $ ts++showPosTag :: LineOffset -> Tag -> Text+showPosTag lo tag = def <>"\x7f" <> name <> "\x01" <> showInt line <>+                    "," <> showInt offset <> "\n"+    where line = loLine lo+          offset = loOffset lo+          def = tagPattern tag+          name = tagName tag++showInt :: Int -> Text+showInt = T.pack . show++{-| Generate list of files for a given `Input`+-}+inputToFiles+    :: Bool+    -- ^ If `True`, this function will follow  symbolic links+    -> Maybe [String]+    -- ^ List of suffixes. If `Nothing`, all files will be returned.+    --   This parameter only works when the `Input` is an `InputFile` and point to a directory.+    -> Input+    -> IO [ FilePath ]+    --   List of files.+inputToFiles _ _ StandardInput = lines <$> getContents+inputToFiles followSyms suffixes (InputFile path) = go path+    where go p = do+                   isD <- SD.doesDirectoryExist p+                   isSL <- isSymLink+                   if isD+                     then if isSL && not followSyms+                            then return []+                            else do+                                   -- filter . .. and hidden files .*+                                   contents <- fmap (filter ((/=) '.' . head))+                                                    (SD.getDirectoryContents p)+                                   concat <$> mapM (go . (</>) p) contents+                     else return [p | matchingSuffix || p == path]+               where matchingSuffix = maybe True (any (`isSuffixOf` p)) suffixes+                     isSymLink = SD.pathIsSymbolicLink p
src/Dhall/Tutorial.hs view
@@ -1,2721 +1,2319 @@ {-# OPTIONS_GHC -fno-warn-unused-imports #-}--{-| Dhall is a programming language specialized for configuration files.  This-    module contains a tutorial explaning how to author configuration files using-    this language--}-module Dhall.Tutorial (-    -- * Introduction-    -- $introduction--    -- * Types-    -- $types--    -- * Imports-    -- $imports--    -- * Lists-    -- $lists--    -- * Optional values-    -- $optional0--    -- * Records-    -- $records--    -- * Functions-    -- $functions--    -- * Compiler-    -- $compiler--    -- * Strings-    -- $strings--    -- * Combine-    -- $combine--    -- * Let expressions-    -- $let--    -- * Unions-    -- $unions--    -- * Polymorphic functions-    -- $polymorphic--    -- * Total-    -- $total--    -- * Headers-    -- $headers--    -- * Import integrity-    -- $integrity--    -- * Raw text-    -- $rawText--    -- * Formatting code-    -- $format--    -- * Built-in functions-    -- $builtins--    -- ** Caveats-    -- $caveats--    -- ** Overview-    -- $builtinOverview--    -- ** @Bool@-    -- $bool--    -- *** @(||)@-    -- $or--    -- *** @(&&)@-    -- $and--    -- *** @(==)@-    -- $equal--    -- *** @(!=)@-    -- $unequal--    -- *** @if@\/@then@\/@else@-    -- $ifthenelse--    -- ** @Natural@-    -- $natural--    -- *** @(+)@-    -- $plus--    -- *** @(*)@-    -- $times--    -- *** @Natural/even@-    -- $even--    -- *** @Natural/odd@-    -- $odd--    -- *** @Natural/isZero@-    -- $isZero--    -- *** @Natural/fold@-    -- $naturalFold--    -- *** @Natural/build@-    -- $naturalBuild--    -- ** @Integer@-    -- $integer--    -- ** @Double@-    -- $double--    -- ** @Text@-    -- $text--    -- *** @(++)@-    -- $textAppend--    -- ** @List@-    -- $list--    -- *** @(#)@-    -- $listAppend--    -- *** @List/fold@-    -- $listFold--    -- *** @List/build@-    -- $listBuild--    -- *** @List/length@-    -- $listLength--    -- *** @List/head@-    -- $listHead--    -- *** @List/last@-    -- $listLast--    -- *** @List/indexed@-    -- $listIndexed--    -- *** @List/reverse@-    -- $listReverse--    -- ** @Optional@-    -- $optional1--    -- *** @Optional/fold@-    -- $optionalFold--    -- * Prelude-    -- $prelude--    -- * Conclusion-    -- $conclusion--    -- * Frequently Asked Questions (FAQ)-    -- $faq-    ) where--import Data.Vector (Vector)-import Dhall---- $introduction------ The simplest way to use Dhall is to ignore the programming language features--- and use it as a strongly typed configuration format.  For example, suppose--- that you create the following configuration file:--- --- > $ cat ./config--- > { foo = 1--- > , bar = [3.0, 4.0, 5.0]--- > }--- --- You can read the above configuration file into Haskell using the following--- code:--- --- > -- 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)--- --- If you compile and run the above example, the program prints the corresponding--- Haskell record:--- --- > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ You can also load some types directly into Haskell without having to define a--- record, like this:------ > >>> :set -XOverloadedStrings--- > >>> input auto "True" :: IO Bool--- > True------ The `input` function can decode any value if we specify the value's expected--- `Type`:------ > input--- >     :: Type a  -- Expected type--- >     -> Text    -- Dhall program--- >     -> IO a    -- Decoded expression------ ... and we can either specify an explicit type like `bool`:------ > bool :: Type Bool--- > --- > input bool :: Text -> IO Bool--- >--- > input bool "True" :: IO Bool--- >--- > >>> input bool "True"--- > True------ ... or we can use `auto` to let the compiler infer what type to decode from--- the expected return type:------ > auto :: Interpret a => Type a--- >--- > input auto :: Interpret a => Text -> IO a--- >--- > >>> input auto "True" :: IO Bool--- > True------ You can see what types `auto` supports \"out-of-the-box\" by browsing the--- instances for the `Interpret` class.  For example, the following instance--- says that we can directly decode any Dhall expression that evaluates to a--- @Bool@ into a Haskell `Bool`:------ > instance Interpret Bool------ ... which is why we could directly decode the string @\"True\"@ into the--- value `True`.------ There is also another instance that says that if we can decode a value of--- type @a@, then we can also decode a @List@ of values as a `Vector` of @a@s:------ > instance Interpret a => Interpret (Vector a)------ Therefore, since we can decode a @Bool@, we must also be able to decode a--- @List@ of @Bool@s, like this:------ > >>> input auto "[True, False]" :: IO (Vector Bool)--- > [True,False]------ We could also specify what type to decode by providing an explicit `Type`--- instead of using `auto` with a type annotation:------ > >>> input (vector bool) "[True, False]"--- > [True, False]------ __Exercise:__ Create a @./config@ file that the following program can decode:------ > {-# LANGUAGE DeriveGeneric     #-}--- > {-# LANGUAGE OverloadedStrings #-}--- > --- > import Dhall--- > --- > data Person = Person { age :: Integer, name :: Text }--- >     deriving (Generic, Show)--- > --- > instance Interpret Person--- > --- > main :: IO ()--- > main = do--- >     x <- input auto "./config"--- >     print (x :: Person)------ __Exercise:__ Create a @./config@ file that the following program can decode:------ > {-# LANGUAGE OverloadedStrings #-}--- > --- > import Data.Functor.Identity--- > import Dhall--- > --- > instance Interpret a => Interpret (Identity a)--- > --- > main :: IO ()--- > main = do--- >     x <- input auto "./config"--- >     print (x :: Identity Double)---- $types------ Suppose that we try to decode a value of the wrong type, like this:------ > >>> input auto "1" :: IO Bool--- > *** Exception: --- > Error: Expression doesn't match annotation--- > --- > 1 : Bool--- > --- > (input):1:1------ The interpreter complains because the string @\"1\"@ cannot be decoded into a--- Haskell value of type `Bool`.------ The code excerpt from the above error message has two components:------ * the expression being type checked (i.e. @1@)--- * the expression's expected type (i.e. @Bool@)------ > Expression--- > ⇩--- > 1 : Bool--- >     ⇧--- >     Expected type------ The @(:)@ symbol is how Dhall annotates values with their expected types.--- This notation is equivalent to type annotations in Haskell using the @(::)@--- symbol.  Whenever you see:------ > x : t------ ... you should read that as \"we expect the expression @x@ to have type--- @t@\". However, we might be wrong and if our expected type does not match the--- expression's actual type then the type checker will complain.------ In this case, the expression @1@ does not have type @Bool@ so type checking--- fails with an exception.------ __Exercise:__ Load the Dhall library into @ghci@ and run these commands to get--- get a more detailed error message:------ > >>> import Dhall--- > >>> :set -XOverloadedStrings--- > >>> detailed (input auto "1") :: IO Bool--- > ...------ ... then read the entire error message------ __Exercise:__ Fix the type error, either by changing the value to decode or--- changing the expected type---- $imports------ You might wonder why in some cases we can decode a configuration file:------ > >>> writeFile "bool" "True"--- > >>> input auto "./bool" :: IO Bool--- > True------ ... and in other cases we can decode a value directly:------ > >>> input auto "True" :: IO Bool--- > True------ This is because importing a configuration from a file is a special case of a--- more general language feature: Dhall expressions can reference other--- expressions by their file path.------ To illustrate this, let's create three files:--- --- > $ echo "True"  > bool1--- > $ echo "False" > bool2--- > $ echo "./bool1 && ./bool2" > both------ ... and read in all three files in a single expression:--- --- > >>> input auto "[ ./bool1 , ./bool2 , ./both ]" :: IO (Vector Bool)--- > [True,False,False]------ Each file path is replaced with the Dhall expression contained within that--- file.  If that file contains references to other files then those references--- are transitively resolved.------ In other words: configuration files can reference other configuration files,--- either by their relative or absolute paths.  This means that we can split a--- configuration file into multiple files, like this:------ > $ cat > ./config <<EOF--- > { foo = 1--- > , bar = ./bar--- > }--- > EOF------ > $ echo "[3.0, 4.0, 5.0]" > ./bar------ > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ However, the Dhall language will forbid cycles in these file references.  For--- example, if we create the following cycle:------ > $ echo './file1' > file2--- > $ echo './file2' > file1------ ... then the interpreter will reject the import:------ > >>> input auto "./file1" :: IO Integer--- > *** Exception: --- > ↳ ./file1--- >   ↳ ./file2--- >--- > Cyclic import: ./file1------ You can also import expressions by URL.  For example, you can find a Dhall--- expression hosted at this URL using @ipfs@:------ <https://ipfs.io/ipfs/QmVf6hhTCXc9y2pRvhUmLk3AZYEgjeAz5PNwjt1GBYqsVB>------ > $ curl https://ipfs.io/ipfs/QmVf6hhTCXc9y2pRvhUmLk3AZYEgjeAz5PNwjt1GBYqsVB--- > True------ ... and you can reference that expression either directly:------ > >>> input auto "https://ipfs.io/ipfs/QmVf6hhTCXc9y2pRvhUmLk3AZYEgjeAz5PNwjt1GBYqsVB" :: IO Bool--- > True--- --- ... or inside of a larger expression:------ > >>> input auto "False == https://ipfs.io/ipfs/QmVf6hhTCXc9y2pRvhUmLk3AZYEgjeAz5PNwjt1GBYqsVB" :: IO Bool--- > False------ You're not limited to hosting Dhall expressions on @ipfs@.  You can host a--- Dhall expression anywhere that you can host UTF8-encoded text on the web, such--- as Github, a pastebin, or your own web server.------ You can also import Dhall expressions from environment variables, too:------ > >>> System.Environment.setEnv "FOO" "1"--- > >>> input auto "env:FOO" :: IO Integer--- > 1------ You can import types, too.  For example, we can change our @./bar@ file to:------ > $ echo "[3.0, 4.0, 5.0] : List ./type" > ./bar------ ... then specify the @./type@ in a separate file:------ > $ echo "Double" > ./type------ ... and everything still type checks:------ > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ Note that all imports must be terminated by whitespace or you will get either--- an import error or a parse error, like this:------ > >>> writeFile "baz" "2.0"--- > >>> input auto "./baz: Double" :: IO Double--- > *** Exception: --- > ↳ ./baz: --- > --- > Error: Missing file------ This is because the parser thinks that @./baz:@ is a single token due to--- the missing whitespace before the colon and tries to import a file named--- @./baz:@, which does not exist.  To fix the problem we have to add a space--- after @./baz@:------ > >>> input auto "./baz : Double" :: IO Double--- > 2.0------ __Exercise:__ There is a @not@ function hosted online here:------ <https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not>------ Visit that link and read the documentation.  Then try to guess what this--- code returns:------ > >>> input auto "https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not https://ipfs.io/ipfs/QmVf6hhTCXc9y2pRvhUmLk3AZYEgjeAz5PNwjt1GBYqsVB" :: IO Bool--- > ???------ Run the code to test your guess---- $lists------ You can store 0 or more values of the same type in a list, like this:------ > [1, 2, 3]------ Every list can be followed by the type of the list.  The type annotation is--- required for empty lists but optional for non-empty lists.  You will get a--- type error if you provide an empty list without a type annotation:------ > >>> input auto "[]" :: IO (Vector Integer)--- > *** Exception: --- > Error: Empty lists need a type annotation--- > --- > []--- > --- > (input):1:1--- > >>> input auto "[] : List Integer" :: IO (Vector Integer)--- > []------ Also, list elements must all have the same type.  You will get an error if--- you try to store elements of different types in a list:------ > >>> input auto "[1, True, 3]" :: IO (Vector Integer)--- > *** Exception: --- > Error: List elements should have the same type--- > --- > [1, True, 3]--- > --- > (input):1:1------ __Exercise:__ What is the shortest @./config@ file that you can decode using--- this command:------ > >>> input auto "./config" :: IO (Vector (Vector Integer))---- $optional0------ @Optional@ values are exactly like lists except they can only hold 0 or 1--- elements.  They cannot hold 2 or more elements:------ For example, these are valid @Optional@ values:------ > [1] : Optional Integer--- >--- > []  : Optional Integer------ ... but this is /not/ valid:------ > [1, 2] : Optional Integer  -- NOT valid------ An @Optional@ corresponds to Haskell's `Maybe` type for decoding purposes:------ > >>> input auto "[1] : Optional Integer" :: IO (Maybe Integer)--- > Just 1--- > >>> input auto "[] : Optional Integer" :: IO (Maybe Integer)--- > Nothing------ You cannot omit the type annotation for @Optional@ values.  The type--- annotation is mandatory------ __Exercise:__ What is the shortest possible @./config@ file that you can decode--- like this:------ > >>> input auto "./config" :: IO (Maybe (Maybe (Maybe Integer)))--- > ???------ __Exercise:__ Try to decode an @Optional@ value with more than one element and--- see what happens---- $records------ Record literals are delimited by curly braces and their fields are separated--- by commas.  For example, this is a valid record literal:------ > { foo = True--- > , bar = 2--- > , baz = 4.2--- > }------ A record type is like a record literal except instead of specifying each--- field's value we specify each field's type.  For example, the preceding--- record literal has the following record type:------ > { foo : Bool--- > , bar : Integer--- > , baz : Double--- > }------ If you want to specify an empty record literal, you must use @{=}@, which is--- special syntax reserved for empty records.  If you want to specify the empty--- record type, then you use @{}@.  If you forget which is which you can always--- ask the @dhall@ compiler to remind you of the type for each one:------ > $ dhall--- > {=}--- > <Ctrl-D>--- > {}--- > --- > {=}------ > $ dhall--- > {}--- > <Ctrl-D>--- > Type--- > --- > {}------ You can access a field of a record using the following syntax:------ > record.fieldName------ ... which means to access the value of the field named @fieldName@ from the--- @record@.  For example:------ > >>> input auto "{ foo = True, bar = 2, baz = 4.2 }.baz" :: IO Double--- > 4.2------ __Exercise__: What is the type of this record:------ > { foo = 1--- > , bar =--- >     { baz = 2.0--- >     , qux = True--- >     }--- > }------ __Exercise__: Save the above code to a file named @./record@ and then try to--- access the value of the @baz@ field---- $functions------ The Dhall programming language also supports user-defined anonymous--- functions.  For example, we can save the following anonymous function to a--- file:------ > $ cat > makeBools--- > \(n : Bool) ->--- >     [ n && True, n && False, n || True, n || False ]--- > <Ctrl-D>------ ... or we can use Dhall's support for Unicode characters to use @λ@ (U+03BB)--- instead of @\\@ and @→@ (U+2192) instead of @->@ (for people who are into that--- sort of thing):------ > $ cat > makeBools--- > λ(n : Bool) →--- >     [ n && True, n && False, n || True, n || False ]--- > <Ctrl-D>------ You can read this as a function of one argument named @n@ that has type--- @Bool@.  This function returns a @List@ of @Bool@s.  Each element of the--- @List@ depends on the input argument named @n@.------ The (ASCII) syntax for anonymous functions resembles the syntax for anonymous--- functions in Haskell.  The only difference is that Dhall requires you to--- annotate the type of the function's input.------ You can import this function into Haskell, too:------ >>> makeBools <- input auto "./makeBools" :: IO (Bool -> Vector Bool)--- >>> makeBools True--- [True,False,True,True]------ The reason this works is that there is an `Interpret` instance for simple--- functions:------ > instance (Inject a, Interpret b) => Interpret (a -> b)------ Thanks to currying, this instance works for functions of multiple simple--- arguments:------ >>> dhallAnd <- input auto "λ(x : Bool) → λ(y : Bool) → x && y" :: IO (Bool -> Bool -> Bool)--- >>> dhallAnd True False--- False------ However, you can't convert anything more complex than that (like a polymorphic--- or higher-order function).  You will need to apply those functions to their--- arguments within Dhall before converting their result to a Haskell value.------ Just like `Interpret`, you can derive `Inject` for user-defined data types:------ > {-# LANGUAGE DeriveAnyClass    #-}--- > {-# LANGUAGE DeriveGeneric     #-}--- > {-# LANGUAGE OverloadedStrings #-}--- > --- > module Main where--- > --- > import Dhall--- > --- > data Example0 = Example0 { foo :: Bool, bar :: Bool }--- >     deriving (Generic, Inject)--- > --- > main = do--- >     f <- input auto "λ(r : { foo : Bool, bar : Bool }) → r.foo && r.bar"--- >     print (f (Example0 { foo = True, bar = False }) :: Bool)--- >     print (f (Example0 { foo = True, bar = True  }) :: Bool)------ The above program prints:------ > False--- > True---- $compiler------ We can also test our @makeBools@ function directly from the command line.--- This library comes with a command-line executable program named @dhall@ that--- you can use to both type-check files and convert them to a normal form.  Our--- compiler takes a program on standard input and then prints the program's type--- to standard error followed by the program's normal form to standard output:------ > $ dhall--- > ./makeBools--- > <Ctrl-D>--- > ∀(n : Bool) → List Bool--- > --- > λ(n : Bool) → [n && True, n && False, n || True, n || False]------ The first line says that @makeBools@ is a function of one argument named @n@--- that has type @Bool@ and the function returns a @List@ of @Bool@s.  The @∀@--- (U+2200) symbol is shorthand for the ASCII @forall@ keyword:------ > ∀(x : a) → b        -- This type ...--- > --- > forall (x : a) → b  -- ... is the same as this type------ ... and Dhall's @forall@ keyword behaves the same way as Haskell's @forall@--- keyword for input values that are @Type@s:------ > forall (x : Type) → b  -- This Dhall type ...--- --- > forall x . b           -- ... is the same as this Haskell type------ The part where Dhall differs from Haskell is that you can also use--- @∀@/@forall@ to give names to non-@Type@ arguments (such as the first--- argument to @makeBools@).------ The second line of Dhall's output is our program's normal form:------ > λ(n : Bool) → [n && True, n && False, n || True, n || False]------ ... which in this case happens to be identical to our original program.------ To apply a function to an argument you separate the function and argument by--- whitespace (just like Haskell):------ @f x@------ You can read the above as \"apply the function @f@ to the argument @x@\".  This--- means that we can \"apply\" our @./makeBools@ function to a @Bool@ argument--- like this:------ > $ dhall--- > ./makeBools True--- > <Ctrl-D>--- > List Bool--- > --- > [True, False, True, True]------ Remember that file paths are synonymous with their contents, so the above--- code is exactly equivalent to:--- --- > $ dhall--- > (λ(n : Bool) → [n && True, n && False, n || True, n || False]) True--- > <Ctrl-D>--- > List Bool--- > --- > [True, False, True, True]------ When you apply an anonymous function to an argument, you substitute the--- \"bound variable" with the function's argument:------ >    Bound variable--- >    ⇩--- > (λ(n : Bool) → ...) True--- >                     ⇧--- >                     Function argument------ So in our above example, we would replace all occurrences of @n@ with @True@,--- like this:------ > -- If we replace all of these `n`s with `True` ...--- > [n && True, n && False, n || True, n || False]--- >--- > -- ... then we get this:--- > [True && True, True && False, True || True, True || False]--- >--- > -- ... which reduces to the following normal form:--- > [True, False, True, True]------ Now that we've verified that our function type checks and works, we can use--- the same function within Haskell:------ > >>> input auto "./makeBools True" :: IO (Vector Bool)--- > [True,False,True,True]------ __Exercise__: Create a file named @getFoo@ that is a function of the following--- type:------ > ∀(r : { foo : Bool, bar : Text }) → Bool------ This function should take a single input argument named @r@ that is a record--- with two fields.  The function should return the value of the @foo@ field.------ __Exercise__: Use the @dhall@ compiler to infer the type of the function you--- just created and verify that your function has the correct type------ __Exercise__: Use the @dhall@ compiler to apply your function to a sample--- record---- $strings--- Dhall supports ordinary string literals with Haskell-style escaping rules:------ > dhall--- > "Hello, \"world\"!"--- > <Ctrl-D>--- > Text--- >--- > "Hello, \"world\"!"------ ... and Dhall also supports Nix-style multi-line string literals:------ > dhall--- > ''--- >     #!/bin/bash--- >     --- >     echo "Hi!"--- > ''--- > <Ctrl-D>--- > Text--- >--- > "\n#!/bin/bash\n\necho \"Hi!\"\n"------ These \"double single quote strings\" ignore all special characters, with one--- exception: if you want to include a @''@ in the string, you will need to--- escape it with a preceding @'@ (i.e. use @'''@ to insert @''@ into the final--- string).------ These strings also strip leading whitespace using the same rules as Nix.--- Specifically: \"it strips from each line a number of spaces equal to the--- minimal indentation of the string as a whole (disregarding the indentation--- of empty lines).\"------ You can also interpolate expressions into strings using @${...}@ syntax.  For--- example:------ > $ dhall--- >     let name = "John Doe"--- > in  let age  = 21--- > in  "My name is ${name} and my age is ${Integer/show age}"--- > <Ctrl-D>--- > Text--- >--- > "My name is John Doe and my age is 21"------ Note that you can only interpolate expressions of type @Text@------ If you need to insert a @"${"@ into a string without interpolation then use--- @"''${"@ (same as Nix)------ > ''--- >     for file in *; do--- >       echo "Found ''${file}"--- >     done--- > ''---- $combine------ You can combine two records, using either the @(//)@ operator or the--- @(/\\)@ operator.------ The @(//)@ operator (or @(⫽)@ U+2AFD) combines the fields of both records,--- preferring fields from the right record if they share fields in common:------ > $ dhall--- > { foo = 1, bar = "ABC" } // { baz = True }--- > <Ctrl-D>--- > { bar : Text, baz : Bool, foo : Integer }--- > --- > { bar = "ABC", baz = True, foo = 1 }--- > $ dhall--- > { foo = 1, bar = "ABC" } ⫽ { bar = True }  -- Fancy unicode--- > <Ctrl-D>--- > { bar : Bool, foo : Integer }--- > --- > { bar = True, foo = 1 }------ Note that the order of record fields does not matter.  The compiler--- automatically sorts the fields.------ The @(/\\)@ operator (or @(∧)@ U+2227) also lets you combine records, but--- behaves differently if the records share fields in common.  The operator--- combines shared fields recursively if they are both records:------ > $ dhall--- > { foo = { bar = True }, baz = "ABC" } /\ { foo = { qux = 1.0 } }--- > <Ctrl-D>--- > { baz : Text, foo : { bar : Bool, qux : Double } }--- > --- > { baz = "ABC", foo = { bar = True, qux = 1.0 } }------ ... but fails with a type error if either shared field is not a record:------ > $ dhall--- > { foo = 1, bar = "ABC" } ∧ { foo = True }--- > <Ctrl-D>--- > Use "dhall --explain" for detailed errors--- > --- > Error: Field collision--- > --- > { foo = 1, bar = "ABC" } ∧ { foo = True }--- > --- > (stdin):1:1------ __Exercise__: Combine any record with the empty record.  What do you expect--- to happen?---- $let------ Dhall also supports @let@ expressions, which you can use to define--- intermediate values in the course of a computation, like this:------ > $ dhall--- > let x = "ha" in x ++ x--- > <Ctrl-D>--- > Text--- >--- > "haha"------ You can also annotate the types of values defined within a @let@ expression,--- like this:------ > $ dhall--- > let x : Text = "ha" in x ++ x--- > <Ctrl-D>--- > Text--- >--- > "haha"------ You need to nest @let@ expressions if you want to define more than one value--- in this way:------ > $ dhall--- >     let x = "Hello, "--- > in  let y = "world!"--- > in  x ++ y--- > <Ctrl-D>--- > Text--- > --- > "Hello, world!"------ Dhall is whitespace-insensitive, so feel free to format things over multiple--- lines or indent in any way that you please.------ If you want to define a named function, just give a name to an anonymous--- function:------ > $ dhall--- > let twice = λ(x : Text) → x ++ x in twice "ha"--- > <Ctrl-D>--- > Text--- > --- > "haha"------ Unlike Haskell, Dhall does not support function arguments on the left-hand--- side of the equals sign, so this will not work:------ > $ dhall--- > let twice (x : Text) = x ++ x in twice "ha"--- > <Ctrl-D>--- > (stdin):1:11: error: expected: ":",--- >     "="--- > let twice (x : Text) = x ++ x in twice "ha" --- >           ^------ The error message says that Dhall expected either a @(:)@ (i.e. the beginning--- of a type annotation) or a @(=)@ (the beginning of the assignment) and not a--- function argument.------ You can also use @let@ expressions to rename imports, like this:------ > $ dhall--- > let not = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not--- > in  not True--- > <Ctrl-D>--- > Bool--- > --- > False------ ... or to define synonyms for types:------ > $ dhall <<< 'let Name : Type = Text in [ "John", "Mary" ] : List Name'--- > List Text--- > --- > [ "John", "Mary" ]------ __Exercise:__ What do you think the following code will normalize to?------ >     let x = 1--- > in  let x = 2--- > in  x------ Test your guess using the @dhall@ compiler------ __Exercise:__ Now try to guess what this code will normalize to:------ >     let x = "ha"--- > in  let x = x ++ "ha"--- > in  x------ __Exercise:__ What about this code?------ > let x = x ++ "ha"--- > in  x---- $unions------ A union is a value that can be one of many alternative types of values.  For--- example, the following union type:------ > < Left : Natural | Right : Bool >------ ... represents a value that can be either a @Natural@ or a @Bool@ value.  If--- you are familiar with Haskell these are exactly analogous to Haskell's--- \"sum types\".------ Each alternative is associated with a tag that distinguishes that alternative--- from other alternatives.  In the above example, the @Left@ tag is used for--- the @Natural@ alternative and the @Right@ tag is used for the @Bool@--- alternative.------ A union literal specifies the value of one alternative and the types of the--- remaining alternatives.  For example, both of the following union literals--- have the same type, which is the above union type:------ > < Left  = +0   | Right : Bool    >------ > < Right = True | Left  : Natural >------ You can consume a union using the built-in @merge@ function.  For example,--- suppose we want to convert our union to a @Bool@ but we want to behave--- differently depending on whether or not the union is a @Natural@ wrapped in--- the @Left@ alternative or a @Bool@ wrapped in the @Right@ alternative.  We--- would write:------ > $ cat > process <<EOF--- >     λ(union : < Left : Natural | Right : Bool >)--- > →   let handlers =--- >             { Left  = Natural/even  -- Natural/even is a built-in function--- >             , Right = λ(b : Bool) → b--- >             }--- > in  merge handlers union : Bool--- > EOF------ Now our @./process@ function can handle both alternatives:------ > $ dhall--- > ./process < Left = +3 | Right : Bool >--- > <Ctrl-D>--- > Bool--- > --- > False------ > $ dhall--- > ./process < Right = True | Left : Natural >--- > <Ctrl-D>--- > Bool--- > --- > True------ Every @merge@ has the following form:------ > merge handlers union : type------ ... where: ------ * @union@ is the union you want to consume--- * @handlers@ is a record with one function per alternative of the union--- * @type@ is the declared result type of the @merge@------ The @merge@ function selects which function to apply from the record based on--- which alternative the union selects:------ > merge { Foo = f, ... } < Foo = x | ... > : t = f x : t------ So, for example:------ > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Left = +3 | Right : Bool > : Bool--- >     = Natural/even +3 : Bool--- >     = False------ ... and similarly:------ > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural > : Bool--- >     = (λ(b : Bool) → b) True : Bool--- >     = True------ Notice that each handler has to return the same type of result (@Bool@ in--- this case) which must also match the declared result type of the @merge@.------ You can also omit the type annotation when merging a union with one or more--- alternatives, like this:------ > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural >------ You can also store more than one value or less than one value within--- alternatives using Dhall's support for anonymous records.  You can nest an--- anonymous record within a union such as in this type:------ > < Empty : {} | Person : { name : Text, age : Natural } >------ This union of records resembles following equivalent Haskell data type:------ > data Example = Empty | Person { name :: Text, age :: Text }------ You can resemble Haskell further by defining convenient constructors for each--- alternative, like this:------ >     let Empty  = < Empty = {=} | Person : { name : Text, age : Natural } >--- > in  let Person =--- >         λ(p : { name : Text, age : Natural }) → < Person = p | Empty : {} >--- > in  [   Empty--- >     ,   Person { name = "John", age = +23 }--- >     ,   Person { name = "Amy" , age = +25 }--- >     ,   Empty--- >     ]------ ... and Dhall even provides the @constructors@ keyword to automate this--- common pattern:------ >     let MyType = constructors < Empty : {} | Person : { name : Text, age : Natural } >--- > in  [   MyType.Empty {=}--- >     ,   MyType.Person { name = "John", age = +23 }--- >     ,   MyType.Person { name = "Amy" , age = +25 }--- >     ]------ The @constructors@ keyword takes a union type argument and returns a record--- with one field per union type constructor:------ > $ dhall --pretty--- > constructors < Empty : {} | Person : { name : Text, age : Natural } >--- > <Ctrl-D>--- >--- > { Empty  :--- >     ∀(Empty : {}) → < Empty : {} | Person : { age : Natural, name : Text } >--- > , Person :--- >       ∀(Person : { age : Natural, name : Text })--- >     → < Empty : {} | Person : { age : Natural, name : Text } >--- > }--- >--- > { Empty  =--- >     λ(Empty : {}) → < Empty = Empty | Person : { age : Natural, name : Text } >--- > , Person =--- >       λ(Person : { age : Natural, name : Text })--- >     → < Person = Person | Empty : {} >--- > }------ You can also extract fields during pattern matching such as in the following--- function which renders each value to `Text`:------ >     λ(x : < Empty : {} | Person : { name : Text, age : Natural } >)--- > →   merge--- >     {   Empty = λ(_ : {}) → "Unknown"--- >--- >     ,   Person =--- >             λ(person : { name : Text, age : Natural })--- >         →   "Name: ${person.name}, Age: ${Natural/show person.age}"--- >     }--- >     x------ __Exercise__: Create a list of the following type with at least one element--- per alternative:------ > List < Left : Integer | Right : Double >---- $polymorphic------ The Dhall language supports defining polymorphic functions (a.k.a.--- \"generic\" functions) that work on more than one type of value.  However,--- Dhall differs from Haskell by not inferring the types of these polymorphic--- functions.  Instead, you must be explicit about what type of value the--- function is specialized to.------ Take, for example, Haskell's identity function named @id@:------ > id :: a -> a--- > id = \x -> x------ The identity function is polymorphic, meaning that `id` works on values of--- different types:------ > >>> id 4--- > 4--- > >>> id True--- > True------ The equivalent function in Dhall is:------ > λ(a : Type) → λ(x : a) → x------ Notice how this function takes two arguments instead of one.  The first--- argument is the type of the second argument.------ Let's illustrate how this works by actually using the above function:------ > $ echo "λ(a : Type) → λ(x : a) → x" > id------ If we supply the function alone to the compiler we get the inferred type as--- the first line:--- --- > $ dhall--- > ./id--- > <Ctrl-D>--- > ∀(a : Type) → ∀(x : a) → a--- > --- > λ(a : Type) → λ(x : a) → x------ You can read the type @(∀(a : Type) → ∀(x : a) → a)@ as saying: \"This is the--- type of a function whose first argument is named @a@ and is a @Type@.  The--- second argument is named @x@ and has type @a@ (i.e. the value of the first--- argument).  The result also has type @a@.\"------ This means that the type of the second argument changes depending on what--- type we provide for the first argument.  When we apply @./id@ to @Integer@, we--- create a function that expects an @Integer@ argument:------ > $ dhall--- > ./id Integer--- > <Ctrl-D>--- > ∀(x : Integer) → Integer--- > --- > λ(x : Integer) → x------ Similarly, when we apply @./id@ to @Bool@, we create a function that expects a--- @Bool@ argument:------ > $ dhall--- > ./id Bool--- > <Ctrl-D>--- > ∀(x : Bool) → Bool--- > --- > λ(x : Bool) → x------ We can then supply the final argument to each of those functions to show--- that they both work on their respective types:------ > $ dhall--- > ./id Integer 4--- > <Ctrl-D>--- > Integer--- > --- > 4------ > $ dhall--- > ./id Bool True--- > <Ctrl-D>--- > Bool--- > --- > True------ Built-in functions can also be polymorphic, too.  For example, we can ask--- the compiler for the type of @List/reverse@, the function that reverses a--- list:------ > $ dhall--- > List/reverse--- > <Ctrl-D>--- > ∀(a : Type) → List a → List a--- > --- > List/reverse------ The first argument to @List/reverse@ is the type of the list to reverse:------ > $ dhall--- > List/reverse Bool--- > <Ctrl-D>--- > List Bool → List Bool--- > --- > List/reverse Bool------ ... and the second argument is the list to reverse:------ > $ dhall--- > List/reverse Bool [True, False]--- > <Ctrl-D>--- > List Bool--- > --- > [False, True] : List Bool------ Note that the second argument has no name.  This type:------ > ∀(a : Type) → List a → List a------ ... is equivalent to this type:------ > ∀(a : Type) → ∀(_ : List a) → List a------ In other words, if you don't see the @∀@ symbol surrounding a function--- argument type then that means that the name of the argument is @"_"@.  This--- is true even for user-defined functions:------ > $ dhall--- > λ(_ : Text) → 1--- > <Ctrl-D>--- > Text → Integer--- > --- > λ(_ : Text) → 1------ The type @(Text → Integer)@ is the same as @(∀(_ : Text) → Integer)@------ __Exercise__ : Translate Haskell's `flip` function to Dhall---- $total------ Dhall is a total programming language, which means that Dhall is not--- Turing-complete and evaluation of every Dhall program is guaranteed to--- eventually halt.  There is no upper bound on how long the program might take--- to evaluate, but the program is guaranteed to terminate in a finite amount of--- time and not hang forever.------ This guarantees that all Dhall programs can be safely reduced to a normal--- form where as many functions have been evaluated as possible.  In fact, Dhall--- expressions can be evaluated even if all function arguments haven't been fully--- applied.  For example, the following program is an anonymous function:------ > $ dhall--- > \(n : Bool) -> +10 * +10--- > <Ctrl-D>--- > ∀(n : Bool) → Natural--- > --- > λ(n : Bool) → +100------ ... and even though the function is still missing the first argument named--- @n@ the compiler is smart enough to evaluate the body of the anonymous--- function ahead of time before the function has even been invoked.------ We can use the @map@ function from the Prelude to illustrate an even more--- complex example:------ > $ dhall--- >     let Prelude/List/map = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/map--- > in  λ(f : Integer → Integer) → Prelude/List/map Integer Integer f [1, 2, 3]--- > <Ctrl-D>--- > ∀(f : Integer → Integer) → List Integer--- > --- > λ(f : Integer → Integer) → [f 1, f 2, f 3] : List Integer------ Dhall can apply our function to each element of the list even before we specify--- which function to apply.------ The language will also never crash or throw any exceptions.  Every--- computation will succeed and produce something, even if the result might be--- an @Optional@ value:------ > $ dhall--- > List/head Integer ([] : List Integer)--- > <Ctrl-D>--- > Optional Integer--- > --- > [] : Optional Integer------ __Exercise__: The Dhall Prelude provides a @replicate@ function which you can--- find here:------ <https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/replicate>------ Test what the following Dhall expression normalizes to:------ > let replicate = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/replicate--- > in  replicate +10------ __Exercise__: If you have a lot of spare time, try to \"break the compiler\" by--- finding an input expression that crashes or loops forever (and file a bug--- report if you succeed)---- $headers------ Sometimes you would like to provide additional request headers when importing--- Dhall expressions from URLs.  For example, you might want to provide an--- authorization header or specify the expected content type.------ Dhall URL imports let you add or modify request headers with the @using@--- keyword:------ > https://example.com using ./headers------ ... where you can replace @./headers@ with any import that points to a Dhall--- expression of the following type:------ > List { header : Text, value : Text }------ For example, if you needed to specify the content type correctly in order to--- download the file, then your @./headers@ file might look like this:------ > $ cat headers--- > [ { header = "Accept", value = "application/dhall" } ]------ ... or if you needed to provide an authorization token to access a private--- GitHub repository, then your headers could look like this:------ > [ { header = "Authorization", value = "token ${env:GITHUB_TOKEN as Text}" } ]------ This would read your GitHub API token from the @GITHUB_TOKEN@ environment--- variable and supply that token in the authorization header.------ You cannot inline the headers within the same file as the URL.  You must--- provide them as a separate import.  That means that this is /not/ legal code:------ > http://example.com using [ { header = "Accept", value = "application/dhall" } ]  -- NOT legal------ Dhall will forward imports if you import an expression from a URL that--- contains a relative import.  For example, if you import an expression like--- this:--- --- > http://example.com using ./headers--- --- ... and @http:\/\/example.com@ contains a relative import of @./foo@ then--- Dhall will import @http:\/\/example.com/foo@ using the same @./headers@ file.---- $integrity------ Sometimes you want to use share code while still ensuring that the imported--- value never changes and can't be corrupted by a malicious attacker.  Dhall--- provides built-in support for hashing imported values to verify that their--- value never changes------ For example, suppose you save the following two files:------ > $ cat ./foo--- > ./bar sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b------ > $ cat ./bar--- > ./baz------ > $ cat ./baz--- > 1------ The first file named @./foo@ contains an example of an integrity check.  You--- can add @sha256:XXX@ after any import (such as after @./bar@), where @XXX@ is--- an expected 64-character @sha256@ hash of the Dhall value.  To be precise,--- the hash represents a @sha256@ hash of the UTF-8 encoding of a canonical text--- representation of the fully resolved and normalized abstract syntax tree of--- the imported expression.------ Dhall will verify that the expected hash matches the actual hash of the--- imported Dhall value and reject the import if there is a hash mismatch:------ > $ dhall <<< './foo'--- > Integer--- > --- > 1------ This implies that the hash only changes if the Dhall value changes.  For--- example, if you add a comment to the @./bar@ file:------ > $ cat ./bar--- > -- This comment does not change the hash--- > ./baz------ ... then @./foo@ will still successfully import @./bar@ because the hash--- only depends on the normalized value and does not depend on meaningless--- changes to whitespace or comments:------ > $ dhall <<< './foo'  # This still succeeds--- > Integer--- > --- > 1------ You can compute the Hash for any import by using the @dhall-hash@ utility--- installed by this package.  For example:------ > dhall-hash <<< './bar'--- > sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b------ Then you can paste that output into your code after the import------ Now suppose that you you change the value of the @./baz@ file:------ > $ cat ./baz--- > 2------ ... then the @./foo@ file will fail to import @./bar@, even though the--- text of the @./bar@ file technically never changed:------ > dhall <<< './foo'--- > --- > Error: Import integrity check failed--- > --- > Expected hash:--- > --- > ↳ 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b--- > --- > Actual hash:--- > --- > ↳ d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35------ This is because the @./bar@ file now represents a new value (@2@ instead of--- @1@), even though the text of the @./bar@ is still the same.  Since the value--- changed the hash must change as well.  However, we could change @./baz@ to:------ > $ cat baz--- > if True then 1 else 2------ ... and the import would succeed again because the final result is still @1@.------ The integrity hash ensures that your import's final meaning can never change,--- so an attacker can never compromise an imported value protected by a hash--- unless they can break SHA-256 encryption.  The hash not only protects the--- file that you immediately import, but also protects every transitive import--- as well.------ You can also safely refactor your imported dependencies knowing that the--- refactor will not change your hash so long as your refactor is--- behavior-preserving.  This provides an easy way to detect refactoring errors--- that you might accidentally introduce.  The hash not only protects you--- from attackers, but also protects against human error, too!---- $rawText------ Sometimes you want to import the contents of a raw text file as a Dhall--- value of type `Text`.  For example, one of the fields of a record might be--- the contents of a software license:------ > { package = "dhall"--- > , author  = "Gabriel Gonzalez"--- > , license = ./LICENSE--- > }------ Normally if you wanted to import a text file you would need to wrap the--- contents of the file in double single-quotes, like this:------ > $ cat LICENSE--- > ''--- > Copyright (c) 2017 Gabriel Gonzalez--- > All rights reserved.--- > --- > ...--- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS--- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--- > ''------ ... which does not work well if you need to reuse the same text file for--- other programs------ However, Dhall supports importing a raw text file by adding @as Text@ to the--- end of the import, like this:------ > { package = "dhall"--- > , author  = "Gabriel Gonzalez"--- > , license = ./LICENSE as Text--- > }------ ... and then you can use the original text file unmodified:------ > $ cat LICENSE--- > Copyright (c) 2017 Gabriel Gonzalez--- > All rights reserved.--- > --- > ...--- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS--- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.---- $format------ This package also provides a @dhall-format@ executable that you can use to--- automatically format Dhall expressions.  For example, we can take the--- following unformatted Dhall expression:------ > $ cat ./unformatted--- > λ(a : Type) → λ(kvss : List (List { index : Natural, value : a })) → --- > List/build { index : Natural, value : a } (λ(list : Type) → λ(cons : { --- > index : Natural, value : a } → list → list) → λ(nil : list) → --- > (List/fold (List { index : Natural, value : a }) kvss { count : Natural, diff : --- > Natural → list } (λ(kvs : List { index : Natural, value : a }) → λ(y : { --- > count : Natural, diff : Natural → list }) → { count = y.count + List/length --- > { index : Natural, value : a } kvs, diff = λ(n : Natural) → List/fold { --- > index : Natural, value : a } kvs list (λ(kvOld : { index : Natural, value : a --- > }) → λ(z : list) → cons { index = kvOld.index + n, value = kvOld.value } --- > z) (y.diff (n + List/length { index : Natural, value : a } kvs)) }) { count = --- > +0, diff = λ(_ : Natural) → nil }).diff +0)------ ... and run the expression through the @dhall-format@ executable:------ > $ dhall-format < ./unformatted--- >   λ(a : Type)--- > → λ(kvss : List (List { index : Natural, value : a }))--- > → List/build--- >   { index : Natural, value : a }--- >   (   λ(list : Type)--- >     → λ(cons : { index : Natural, value : a } → list → list)--- >     → λ(nil : list)--- >     → ( List/fold--- >         (List { index : Natural, value : a })--- >         kvss--- >         { count : Natural, diff : Natural → list }--- >         (   λ(kvs : List { index : Natural, value : a })--- >           → λ(y : { count : Natural, diff : Natural → list })--- >           → { count = y.count + List/length { index : Natural, value : a } kvs--- >             , diff  =--- >                   λ(n : Natural)--- >                 → List/fold--- >                   { index : Natural, value : a }--- >                   kvs--- >                   list--- >                   (   λ(kvOld : { index : Natural, value : a })--- >                     → λ(z : list)--- >                     → cons { index = kvOld.index + n, value = kvOld.value } z--- >                   )--- >                   (y.diff (n + List/length { index : Natural, value : a } kvs))--- >             }--- >         )--- >         { count = +0, diff = λ(_ : Natural) → nil }--- >       ).diff--- >       +0--- >   )------ The executable formats expressions without resolving, type-checking, or--- normalizing them:------ > $ dhall-format--- > let replicate = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/replicate --- > in replicate +5 (List (List Integer)) (replicate +5 (List Integer) (replicate +5 Integer 1))--- > <Ctrl-D>--- >     let replicate =--- >           https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/replicate --- > --- > in  replicate--- >     +5--- >     (List (List Integer))--- >     (replicate +5 (List Integer) (replicate +5 Integer 1))------ If you want to evaluate and format an expression then you can use the--- @--pretty@ flag of the @dhall@ executable:------ > $ dhall --pretty--- > let replicate = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/replicate --- > in replicate +5 (List (List Integer)) (replicate +5 (List Integer) (replicate +5 Integer 1))--- > <Ctrl-D>--- > List (List (List Integer))--- > --- >   [   [ [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       ]--- >     : List (List Integer)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       ]--- >     : List (List Integer)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       ]--- >     : List (List Integer)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       ]--- >     : List (List Integer)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       , [ 1, 1, 1, 1, 1 ] : List Integer--- >       ]--- >     : List (List Integer)--- >   ]--- > : List (List (List Integer))------ You can also use the formatter to modify files in place using the--- @--inplace@ flag:------ > $ dhall-format --inplace ./unformatted--- > $ cat ./unformatted--- >   λ(a : Type)--- > → λ(kvss : List (List { index : Natural, value : a }))--- > → List/build--- >   { index : Natural, value : a }--- >   (   λ(list : Type)--- >     → λ(cons : { index : Natural, value : a } → list → list)--- >     → λ(nil : list)--- >     → ( List/fold--- >         (List { index : Natural, value : a })--- >         kvss--- >         { count : Natural, diff : Natural → list }--- >         (   λ(kvs : List { index : Natural, value : a })--- >           → λ(y : { count : Natural, diff : Natural → list })--- >           → { count = y.count + List/length { index : Natural, value : a } kvs--- >             , diff  =--- >                   λ(n : Natural)--- >                 → List/fold--- >                   { index : Natural, value : a }--- >                   kvs--- >                   list--- >                   (   λ(kvOld : { index : Natural, value : a })--- >                     → λ(z : list)--- >                     → cons { index = kvOld.index + n, value = kvOld.value } z--- >                   )--- >                   (y.diff (n + List/length { index : Natural, value : a } kvs))--- >             }--- >         )--- >         { count = +0, diff = λ(_ : Natural) → nil }--- >       ).diff--- >       +0--- >   )------ Carefully note that the code formatter does not preserve all comments.--- Currently, the formatter only preserves leading comments and whitespace--- up until the last newline preceding the code.  In other words:------ > $ dhall-format--- > {- This comment will be preserved by the formatter -}--- > -- ... and this comment will be preserved, too--- > {- This comment will *NOT* be preserved -} 1--- > -- ... and this comment will also *NOT* be preserved--- > <Ctrl-D>--- > {- This comment will be preserved by the formatter -}--- > -- ... and this comment will be preserved, too--- > 1---- $builtins------ Dhall is a restricted programming language that only supports simple built-in--- functions and operators.  If you want to do anything fancier you will need to--- load your data into Haskell for further processing------ This section covers types, functions, and operators that are built into the--- language, meaning that you do not need to import any code to use them.--- Additionally, Dhall also comes with a Prelude (covered in the next section)--- hosted online that contains functions derived from these base utilities.  The--- Prelude also re-exports all built-in functions for people who prefer--- consistency.------ The following documentation on built-ins is provided primarily as a reference.--- You don't need to read about every single built-in and you may want to skip to--- the following Prelude section.---- The language provides built-in support for the following primitive types:------ * @Bool@ values--- * @Natural@ values--- * @Integer@ values--- * @Double@ values--- * @Text@ values------ ... as well as support for the following derived types:------ * @List@s of values--- * @Optional@ values--- * Anonymous records--- * Anonymous unions---- $caveats------ Dhall differs in a few important ways from other programming languages, so--- you should keep the following caveats in mind:------ First, Dhall only supports addition and multiplication on @Natural@ numbers--- (i.e. non-negative integers), which are not the same type of number as--- @Integer@s (which can be negative).  A @Natural@ number is a number prefixed--- with the @+@ symbol.  If you try to add or multiply two @Integer@s (without--- the @+@ prefix) you will get a type error:------ > $ dhall--- > 2 + 2--- > <Ctrl-D>--- > Use "dhall --explain" for detailed errors--- > --- > Error: ❰+❱ only works on ❰Natural❱s--- > --- > 2 + 2--- > --- > (stdin):1:1------ In fact, there are no built-in functions for @Integer@s (or @Double@s).  As--- far as the language is concerned they are opaque values that can only be--- shuffled around but not used in any meaningful way until they have been--- loaded into Haskell.------ Second, the equality @(==)@ and inequality @(!=)@ operators only work on--- @Bool@s.  You cannot test any other types of values for equality.---- $builtinOverview------ Each of the following sections provides an overview of builtin functions and--- operators for each type.  For each function you get:------ * An example use of that function------ * A \"type judgement\" explaining when that function or operator is well---   typed------ For example, for the following judgement:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x && y : Bool------ ... you can read that as saying: "if @x@ has type @Bool@ and @y@ has type--- @Bool@, then @x && y@ has type @Bool@"------ Similarly, for the following judgement:------ > ─────────────────────────────────--- > Γ ⊢ Natural/even : Natural → Bool------ ... you can read that as saying: "@Natural/even@ always has type--- @Natural → Bool@"------ * Rules for how that function or operator behaves------ These rules are just equalities that come in handy when reasoning about code.--- For example, the section on @(&&)@ has the following rules:------ > (x && y) && z = x && (y && z)--- >--- > x && True = x--- >--- > True && x = x------ These rules are also a contract for how the compiler should behave.  If you--- ever observe code that does not obey these rules you should file a bug--- report.---- $bool------ There are two values that have type @Bool@ named @True@ and @False@:------ > ───────────────--- > Γ ⊢ True : Bool------ > ────────────────--- > Γ ⊢ False : Bool------ The built-in operations for values of type @Bool@ are:------- $or------ Example:------ > $ dhall--- > True || False--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x || y : Bool------ Rules:------ > (x || y) || z = x || (y || z)--- > --- > x || False = x--- > --- > False || x = x--- >--- > x || (y && z) = (x || y) && (x || z)--- > --- > x || True = True--- > --- > True || x = True---- $and------ Example:------ > $ dhall--- > True && False--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x && y : Bool------ Rules:------ > (x && y) && z = x && (y && z)--- > --- > x && True = x--- > --- > True && x = x--- >--- > x && (y || z) = (x && y) || (x && z)--- > --- > x && False = False--- > --- > False && x = False---- $equal------ Example:------ > $ dhall--- > True == False--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x == y : Bool------ Rules:------ > (x == y) == z = x == (y == z)--- > --- > x == True = x--- > --- > True == x = x--- >--- > x == x = True---- $unequal------ Example:------ > $ dhall--- > True != False--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x != y : Bool------ Rules:------ > (x != y) != z = x != (y != z)--- > --- > x != False = x--- > --- > False != x = x--- >--- > x != x = False---- $ifthenelse------ Example:------ > $ dhall--- > if True then 3 else 5--- > <Ctrl-D>--- > Integer--- > --- > 3------ Type:------ >                Γ ⊢ t : Type--- >                ─────────────────────--- > Γ ⊢ b : Bool   Γ ⊢ l : t   Γ ⊢ r : t--- > ────────────────────────────────────--- > Γ ⊢ if b then l else r : t------ Rules:------ > if b then True else False = b--- > --- > if True  then l else r = l--- > --- > if False then l else r = r---- $natural------ @Natural@ literals are numbers prefixed by a @+@ sign, like this:------ > +4 : Natural------ If you omit the @+@ sign then you get an @Integer@ literal, which is a--- different type of value---- $plus------ Example:------ > $ dhall--- > +2 + +3--- > <Ctrl-D>--- > Natural--- > --- > +5------ Type:------ > Γ ⊢ x : Natural   Γ ⊢ y : Natural--- > ─────────────────────────────────--- > Γ ⊢ x + y : Natural------ Rules:------ > (x + y) + z = x + (y + z)--- >--- > x + +0 = x--- >--- > +0 + x = x---- $times------ Example:------ > $ dhall--- > +2 * +3--- > <Ctrl-D>--- > Natural--- > --- > +6------ Type:------ > Γ ⊢ x : Natural   Γ ⊢ y : Natural--- > ─────────────────────────────────--- > Γ ⊢ x * y : Natural------ Rules:------ > (x * y) * z = x * (y * z)--- >--- > x * +1 = x--- >--- > +1 * x = x--- >--- > (x + y) * z = (x * z) + (y * z)--- >--- > x * (y + z) = (x * y) + (x * z)--- >--- > x * +0 = +0--- >--- > +0 * x = +0---- $even------ Example:------ > $ dhall--- > Natural/even +6--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > ─────────────────────────────────--- > Γ ⊢ Natural/even : Natural → Bool------ Rules:------ > Natural/even (x + y) = Natural/even x == Natural/even y--- >--- > Natural/even +0 = True--- >--- > Natural/even (x * y) = Natural/even x || Natural/even y--- >--- > Natural/even +1 = False---- $odd------ Example:------ > $ dhall--- > Natural/odd +6--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ────────────────────────────────--- > Γ ⊢ Natural/odd : Natural → Bool------ Rules:------ > Natural/odd (x + y) = Natural/odd x != Natural/odd y--- >--- > Natural/odd +0 = False--- >--- > Natural/odd (x * y) = Natural/odd x && Natural/odd y--- >--- > Natural/odd +1 = True---- $isZero------ Example:------ > $ dhall--- > Natural/isZero +6--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ───────────────────────────────────--- > Γ ⊢ Natural/isZero : Natural → Bool------ Rules:------ > Natural/isZero (x + y) = Natural/isZero x && Natural/isZero y--- >--- > Natural/isZero +0 = True--- >--- > Natural/isZero (x * y) = Natural/isZero x || Natural/isZero y--- >--- > Natural/isZero +1 = False---- $naturalFold------ Example:------ > $ dhall--- > Natural/fold +40 Text (λ(t : Text) → t ++ "!") "You're welcome"--- > <Ctrl-D>--- > Text--- > --- > "You're welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"------ Type:------ > ──────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Natural/fold : Natural → ∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural------ Rules:--- --- > Natural/fold (x + y) n s z = Natural/fold x n s (Natural/fold y n s z)--- > --- > Natural/fold +0 n s z = z--- > --- > Natural/fold (x * y) n s = Natural/fold x n (Natural/fold y n s)--- > --- > Natural/fold +1 n s = s---- $naturalBuild------ Example:------ > $ dhall--- > Natural/build (λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ zero))--- > <Ctrl-D>--- > Natural--- > --- > +2------ Type:------ > ─────────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Natural/build : (∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural) → Natural------ Rules:------ > Natural/fold (Natural/build x) = x--- >--- > Natural/build (Natural/fold x) = x---- $integer------ @Integer@ literals are either prefixed with a @-@ sign (if they are negative)--- or no sign (if they are positive), like this:------ >  3 : Integer--- > -2 : Integer------ If you prefix them with a @+@ sign then they are @Natural@ literals and not--- @Integer@s------ There are no built-in operations on @Integer@s.  For all practical purposes--- they are opaque values within the Dhall language---- $double------ A @Double@ literal is a floating point value with at least one decimal--- place, such as:------ > -2.0     : Double--- >  3.14159 : Double------ There are no built-in operations on @Double@s.  For all practical purposes--- they are opaque values within the Dhall language---- $text------ A @Text@ literal is just a sequence of characters enclosed in double quotes,--- like:------ > "ABC" : Text------ The only thing you can do with @Text@ values is concatenate them---- $textAppend------ Example:------ > $ dhall--- > "Hello, " ++ "world!"--- > <Ctrl-D>--- > Text--- > --- > "Hello, world!"------ Type:------ > Γ ⊢ x : Text   Γ ⊢ y : Text--- > ───────────────────────────--- > Γ ⊢ x && y : Text------ Rules:------ > (x ++ y) ++ z = x ++ (y ++ z)--- > --- > x ++ "" = x--- > --- > "" ++ x = x---- $list------ Dhall @List@ literals are a sequence of values inside of brackets separated by--- commas:------ > Γ ⊢ t : Type   Γ ⊢ x : t   Γ ⊢ y : t   ...--- > ──────────────────────────────────────────--- > Γ ⊢ [x, y, ... ] : List t------ Also, every empty @List@ must end with a mandatory type annotation, for example:------ > [] : List Integer------ The built-in operations on @List@s are:---- $listAppend------ Example:------ > $ dhall--- > [1, 2, 3] # [4, 5, 6]--- > <Ctrl-D>--- > List Integer--- >--- > [1, 2, 3, 4, 5, 6]------ Type:------ > Γ ⊢ x : List a    Γ ⊢ y : List a--- > ─────────────────────────────────--- > Γ ⊢ x # y : List a------ Rules:------ > ([] : List a) # xs = xs--- >--- > xs # ([] : List a) = xs--- >--- > (xs # ys) # zs = xs # (ys # zs)---- $listFold------ Example:------ > $ dhall--- > List/fold Bool [True, False, True] Bool (λ(x : Bool) → λ(y : Bool) → x && y) True--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/fold : ∀(a : Type) → List a → ∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list------ Rules:------ > let Prelude/List/concat = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concat--- >--- > List/fold a (Prelude/List/concat a xss) b c--- >     = List/fold (List a) xss b (λ(x : List a) → List/fold a x b c)--- >--- > List/fold a ([] : List a) b c n = n--- >--- > List/fold a ([x] : List a) b c = c x---- $listBuild------ Example:------ > $ dhall--- > List/build Integer (λ(list : Type) → λ(cons : Integer → list → list) → λ(nil : list) → cons 1 (cons 2 (cons 3 nil)))--- > <Ctrl-D>--- > List Integer--- > --- > [1, 2, 3] : List Integer------ Type:------ > ───────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/build : ∀(a : Type) → (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list) → List a------ Rules:------ > List/build t (List/fold t x) = x--- >--- > List/fold t (List/build t x) = x---- $listLength------ Example:------ > $ dhall--- > List/length Integer [1, 2, 3]--- > <Ctrl-D>--- > Natural--- > --- > +3------ Type:------ > ────────────────────────────────────────────────--- > Γ ⊢ List/length : ∀(a : Type) → List a → Natural------ Rules:------ > List/length t xs = List/fold t xs Natural (λ(_ : t) → λ(n : Natural) → n + +1) +0---- $listHead------ Example:------ > $ dhall--- > List/head Integer [1, 2, 3]--- > <Ctrl-D>--- > Optional Integer--- > --- > [1] : Optional Integer------ Type:------ > ─────────────────────────────────────--- > Γ ⊢ List/head ∀(a : Type) → List a → Optional a------ Rules:------ > let Prelude/Optional/head  = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Optional/head--- > let Prelude/List/concat    = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concat--- > let Prelude/List/concatMap = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concatMap--- > let Prelude/List/map       = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/map--- > --- > List/head a (Prelude/List/concat a xss) =--- >     Prelude/Optional/head a (Prelude/List/map (List a) (Optional a) (List/head a) xss)--- > --- > List/head a ([x] : List a) = [x] : Optional a--- > --- > List/head b (Prelude/List/concatMap a b f m)--- >     = Prelude/Optional/concatMap a b (λ(x : a) → List/head b (f x)) (List/head a m)---- $listLast------ Example:------ > $ dhall--- > List/last Integer [1, 2, 3]--- > <Ctrl-D>--- > Optional Integer--- > --- > [1] : Optional Integer------ Type:------ > ─────────────────────────────────────--- > Γ ⊢ List/last : ∀(a : Type) → List a → Optional a------ Rules:------ > let Prelude/Optional/last  = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Optional/last--- > let Prelude/List/concat    = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concat--- > let Prelude/List/concatMap = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concatMap--- > let Prelude/List/map       = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/map--- > --- > List/last a (Prelude/List/concat a xss) =--- >     Prelude/Optional/last a (Prelude/List/map (List a) (Optional a) (List/last a) xss)--- > --- > List/last a ([x] : List a) = [x] : Optional a--- > --- > List/last b (Prelude/List/concatMap a b f m)--- >     = Prelude/Optional/concatMap a b (λ(x : a) → List/last b (f x)) (List/last a m)---- $listIndexed------ Example------ > $ dhall--- > List/indexed Text ["ABC", "DEF", "GHI"]--- > <Ctrl-D>--- > List { index : Natural, value : Text }--- > --- > [{ index = +0, value = "ABC" }, { index = +1, value = "DEF" }, { index = +2, value = "GHI" }] : List { index : Natural, value : Text }------ Type:------ > ─────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/indexed : ∀(a : Type) → List a → List { index : Natural, value : a }------ Rules:------ > let Prelude/List/shifted = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/shifted--- > let Prelude/List/concat  = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concat--- > let Prelude/List/map     = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/map--- > --- > List/indexed a (Prelude/List/concat a xss) =--- >     Prelude/List/shifted a (Prelude/List/map (List a) (List { index : Natural, value : a }) (List/indexed a) xss)---- $listReverse------ Example:------ > $ dhall--- > List/reverse Integer [1, 2, 3]--- > <Ctrl-D>--- > List Integer--- > --- > [3, 2, 1] : List Integer------ Type:------ > ─────────────────────────────────────────────────--- > Γ ⊢ List/reverse : ∀(a : Type) → List a → List a------ Rules:------ > let Prelude/List/map       = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/map--- > let Prelude/List/concat    = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concat--- > let Prelude/List/concatMap = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/List/concatMap--- > --- > List/reverse a (Prelude/List/concat a xss)--- >     = Prelude/List/concat a (List/reverse (List a) (Prelude/List/map (List a) (List a) (List/reverse a) xss))--- >--- > List/reverse a ([x] : List a) = [x] : List a--- >--- > List/reverse b (Prelude/List/concatMap a b f xs)--- >     = Prelude/List/concatMap a b (λ(x : a) → List/reverse b (f x)) (List/reverse a xs)--- >--- > List/reverse a ([x, y] : List a) = [y, x] : List a---- $optional1------ Dhall @Optional@ literals are 0 or 1 values inside of brackets:------ > Γ ⊢ t : Type   Γ ⊢ x : t--- > ────────────────────────--- > Γ ⊢ ([x] : Optional t) : Optional t------ > Γ ⊢ t : Type--- > ────────────────────────--- > Γ ⊢ ([] : Optional t) : Optional t------ Also, every @Optional@ literal must end with a mandatory type annotation------ The built-in operations on @Optional@ values are:---- $optionalFold------ Example:------ > $ dhall--- > Optional/fold Text (["ABC"] : Optional Text) Text (λ(t : Text) → t) ""--- > <Ctrl-D>--- > Text--- > --- > "ABC"------ Type:------ > ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Optional/fold : ∀(a : Type) → Optional a → ∀(optional : Type) → ∀(just : a → optional) → ∀(nothing : optional) → optional------ Rules:------ > Optional/fold a ([]  : Optional a) o j n = n--- >--- > Optional/fold a ([x] : Optional a) o j n = j x---- $prelude------ There is also a Prelude available at:------ <http://prelude.dhall-lang.org>------ ... which currenty redirects to:------ <https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude>------ There is nothing \"official\" or \"standard\" about this Prelude other than--- the fact that it is mentioned in this tutorial.  The \"Prelude\" is just a--- set of convenient utilities which didn't quite make the cut to be built into--- the language.  Feel free to host your own custom Prelude if you want!------ If you visit the above link you can browse the Prelude, which has a few--- subdirectories.  For example, the @Bool@ subdirectory has a @not@ file--- located here:------ <https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not>------ The @not@ function is just a UTF8-encoded text file hosted online with the--- following contents------ > $ curl https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not--- > {---- > Flip the value of a `Bool`--- > --- > Examples:--- > --- > ```--- > ./not True = False--- > --- > ./not False = True--- > ```--- > -}--- > let not : Bool → Bool--- >     =   λ(b : Bool) → b == False--- > --- > in  not------ The file could have been much shorter, like this:------ > λ(b : Bool) → b == False------ ... but all the functions exported from the Prelude try to be as--- self-documenting as possible by including:------ * the name of the function--- * the type of the function--- * documentation (including a few examples)------ The performance penalty for adding these helpful features is negligible.------ You can use this @not@ function either directly:------ > $ dhall--- > https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not True--- > <Ctrl-D>--- > Bool--- > --- > False------ ... or assign the URL to a shorter name:------ > $ dhall--- > let Bool/not = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Bool/not--- > in  Bool/not True--- > <Ctrl-D>--- > Bool--- > --- > False------ Some functions in the Prelude just re-export built-in functions for--- consistency and documentation, such as @Prelude\/Natural\/even@, which--- re-exports the built-in @Natural/even@ function:------ > $ curl https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/Natural/even--- > {---- > Returns `True` if a number if even and returns `False` otherwise--- > --- > Examples:--- > --- > ```--- > ./even +3 = False--- > --- > ./even +0 = True--- > ```--- > -}--- > let even : Natural → Bool--- >     =   Natural/even--- > --- > in  even------ You can also download the Prelude locally to your filesystem if you prefer--- using local relative paths instead of URLs.  For example, you can use @wget@,--- like this:------ > $ wget -np -nH -r --cut-dirs=2 https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/--- > $ tree Prelude--- > Prelude--- > ├── Bool--- > │   ├── and--- > │   ├── build--- > │   ├── even--- > │   ├── fold--- > │   ├── not--- > │   ├── odd--- > │   ├── or--- > │   └── show--- > ├── Double--- > │   └── show--- > ├── Integer--- > │   └── show--- > ├── List--- > │   ├── all--- > │   ├── any--- > │   ├── build--- > │   ├── concat--- > │   ├── filter--- > │   ├── fold--- > │   ├── generate--- > │   ├── head--- > │   ├── indexed--- > │   ├── iterate--- > │   ├── last--- > │   ├── length--- > │   ├── map--- > │   ├── null--- > │   ├── replicate--- > │   ├── reverse--- > │   ├── shifted--- > │   └── unzip--- > ├── Monoid--- > ├── Natural--- > │   ├── build--- > │   ├── enumerate--- > │   ├── even--- > │   ├── fold--- > │   ├── isZero--- > │   ├── odd--- > │   ├── product--- > │   ├── show--- > │   ├── sum--- > │   └── toInteger--- > ├── Optional--- > │   ├── build--- > │   ├── concat--- > │   ├── fold--- > │   ├── head--- > │   ├── last--- > │   ├── map--- > │   ├── toList--- > │   └── unzip--- > ├── Text--- > │   └── concat--- > └── index.html------ ... or if you have an @ipfs@ daemon running, you can mount the Prelude--- locally like this:------ > $ ipfs mount--- > $ cd /ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude------ Browse the Prelude online to learn more by seeing what functions are--- available and reading their inline documentation:------ <https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude>------ __Exercise__: Try to use a new Prelude function that has not been covered--- previously in this tutorial------ You can also import the entire Prelude as a single large record for--- convenience:------ > $ dhall--- >     let Prelude = https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/package.dhall--- >--- > in    λ(x : Text)--- >     → Prelude.`List`.length Text (Prelude.`List`.replicate +10 Text x)--- > <Ctrl-D>--- > ∀(x : Text) → Natural--- >--- > λ(x : Text) → +10------ The organization of the package mirrors the layout of the Prelude, meaning--- that every directory is stored as a record whose children are the fields of--- that record.------ __Exercise__: Browse the Prelude by running:------ > $ dhall --pretty <<< 'https://ipfs.io/ipfs/QmdtKd5Q7tebdo6rXfZed4kN6DXmErRQHJ4PsNCtca9GbB/Prelude/package.dhall'---- $conclusion------ By this point you should be able to use the Dhall configuration language to--- author, import, and program configuration files.  If you run into any issues--- you can report them at:------ <https://github.com/dhall-lang/dhall-haskell/issues>------ You can also request features, support, or documentation improvements on the--- above issue tracker.------ If you would like to contribute to the Dhall project you can try to port Dhall--- to other languages besides Haskell so that Dhall configuration files can be--- read into those languages, too.---- $faq------ * Why do empty lists require a type annotation?------ Unlike Haskell, Dhall cannot infer a polymorphic type for the empty list--- because Dhall represents polymorphic values as functions of types, like this:------ > λ(a : Type) → [] : List a------ If the compiler treated an empty list literal as syntactic short-hand for--- the above polymorphic function then you'd get the unexpected behavior where--- a list literal is a function if the list has 0 elements but not a function--- otherwise.--- --- * Does Dhall support user-defined recursive types?------ No, but you can translate recursive code to non-recursive code by following--- this guide:------ <https://github.com/dhall-lang/dhall-lang/wiki/How-to-translate-recursive-code-to-Dhall How to translate recursive code to Dhall>+{-# LANGUAGE CPP #-}++{-| Dhall is a programming language specialized for configuration files.  This+    module contains a tutorial explaining how to author configuration files+    using this language++    You might also be interested in the+    <https://docs.dhall-lang.org/tutorials/Language-Tour.html Language Tour>, a+    Haskell-agnostic tour of Dhall's language features.+-}+module Dhall.Tutorial (+    -- * Introduction+    -- $introduction++    -- * Types+    -- $types++    -- * Imports+    -- $imports++    -- * Lists+    -- $lists++    -- * Optional values+    -- $optional0++    -- * Records+    -- $records++    -- * Functions+    -- $functions++    -- * Compiler+    -- $compiler++    -- * Strings+    -- $strings++    -- * Combine+    -- $combine++    -- * Let expressions+    -- $let++    -- * Defaults+    -- $defaults++    -- * Unions+    -- $unions++    -- * Polymorphic functions+    -- $polymorphic++    -- * Total+    -- $total++    -- * Assertions+    -- $assertions++    -- * Headers+    -- $headers++    -- * Import integrity+    -- $integrity++    -- * Raw text+    -- $rawText++    -- * Formatting code+    -- $format++    -- * Built-in functions+    -- $builtins++    -- ** Caveats+    -- $caveats++    -- ** Extending the language+    -- $extending++    -- ** Substitutions+    -- $substitutions++    -- * Prelude+    -- $prelude++    -- * Limitations+    -- $limitations++    -- * Conclusion+    -- $conclusion++    -- * Frequently Asked Questions (FAQ)+    -- $faq+    ) where++import Data.Vector (Vector)+import Dhall++-- $setup+--+-- >>> :set -XOverloadedStrings++-- $introduction+--+-- The simplest way to use Dhall is to ignore the programming language features+-- and use it as a strongly typed configuration format.  For example, suppose+-- that you create the following configuration file:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = [3.0, 4.0, 5.0]+-- > }+--+-- You can read the above configuration file into Haskell using the following+-- code:+--+-- > -- example.hs+-- >+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Dhall+-- >+-- > data Example = Example { foo :: Natural, bar :: Vector Double }+-- >     deriving (Generic, Show)+-- >+-- > instance FromDhall Example+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Example)+--+-- __WARNING__: You must not instantiate FromDhall with a recursive type. See [Limitations](#limitations).+--+-- If you compile and run the above example, the program prints the corresponding+-- Haskell record:+--+-- > $ ./example+-- > Example {foo = 1, bar = [3.0,4.0,5.0]}+--+-- You can also load some types directly into Haskell without having to define a+-- record, like this:+--+-- >>> import Dhall+-- >>> :set -XOverloadedStrings+-- >>> input auto "True" :: IO Bool+-- True+--+-- The `Dhall.input` function can decode any value if we specify the value's+-- expected `Dhall.Type`:+--+-- > input+-- >     :: Type a  -- Expected type+-- >     -> Text    -- Dhall program+-- >     -> IO a    -- Decoded expression+--+-- ... and we can either specify an explicit type like `bool`:+--+-- > bool :: Type Bool+-- >+-- > input bool :: Text -> IO Bool+-- >+-- > input bool "True" :: IO Bool+--+-- >>> input bool "True"+-- True+--+-- ... or we can use `auto` to let the compiler infer what type to decode from+-- the expected return type:+--+-- > auto :: FromDhall a => Type a+-- >+-- > input auto :: FromDhall a => Text -> IO a+--+-- >>> input auto "True" :: IO Bool+-- True+--+-- You can see what types `auto` supports \"out-of-the-box\" by browsing the+-- instances for the `FromDhall` class.  For example, the following instance+-- says that we can directly decode any Dhall expression that evaluates to a+-- @Bool@ into a Haskell `Prelude.Bool`:+--+-- > instance FromDhall Bool+--+-- ... which is why we could directly decode the string @\"True\"@ into the+-- value `True`.+--+-- There is also another instance that says that if we can decode a value of+-- type @a@, then we can also decode a @List@ of values as a `Vector` of @a@s:+--+-- > instance FromDhall a => FromDhall (Vector a)+--+-- Therefore, since we can decode a @Bool@, we must also be able to decode a+-- @List@ of @Bool@s, like this:+--+-- >>> input auto "[True, False]" :: IO (Vector Bool)+-- [True,False]+--+-- We could also specify what type to decode by providing an explicit+-- `Dhall.Type` instead of using `auto` with a type annotation:+--+-- >>> input (vector bool) "[True, False]"+-- [True,False]+--+-- __Exercise:__ Create a @./config.dhall@ file that the following program can+-- decode:+--+-- > {-# LANGUAGE DeriveAnyClass    #-}+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Dhall+-- >+-- > data Person = Person { age :: Natural, name :: Text }+-- >     deriving (Generic, FromDhall, Show)+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Person)+--+-- __Exercise:__ Create a @./config.dhall@ file that the following program can+-- decode:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Data.Functor.Identity+-- > import Dhall+-- >+-- > instance FromDhall a => FromDhall (Identity a)+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Identity Double)++-- $types+--+-- Suppose that we try to decode a value of the wrong type, like this:+--+-- >>> input auto "1" :: IO Bool+-- *** Exception:+-- ...Error...: Expression doesn't match annotation+-- ...+-- - Bool+-- + Natural+-- ...+-- 1│ 1 : Bool+-- ...+-- (input):1:1+-- ...+--+-- The interpreter complains because the string @\"1\"@ cannot be decoded into a+-- Haskell value of type `Prelude.Bool`.  This part of the type error:+--+-- > - Bool+-- > + Natural+--+-- ... means that the expected type was @Bool@ but the inferred type of the+-- expression @1@ was @Natural@.+--+-- The code excerpt from the above error message has two components:+--+-- * the expression being type checked (i.e. @1@)+-- * the expression's expected type (i.e. @Bool@)+--+-- > Expression+-- > ⇩+-- > 1 : Bool+-- >     ⇧+-- >     Expected type+--+-- The @(:)@ symbol is how Dhall annotates values with their expected types.+-- This notation is equivalent to type annotations in Haskell using the @(::)@+-- symbol.  Whenever you see:+--+-- > x : t+--+-- ... you should read that as \"we expect the expression @x@ to have type+-- @t@\". However, we might be wrong and if our expected type does not match the+-- expression's actual type then the type checker will complain.+--+-- In this case, the expression @1@ does not have type @Bool@ so type checking+-- fails with an exception.+--+-- __Exercise:__ Load the Dhall library into @ghci@ and run these commands to get+-- get a more detailed error message:+--+-- > >>> import Dhall+-- > >>> :set -XOverloadedStrings+-- > >>> detailed (input auto "1") :: IO Bool+-- > ...+--+-- ... then read the entire error message+--+-- __Exercise:__ Fix the type error, either by changing the value to decode or+-- changing the expected type++-- $imports+--+-- You might wonder why in some cases we can decode a configuration file:+--+-- >>> writeFile "bool" "True"+-- >>> input auto "./bool" :: IO Bool+-- True+--+-- ... and in other cases we can decode a value directly:+--+-- >>> input auto "True" :: IO Bool+-- True+--+-- This is because importing a configuration from a file is a special case of a+-- more general language feature: Dhall expressions can reference other+-- expressions by their file path.+--+-- To illustrate this, let's create three files:+--+-- > $ echo "True"  > bool1+-- > $ echo "False" > bool2+-- > $ echo "./bool1 && ./bool2" > both+--+-- ... and read in all three files in a single expression:+--+-- >>> input auto "[ ./bool1 , ./bool2 , ./both ]" :: IO (Vector Bool)+-- [True,False,False]+--+-- Each file path is replaced with the Dhall expression contained within that+-- file.  If that file contains references to other files then those references+-- are transitively resolved.+--+-- In other words: configuration files can reference other configuration files,+-- either by their relative or absolute paths.  This means that we can split a+-- configuration file into multiple files, like this:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = ./bar.dhall+-- > }+--+-- > -- ./bar.dhall+-- > [3.0, 4.0, 5.0]+--+-- ... which is equivalent to our original configuration:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = [3.0, 4.0, 5.0]+-- > }+--+-- However, the Dhall language will forbid cycles in these file references.  For+-- example, if we create the following cycle:+--+-- > $ echo './file1' > file2+-- > $ echo './file2' > file1+--+-- ... then the interpreter will reject the import:+--+-- >>> input auto "./file1" :: IO Natural+-- *** Exception:+-- ↳ ./file1+--   ↳ ./file2+-- ...+-- Cyclic import: ./file1+-- ...+--+-- You can also import expressions by URL.  For example, you can find a Dhall+-- expression hosted at this GitHub URL:+--+-- <https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True>+--+-- > $ curl https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True+-- > True+--+-- ... and you can reference that expression either directly:+--+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS)+-- >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- True+#else+-- > >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > True+#endif+--+-- ... or inside of a larger expression:+--+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS)+-- >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- False+#else+-- > >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > False+#endif+--+-- You're not limited to hosting Dhall expressions on GitHub.  You can host a+-- Dhall expression anywhere that you can host UTF8-encoded text on the web,+-- such as a pastebin, or your own web server.+--+-- You can also import Dhall expressions from environment variables, too:+--+-- >>> System.Environment.setEnv "FOO" "1"+-- >>> input auto "env:FOO" :: IO Natural+-- 1+--+-- You can import types, too.  For example, we can change our @./bar@ file to:+--+-- > -- ./bar.dhall+-- > [3.0, 4.0, 5.0] : List ./type.dhall+--+-- ... then specify the type in a separate file:+--+-- > -- ./type.dhall+-- > Double+--+-- ... and everything still type checks:+--+-- > $ ./example+-- > Example {foo = 1, bar = [3.0,4.0,5.0]}+--+-- Note that imports should be terminated by whitespace or parentheses otherwise+-- you will get either an import error or a parse error, like this:+--+-- >>> writeFile "baz" "2.0"+-- >>> input auto "./baz: Double" :: IO Double+-- *** Exception:+-- ↳ ./baz:+-- ...+-- ...Error...: Missing file ...baz:+-- ...+--+-- This is because the parser thinks that @./baz:@ is a single token due to+-- the missing whitespace before the colon and tries to import a file named+-- @./baz:@, which does not exist.  To fix the problem we have to add a space+-- after @./baz@:+--+-- >>> input auto "./baz : Double" :: IO Double+-- 2.0+--+-- __Exercise:__ There is a @not@ function hosted online here:+--+-- <https://prelude.dhall-lang.org/Bool/not>+--+-- Visit that link and read the documentation.  Then try to guess what this+-- code returns:+--+-- > >>> input auto "https://prelude.dhall-lang.org/Bool/not https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > ???+--+-- Run the code to test your guess++-- $lists+--+-- You can store 0 or more values of the same type in a list, like this:+--+-- > [1, 2, 3]+--+-- Every list can be followed by the type of the list.  The type annotation is+-- required for empty lists but optional for non-empty lists.  You will get a+-- parse error if you provide an empty list without a type annotation:+--+-- >>> input auto "[]" :: IO (Vector Natural)+-- *** Exception:+-- ...Error...: Invalid input+-- ...+-- (input):1:3:+--   |+-- 1 | []+--   |   ^+-- Empty list literal without annotation+-- ...+--+-- Also, list elements must all have the same type.  You will get an error if+-- you try to store elements of different types in a list:+--+-- >>> input auto "[1, True, 3]" :: IO (Vector Natural)+-- *** Exception:+-- ...Error...: List elements should all have the same type+-- ...+-- - Natural+-- + Bool+-- ...+-- 1│     True+-- ...+-- (input):1:5+-- ...+--+-- __Exercise:__ Replace the @\"???\"@ with an expression that successfully+-- decodes to the specified type:+--+-- > >>> input auto "???" :: IO (Vector (Vector Natural))++-- $optional0+--+-- @Optional@ values are either of the form @Some value@ or @None type@.+--+-- For example, these are valid @Optional@ values:+--+-- > Some 1+-- >+-- > None Natural+--+-- ... which both have type @Optional Natural@+--+-- An @Optional@ corresponds to Haskell's `Maybe` type for decoding purposes:+--+-- >>> input auto "Some 1" :: IO (Maybe Natural)+-- Just 1+-- >>> input auto "None Natural" :: IO (Maybe Natural)+-- Nothing+--+-- __Exercise:__ Replace the @\"???\"@ with an expression that successfully+-- decodes to the specified type:+--+-- > >>> input auto "???" :: IO (Maybe (Maybe (Maybe Natural)))++-- $records+--+-- Record literals are delimited by curly braces and their fields are separated+-- by commas.  For example, this is a valid record literal:+--+-- > { foo = True+-- > , bar = 2+-- > , baz = 4.2+-- > }+--+-- A record type is like a record literal except instead of specifying each+-- field's value we specify each field's type.  For example, the preceding+-- record literal has the following record type:+--+-- > { foo : Bool+-- > , bar : Natural+-- > , baz : Double+-- > }+--+-- If you want to specify an empty record literal, you must use @{=}@, which is+-- special syntax reserved for empty records.  If you want to specify the empty+-- record type, then you use @{}@.  If you forget which is which you can always+-- ask the @dhall@ compiler to remind you of the type for each one:+--+-- > $ dhall type <<< '{=}'+-- > {}+--+-- > $ dhall type <<< '{}'+-- > Type+--+-- This is our first use of the @dhall@ command-line tool (provided by this+-- package), which provides a @type@ subcommand for inferring an expression's+-- type.  By default the tool reads the expression on standard input and outputs+-- the type to standard output.+--+-- Note that @<<<@ is a feature specific to the Bash shell to feed a string to+-- a command's standard input.  If you are using another shell, then you can+-- instead do this:+--+-- > $ echo '{=}' | dhall type+-- > {}+--+-- __Exercise__: Use the @dhall type@ command to infer the type of this record:+--+-- > -- ./nested.dhall+-- > { foo = 1+-- > , bar =+-- >     { baz = 2.0+-- >     , qux = True+-- >     }+-- > }+--+-- You can specify nested fields using dot-separated keys, like this:+--+-- > { foo = 1, bar.baz = 2.0, bar.qux = True }+--+-- ... which is equivalent to:+--+-- > { foo = 1, bar = { baz = 2.0, qux = True } }+--+-- You can also access a field of a record using the following syntax:+--+-- > record.fieldName+--+-- ... which means to access the value of the field named @fieldName@ from the+-- @record@.  For example:+--+-- >>> input auto "{ foo = True, bar = 2, baz = 4.2 }.baz" :: IO Double+-- 4.2+--+-- ... and you can project out multiple fields into a new record using this+-- syntax:+--+-- > someRecord.{ field₀, field₁, … }+--+-- For example:+--+-- > $ dhall <<< '{ x = 1, y = True, z = "ABC" }.{ x, y }'+-- > { x = 1, y = True }+--+-- This is our first example of using the @dhall@ command-line tool with no+-- subcommand (like @type@), which evaluates the provided expression.  By+-- default, this reads the expression on standard input and outputs the+-- evaluated result on standard output.+--+-- __Exercise__: Save the above @./nested.dhall@ file and then try to access the+-- value of the @baz@ field.  Test that this works by interpreting your code+-- using the @dhall@ command.+--+-- You can convert a record to a list of key-value pairs (a.k.a. a \"Map\") by+-- using the @toMap@ keyword.  For example:+--+-- > $ dhall <<< 'toMap { foo = 1, bar = 2 }'+-- > [ { mapKey = "bar", mapValue = 2 }, { mapKey = "foo", mapValue = 1 } ]+--+-- This conversion only works if all field of the record have the same type.+-- This comes in handy when you need to convert a Dhall record to the Dhall+-- equivalent of a homogeneous map (i.e. Haskell's @"Data.Map"@).++-- $functions+--+-- The Dhall programming language also supports user-defined anonymous+-- functions.  For example, we can save the following anonymous function to a+-- file:+--+-- > -- ./makeBools.dhall+-- > \(n : Bool) ->+-- >     [ n && True, n && False, n || True, n || False ]+--+-- ... or we can use Dhall's support for Unicode characters to use @λ@ (U+03BB)+-- instead of @\\@ and @→@ (U+2192) instead of @->@ (for people who are into+-- that sort of thing):+--+-- > $ -- ./makeBools.dhall+-- > λ(n : Bool) →+-- >     [ n && True, n && False, n || True, n || False ]+-- > <Ctrl-D>+--+-- We'll be sticking to ASCII for the remainder of the tutorial, though, while+-- still pointing out Unicode equivalents as we go.+--+-- You can read this as a function of one argument named @n@ that has type+-- @Bool@.  This function returns a @List@ of @Bool@s.  Each element of the+-- @List@ depends on the input argument named @n@.+--+-- The (ASCII) syntax for anonymous functions resembles the syntax for anonymous+-- functions in Haskell.  The only difference is that Dhall requires you to+-- annotate the type of the function's input.+--+-- You can import this function into Haskell, too:+--+-- >>> makeBools <- input auto "./makeBools.dhall" :: IO (Bool -> Vector Bool)+-- >>> makeBools True+-- [True,False,True,True]+--+-- The reason this works is that there is an `FromDhall` instance for simple+-- functions:+--+-- > instance (ToDhall a, FromDhall b) => FromDhall (a -> b)+--+-- Thanks to currying, this instance works for functions of multiple simple+-- arguments:+--+-- >>> dhallAnd <- input auto "\\(x : Bool) -> \\(y : Bool) -> x && y" :: IO (Bool -> Bool -> Bool)+-- >>> dhallAnd True False+-- False+--+-- However, you can't convert anything more complex than that (like a polymorphic+-- or higher-order function).  You will need to apply those functions to their+-- arguments within Dhall before converting their result to a Haskell value.+--+-- Just like `FromDhall`, you can derive `ToDhall` for user-defined data types:+--+-- > {-# LANGUAGE DeriveAnyClass    #-}+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > module Main where+-- >+-- > import Dhall+-- >+-- > data Example0 = Example0 { foo :: Bool, bar :: Bool }+-- >     deriving (Generic, ToDhall)+-- >+-- > main = do+-- >     f <- input auto "\\(r : { foo : Bool, bar : Bool }) -> r.foo && r.bar"+-- >     print (f (Example0 { foo = True, bar = False }) :: Bool)+-- >     print (f (Example0 { foo = True, bar = True  }) :: Bool)+--+-- The above program prints:+--+-- > False+-- > True++-- $compiler+--+-- We can also test our @makeBools@ function directly from the command line.+-- This library comes with a command-line executable program named @dhall@ that+-- you can use to both type-check files and convert them to a normal form.  Our+-- compiler takes a program on standard input and then prints the program's type+-- to standard error followed by the program's normal form to standard output:+--+-- > $ dhall --annotate <<< './makeBools.dhall'+-- > (λ(n : Bool) → [ n, False, True, n ]) : ∀(n : Bool) → List Bool+--+-- The @dhall@ command emits Unicode output by default, but you can switch to+-- ASCII output using the @--ascii@ flag:+--+-- > $ dhall --annotate --ascii <<< './makeBools.dhall'+-- > (\(n : Bool) -> [ n, False, True, n ]) : forall (n : Bool) -> List Bool+--+-- The @--annotate@ flag adds a type signature to the output to let us know+-- what type the interpreter inferred for our expression.  The type signature+-- is @∀(n : Bool) → List Bool@ which says that @makeBools@ is a function of one+-- argument named @n@ that has type @Bool@ and the function returns a @List@ of+-- @Bool@s.  The @∀@ (U+2200) symbol is shorthand for the ASCII @forall@+-- keyword:+--+-- > ∀(x : a) → b         -- This type ...+-- >+-- > forall (x : a) -> b  -- ... is the same as this type+--+-- ... and Dhall's @forall@ keyword behaves the same way as Haskell's @forall@+-- keyword for input values that are @Type@s:+--+-- > forall (x : Type) -> b  -- This Dhall type ...+--+-- > forall x . b            -- ... is the same as this Haskell type+--+-- The part where Dhall differs from Haskell is that you can also use+-- @∀@/@forall@ to give names to non-@Type@ arguments (such as the first+-- argument to @makeBools@).+--+-- This expression is our program's normal form:+--+-- > λ(n : Bool) → [ n, False, True, n ]+--+-- ... and the interpreter was able to simplify our expression by noting that:+--+-- * @n && True  = n@+-- * @n && False = False@+-- * @n || True  = True@+-- * @n || False = n@+--+-- To apply a function to an argument you separate the function and argument by+-- whitespace (just like Haskell):+--+-- @f x@+--+-- You can read the above as \"apply the function @f@ to the argument @x@\".  This+-- means that we can \"apply\" our @./makeBools@ function to a @Bool@ argument+-- like this:+--+-- > $ dhall <<< './makeBools.dhall True'+-- > [True, False, True, True]+--+-- Remember that file paths are synonymous with their contents, so the above+-- code is exactly equivalent to:+--+-- > $ dhall <<< '(\(n : Bool) -> [n && True, n && False, n || True, n || False]) True'+-- > [True, False, True, True]+--+-- When you apply an anonymous function to an argument, you substitute the+-- \"bound variable" with the function's argument:+--+-- >    Bound variable+-- >    ⇩+-- > (\(n : Bool) -> ...) True+-- >                      ⇧+-- >                      Function argument+--+-- So in our above example, we would replace all occurrences of @n@ with @True@,+-- like this:+--+-- > -- If we replace all of these `n`s with `True` ...+-- > [n && True, n && False, n || True, n || False]+-- >+-- > -- ... then we get this:+-- > [True && True, True && False, True || True, True || False]+-- >+-- > -- ... which reduces to the following normal form:+-- > [True, False, True, True]+--+-- Now that we've verified that our function type checks and works, we can use+-- the same function within Haskell:+--+-- >>> input auto "./makeBools.dhall True" :: IO (Vector Bool)+-- [True,False,True,True]+--+-- __Exercise__: Create a file named @getFoo@ that is a function of the following+-- type:+--+-- > forall (r : { foo : Bool, bar : Text }) -> Bool+--+-- This function should take a single input argument named @r@ that is a record+-- with two fields.  The function should return the value of the @foo@ field.+--+-- __Exercise__: Use the @dhall@ command to infer the type of the function you+-- just created and verify that your function has the correct type+--+-- __Exercise__: Use the @dhall@ command to apply your function to a sample+-- record++-- $strings+-- Dhall supports ordinary string literals with Haskell-style escaping rules:+--+-- > $ dhall+-- > "Hello, \"world\"!"+-- > <Ctrl-D>+-- > "Hello, \"world\"!"+--+-- ... and Dhall also supports Nix-style multi-line string literals:+--+-- > $ dhall+-- > ''+-- >     #!/bin/bash+-- >+-- >     echo "Hi!"+-- > ''+-- > <Ctrl-D>+-- > "\n#!/bin/bash\n\necho \"Hi!\"\n"+--+-- These \"double single quote strings\" ignore all special characters, with one+-- exception: if you want to include a @''@ in the string, you will need to+-- escape it with a preceding @'@ (i.e. use @'''@ to insert @''@ into the final+-- string).+--+-- These strings also strip leading whitespace using the same rules as Nix.+-- Specifically: \"it strips from each line a number of spaces equal to the+-- minimal indentation of the string as a whole (disregarding the indentation+-- of empty lines).\"+--+-- You can also interpolate expressions into strings using @${...}@ syntax.  For+-- example:+--+-- > $ dhall+-- > let name = "John Doe"+-- > let age  = 21+-- > in  "My name is ${name} and my age is ${Natural/show age}"+-- > <Ctrl-D>+-- > "My name is John Doe and my age is 21"+--+-- Note that you can only interpolate expressions of type @Text@+--+-- If you need to insert a @"${"@ into a string without interpolation then use+-- @"''${"@ (same as Nix)+--+-- > ''+-- >     for file in *; do+-- >       echo "Found ''${file}"+-- >     done+-- > ''++-- $combine+--+-- You can combine two records, using either the @(//)@ operator or the+-- @(/\\)@ operator.+--+-- The @(//)@ operator (or @(⫽)@ U+2AFD) combines the fields of both records,+-- preferring fields from the right record if they share fields in common:+--+-- > $ dhall+-- > { foo = 1, bar = "ABC" } // { baz = True }+-- > <Ctrl-D>+-- > { bar = "ABC", baz = True, foo = 1 }+-- > $ dhall+-- > { foo = 1, bar = "ABC" } ⫽ { bar = True }  -- Fancy unicode+-- > <Ctrl-D>+-- > { bar = True, foo = 1 }+--+-- Note that the order of record fields does not matter.  The compiler+-- automatically sorts the fields.+--+-- If you need to set or add a deeply nested field you can use the @with@+-- keyword, like this:+--+-- > $ dhall <<< '{ x.y = 1 } with x.z = True'+-- > { x = { y = 1, z = True } }+--+-- > $ dhall <<< '{ x.y = 1 } with x.y = 2'+-- > { x.y = 2 }+--+-- The @with@ keyword is syntactic sugar for the @//@ operator which follows+-- these rules:+--+-- > -- Nested case+-- > record with k.ks… = value  ⇒  record // { k = record.k with ks… = value }+-- >+-- > -- Base case+-- > record with k = value      ⇒  record // { k = value }+--+-- The @(/\\)@ operator (or @(∧)@ U+2227) also lets you combine records, but+-- behaves differently if the records share fields in common.  The operator+-- combines shared fields recursively if they are both records:+--+-- > $ dhall+-- > { foo = { bar = True }, baz = "ABC" } /\ { foo = { qux = 1.0 } }+-- > <Ctrl-D>+-- > { baz = "ABC", foo = { bar = True, qux = 1.0 } }+--+-- ... but fails with a type error if either shared field is not a record:+--+-- > $ dhall+-- > { foo = 1, bar = "ABC" } /\ { foo = True }+-- > <Ctrl-D>+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: Field collision+-- >+-- > { foo = 1, bar = "ABC" } ∧ { foo = True }+-- >+-- > (input):1:1+--+-- __Exercise__: Combine any record with the empty record.  What do you expect+-- to happen?+--+-- You can analogously combine record types using the @//\\\\@ operator (or @(⩓)@ U+2A53):+--+-- > $ dhall+-- > { foo : Natural } //\\ { bar : Text }+-- > <Ctrl-D>+-- > { foo : Natural, bar : Text }+--+-- ... which behaves the exact same, except at the type level, meaning that the+-- operator descends recursively into record types:+--+-- > $ dhall+-- > { foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Natural }+-- > <Ctrl-D>+-- > { foo : { bar : Text, baz : Bool }, qux : Natural }++-- $let+--+-- Dhall also supports @let@ expressions, which you can use to define+-- intermediate values in the course of a computation, like this:+--+-- > $ dhall+-- > let x = "ha" in x ++ x+-- > <Ctrl-D>+-- > "haha"+--+-- You can also annotate the types of values defined within a @let@ expression,+-- like this:+--+-- > $ dhall+-- > let x : Text = "ha" in x ++ x+-- > <Ctrl-D>+-- > "haha"+--+-- You need to nest @let@ expressions if you want to define more than one value+-- in this way:+--+-- > $ dhall+-- > let x = "Hello, "+-- > let y = "world!"+-- > in  x ++ y+-- > <Ctrl-D>+-- > "Hello, world!"+--+-- Dhall is whitespace-insensitive, so feel free to format things over multiple+-- lines or indent in any way that you please.+--+-- If you want to define a named function, just give a name to an anonymous+-- function:+--+-- > $ dhall+-- > let twice = \(x : Text) -> x ++ x in twice "ha"+-- > <Ctrl-D>+-- > "haha"+--+-- Unlike Haskell, Dhall does not support function arguments on the left-hand+-- side of the equals sign, so this will not work:+--+-- > $ dhall+-- > let twice (x : Text) = x ++ x in twice "ha"+-- > <Ctrl-D>+-- > Error: Invalid input+-- >+-- > (input):1:11:+-- >   |+-- > 1 | let twice (x : Text) = x ++ x in twice "ha"+-- >   |           ^+-- > unexpected '('+-- > expecting ':', '=', or the rest of label+--+-- The error message says that Dhall expected either a @(:)@ (i.e. the beginning+-- of a type annotation) or a @(=)@ (the beginning of the assignment) and not a+-- function argument.+--+-- You can also use @let@ expressions to rename imports, like this:+--+-- > $ dhall+-- > let not = https://prelude.dhall-lang.org/Bool/not+-- > in  not True+-- > <Ctrl-D>+-- > False+--+-- ... or to define synonyms for types:+--+-- > $ dhall <<< 'let Name : Type = Text in [ "John", "Mary" ] : List Name'+-- > List Text+-- >+-- > [ "John", "Mary" ]+--+-- __Exercise:__ What do you think the following code will normalize to?+--+-- > let x = 1+-- > let x = 2+-- > in  x+--+-- Test your guess using the @dhall@ compiler+--+-- __Exercise:__ Now try to guess what this code will normalize to:+--+-- > let x = "ha"+-- > let x = x ++ "ha"+-- > in  x+--+-- __Exercise:__ What about this code?+--+-- > let x = x ++ "ha"+-- > in  x++-- $defaults+--+-- For records with a large number of defaultable fields you can use the+-- @::@ operator to auto-complete a record.  For example:+--+-- > let greet =+-- >           \(args : { greeting : Text, name : Text })+-- >       ->  "${args.greeting}, ${args.name}!"+-- >+-- > let Greeting =+-- >       { Type = { greeting : Text, name : Text }+-- >       , default = { greeting = "Hello", name = "John" }+-- >       }+-- >+-- > in  ''+-- >     ${greet Greeting::{=}}+-- >     ${greet Greeting::{ greeting = "Hola" }}+-- >     ${greet Greeting::{ name = "Jane" }}+-- >     ${greet Greeting::{ greeting = "Hola", name = "Jane" }}+-- >     ''+--+-- This operator is syntactic sugar.  Specifically an expression of the form:+--+-- > T::r+--+-- ... is equivalent to:+--+-- > (T.default // r) : T.Type+--+-- So, for example:+--+-- > Greeting::{ greeting = "Hola" }+--+-- ... is the same thing as:+--+-- > (Greeting.default // { greeting = "Hola" }) : Greeting.Type+--+-- ... which is the same thing as:+--+-- > ({ greeting = "Hello", name = "John" } // { greeting = "Hola" }) : { greeting : Text, name : Text }+--+-- ... which is the same thing as:+--+-- > { greeting = "Hola", name = "John" }++-- $unions+--+-- A union is a value that can be one of many alternative types of values.  For+-- example, the following union type:+--+-- > < Left : Natural | Right : Bool >+--+-- ... represents a value that can be either a @Natural@ or a @Bool@ value.  If+-- you are familiar with Haskell these are exactly analogous to Haskell's+-- \"sum types\" and the above type is equivalent to @Either Natural Bool@.+--+-- Each alternative is associated with a tag that distinguishes that alternative+-- from other alternatives.  In the above example, the @Left@ tag is used for+-- the @Natural@ alternative and the @Right@ tag is used for the @Bool@+-- alternative.+--+-- You can specify the value of a union constructor like this:+--+-- > let Union = < Left : Natural | Right : Bool>+-- >+-- > in  [ Union.Left 0, Union.Right True ]+--+-- In other words, you can access a union constructor as a field of a union+-- type and use that constructor to wrap a value of a type appropriate for+-- that alternative.  In the above example, the @Left@ constructor can wrap+-- a @Natural@ value and the @Right@ constructor can wrap a @Bool@ value.  We+-- can also confirm that by inspecting their type:+--+-- > $ echo '< Left : Natural | Right : Bool>' > ./Union+--+-- > $ dhall --annotate <<< '(./Union).Left'+-- >   < Left : Natural | Right : Bool >.Left+-- > : ∀(Left : Natural) → < Left : Natural | Right : Bool >+--+-- > $ dhall --annotate <<< '(./Union).Right'+-- >   < Left : Natural | Right : Bool >.Right+-- > : ∀(Right : Bool) → < Left : Natural | Right : Bool >+--+-- In other words, the @Left@ constructor is a function from a @Natural@ to a+-- value of our @Union@ type and the @Right@ constructor is a separate function+-- from a @Bool@ to that same @Union@ type.+--+-- You can consume a union using the built-in @merge@ function.  For example,+-- suppose we want to convert our union to a @Bool@ but we want to behave+-- differently depending on whether or not the union is a @Natural@ wrapped in+-- the @Left@ constructor or a @Bool@ wrapped in the @Right@ constructor .  We+-- would write:+--+-- > $ cat > process <<EOF+-- >   \(union : < Left : Natural | Right : Bool >) ->+-- >     let handlers =+-- >             { Left  = Natural/even  -- Natural/even is a built-in function+-- >             , Right = \(b : Bool) -> b+-- >             }+-- > in  merge handlers union+-- > EOF+--+-- Now our @./process@ function can handle both alternatives:+--+-- > $ dhall <<< './process ((./Union).Left 3)'+-- > False+--+-- > $ dhall <<< './process ((./Union).Right True)'+-- > True+--+-- Every @merge@ has the following form:+--+-- > merge handlers union [ : type ]+--+-- ... where:+--+-- * @union@ is the union you want to consume+-- * @handlers@ is a record with one function per alternative of the union+-- * @type@ is an optional declared result type of the @merge@+--+-- The @merge@ function selects which function to apply from the record based on+-- which alternative the union selects:+--+-- > merge { Foo = f, ... } (< … >.Foo x) = f x+--+-- So, for example:+--+-- > merge { Left = Natural/even, Right = \(b : Bool) -> b } (< Left : Natural | Right : Bool >.Left 3)+-- >     = Natural/even 3+-- >     = False+--+-- ... and similarly:+--+-- > merge { Left = Natural/even, Right = \(b : Bool) -> b } (< Left : Natural | Right : Bool >.Right True)+-- >     = (\(b : Bool) -> b) True+-- >     = True+--+-- Notice that each handler has to return the same type of result (@Bool@ in+-- this case).+--+-- You can also store more than one value within alternatives using Dhall's+-- support for anonymous records.  You can nest an anonymous record within a+-- union such as in this type:+--+-- > < Empty : {} | Person : { name : Text, age : Natural } >+--+-- You can even go a step further and omit the type of an alternative if it+-- stores no data, like this:+--+-- > < Empty | Person : { name : Text, age : Natural } >+--+-- The above Dhall type resembles the following equivalent Haskell data type:+--+-- > data Example = Empty | Person { name :: Text, age :: Text }+--+-- Empty alternatives like @Empty@ require no argument:+--+-- > let Example = < Empty | Person : { name : Text, age : Natural } >+-- >+-- > in  [ Example.Empty  -- Note the absence of any argument to `Empty`+-- >     , Example.Person { name = "John", age = 23 }+-- >     , Example.Person { name = "Amy" , age = 25 }+-- >     ]+--+-- ... and when you @merge@ an empty alternative the correspond handler takes no+-- argument:+--+-- > \(x : < Empty | Person : { name : Text, age : Natural } >) ->+-- >   merge+-- >     { Empty = "Unknown"  -- Note the absence of an anonymous function+-- >+-- >     , Person =+-- >         \(person : { name : Text, age : Natural }) ->+-- >           "Name: ${person.name}, Age: ${Natural/show person.age}"+-- >     }+-- >     x+--+-- __Exercise__: Create a list of the following type with at least one element+-- per alternative:+--+-- > List < Left : Natural | Right : Double >++-- $polymorphic+--+-- The Dhall language supports defining polymorphic functions (a.k.a.+-- \"generic\" functions) that work on more than one type of value.  However,+-- Dhall differs from Haskell by not inferring the types of these polymorphic+-- functions.  Instead, you must be explicit about what type of value the+-- function is specialized to.+--+-- Take, for example, Haskell's identity function named @id@:+--+-- > id :: a -> a+-- > id = \x -> x+--+-- The identity function is polymorphic, meaning that `id` works on values of+-- different types:+--+-- >>> id 4+-- 4+-- >>> id True+-- True+--+-- The equivalent function in Dhall is:+--+-- > \(a : Type) -> \(x : a) -> x+--+-- Notice how this function takes two arguments instead of one.  The first+-- argument is the type of the second argument.+--+-- Let's illustrate how this works by actually using the above function:+--+-- > $ echo "\\(a : Type) -> \\(x : a) -> x" > id+--+-- Let's ask the interpreter for the type of this function:+-- the first line:+--+-- > $ dhall type <<< './id'+-- > ∀(a : Type) → ∀(x : a) → a+--+-- You can read the type @(∀(a : Type) → ∀(x : a) → a)@ as saying: \"This is the+-- type of a function whose first argument is named @a@ and is a @Type@.  The+-- second argument is named @x@ and has type @a@ (i.e. the value of the first+-- argument).  The result also has type @a@.\"+--+-- This means that the type of the second argument changes depending on what+-- type we provide for the first argument.  When we apply @./id@ to @Natural@,+-- we create a function that expects an @Natural@ argument:+--+-- > $ dhall type <<< './id Natural'+-- > ∀(x : Natural) → Natural+--+-- Similarly, when we apply @./id@ to @Bool@, we create a function that expects a+-- @Bool@ argument:+--+-- > $ dhall type <<< './id Bool'+-- > ∀(x : Bool) → Bool+--+-- We can then supply the final argument to each of those functions to show+-- that they both work on their respective types:+--+-- > $ dhall <<< './id Natural 4'+-- > 4+--+-- > $ dhall <<< './id Bool True'+-- > True+--+-- Built-in functions can also be polymorphic, too.  For example, we can ask+-- the compiler for the type of @List/reverse@, the function that reverses a+-- list:+--+-- > $ dhall --annotate+-- > List/reverse+-- > <Ctrl-D>+-- > List/reverse : ∀(a : Type) → List a → List a+--+-- The first argument to @List/reverse@ is the type of the list to reverse:+--+-- > $ dhall+-- > List/reverse Bool+-- > <Ctrl-D>+-- > List/reverse Bool : List Bool → List Bool+--+-- ... and the second argument is the list to reverse:+--+-- > $ dhall+-- > List/reverse Bool [True, False]+-- > <Ctrl-D>+-- > [False, True]+--+-- Note that the second argument has no name.  This type:+--+-- > ∀(a : Type) → List a → List a+--+-- ... is equivalent to this type:+--+-- > ∀(a : Type) → ∀(_ : List a) → List a+--+-- In other words, if you don't see the @∀@ symbol surrounding a function+-- argument type then that means that the name of the argument is @"_"@.  This+-- is true even for user-defined functions:+--+-- > $ dhall type <<< '\\(_ : Text) -> 1'+-- > Text → Natural+--+-- The type @Text → Natural@ is the same as @∀(_ : Text) → Natural@+--+-- __Exercise__ : Translate Haskell's `flip` function to Dhall++-- $total+--+-- Dhall is a total programming language, which means that Dhall is not+-- Turing-complete and evaluation of every Dhall program is guaranteed to+-- eventually halt.  There is no upper bound on how long the program might take+-- to evaluate, but the program is guaranteed to terminate in a finite amount of+-- time and not hang forever.+--+-- This guarantees that all Dhall programs can be safely reduced to a normal+-- form where as many functions have been evaluated as possible.  In fact, Dhall+-- expressions can be evaluated even if all function arguments haven't been fully+-- applied.  For example, the following program is an anonymous function:+--+-- > $ dhall+-- > \(n : Bool) -> 10 * 10+-- > <Ctrl-D>+-- > λ(n : Bool) → 100+--+-- ... and even though the function is still missing the first argument named+-- @n@ the compiler is smart enough to evaluate the body of the anonymous+-- function ahead of time before the function has even been invoked.+--+-- We can use the @map@ function from the Prelude to illustrate an even more+-- complex example:+--+-- > $ dhall+-- > let List/map = https://prelude.dhall-lang.org/List/map+-- > in  \(f : Natural → Natural) -> List/map Natural Natural f [1, 2, 3]+-- > <Ctrl-D>+-- > λ(f : Natural → Natural) → [f 1, f 2, f 3]+--+-- Dhall can apply our function to each element of the list even before we specify+-- which function to apply.+--+-- The language will also never crash or throw any exceptions.  Every+-- computation will succeed and produce something, even if the result might be+-- an @Optional@ value:+--+-- > $ dhall <<< 'List/head Natural ([] : List Natural)'+-- > None Natural+--+-- __Exercise__: The Dhall Prelude provides a @replicate@ function which you can+-- find here:+--+-- <https://prelude.dhall-lang.org/List/replicate>+--+-- Test what the following Dhall expression normalizes to:+--+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in  replicate 10+--+-- __Exercise__: If you have a lot of spare time, try to \"break the compiler\"+-- by finding an input expression that crashes or loops forever (and file a bug+-- report if you succeed).++-- $assertions+--+-- You can add compile-time assertions which you can use to add tests to your+-- code.  For example, we can add some tests to our @not@ function like this:+--+-- > let not+-- >     : Bool -> Bool+-- >     = \(b : Bool) -> b == False+-- >+-- > let example0 = assert : not False === True+-- >+-- > let example1 = assert : not True === False+-- >+-- > in  not+--+-- The expression @assert : not False == True@ is a type-checking assertion+-- that two expressions have the same normal form.  If the two expressions differ+-- then type-checking rejects the code.+--+-- For example, suppose that we change the example to add an incorrect assertion:+--+-- > -- ./test.dhall+-- >+-- > let not+-- >     : Bool -> Bool+-- >     = \(b : Bool) -> b == False+-- >+-- > let example0 = assert : not False === True+-- >+-- > let example1 = assert : not True === True  -- Oops!+-- >+-- > in  not+--+-- The type-checker then rejects the assertion with the following error message:+--+-- > $ dhall <<< './test.dhall'+-- >+-- > ↳ ./test.dhall+-- >+-- > Error: Assertion failed+-- >+-- > - False+-- > + True+-- >+-- > 7│                assert : not True === True -- Oops!+-- > 8│+-- >+-- > ./test.dhall:7:16+-- >+-- > 1│ ./test.dhall+-- >+-- > (input):1:1+--+-- You can compare expressions that contain variables, too, which is equivalent+-- to symbolic reasoning:+--+-- > $ dhall <<< '\(n : Natural) -> assert : n === (n + 0)'+-- > λ(n : Natural) → assert : n ≡ n+--+-- Dhall accepts this because the language has built-in support for normalizing+-- @n + 0@ to @n@, so both sides of the comparison normalize to the same value:+-- @n@.+--+-- Note that this sort of symbolic reasoning is limited and can only detect+-- equality of normal forms.  Some equivalent expressions will be rejected+-- if they don't share the same normal form, such as these:+--+-- > $ dhall <<< '\(n : Natural) -> assert : Natural/even (n + n) === True'+-- >+-- > Use "dhall --explain" for detailed errors+-- >+-- > n : Natural+-- >+-- > Error: Assertion failed+-- >+-- > - … …+-- > + True+-- >+-- > 1│                   assert : Natural/even (n + n) === True+-- >+-- > (input):1:19+--+-- Here the interpreter is not smart enough to simplify @Natural/even (n + n)@+-- to @True@ so the assertion fails.+--+-- If you prefer to use Unicode, then the Unicode equivalent of @===@ is @≡@+-- (U+2261).++-- $headers+--+-- Sometimes you would like to provide additional request headers when importing+-- Dhall expressions from URLs.  For example, you might want to provide an+-- authorization header or specify the expected content type.+--+-- Dhall URL imports let you add or modify request headers with the @using@+-- keyword:+--+-- > https://example.com/example.dhall using ./headers+--+-- ... where you can replace @./headers@ with any import that points to a Dhall+-- expression of the following type:+--+-- > List { header : Text, value : Text }+--+-- For example, if you needed to specify the content type correctly in order to+-- download the file, then your @./headers@ file might look like this:+--+-- > $ cat headers+-- > [ { header = "Accept", value = "application/dhall" } ]+--+-- ... or if you needed to provide an authorization token to access a private+-- GitHub repository, then your headers could look like this:+--+-- > [ { header = "Authorization", value = "token ${env:GITHUB_TOKEN as Text}" } ]+--+-- This would read your GitHub API token from the @GITHUB_TOKEN@ environment+-- variable and supply that token in the authorization header.+--+-- You cannot inline the headers within the same file as the URL.  You must+-- provide them as a separate import.  That means that this is /not/ legal code:+--+-- > http://example.com/example.dhall using [ { header = "Accept", value = "application/dhall" } ]  -- NOT legal+--+-- Dhall will forward imports if you import an expression from a URL that+-- contains a relative import.  For example, if you import an expression like+-- this:+--+-- > http://example.com/example.dhall using ./headers+--+-- ... and @http:\/\/example.com/example.dhall@ contains a relative import of @./foo@+-- then Dhall will import @http:\/\/example.com/foo@ using the same @./headers@ file.++-- $integrity+--+-- Sometimes you want to use share code while still ensuring that the imported+-- value never changes and can't be corrupted by a malicious attacker.  Dhall+-- provides built-in support for hashing imported values to verify that their+-- value never changes+--+-- For example, suppose you save the following two files:+--+-- > $ cat ./foo+-- > ./bar sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+--+-- > $ cat ./bar+-- > ./baz+--+-- > $ cat ./baz+-- > 1+--+-- The first file named @./foo@ contains an example of an integrity check.  You+-- can add @sha256:XXX@ after any import (such as after @./bar@), where @XXX@ is+-- an expected 64-character @sha256@ hash of the Dhall value.  To be precise,+-- the hash represents a @sha256@ hash of the UTF-8 encoding of a canonical text+-- representation of the fully resolved and normalized abstract syntax tree of+-- the imported expression.+--+-- Dhall will verify that the expected hash matches the actual hash of the+-- imported Dhall value and reject the import if there is a hash mismatch:+--+-- > $ dhall <<< './foo'+-- > Natural+-- >+-- > 1+--+-- Any import protected by a semantic integrity check is automatically cached+-- locally underneath either @~\/.cache\/dhall\/1220${HASH}@ or+-- @${XDG_CACHE_HOME}\/dhall/1220${HASH}@ if you define the @XDG_CACHE_HOME@+-- environment variable.+--+-- For example, after you import @./foo@ the contents of `./bar` are locally+-- cached in a fully-evaluated and binary-encoded form which you can inspect by+-- running:+--+-- > $ dhall decode < ~/.cache/dhall/1220d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+-- > 1+--+-- Subsequent attempts to resolve the same import will automatically retrieve+-- the import from the cache.  This matters less for local imports, but comes in+-- handy for remote imports to avoid redownloading them.+--+-- The local cache takes precedence when resolving imports, so changing the+-- original import afterwards will have no affect until you update the hash.+-- From Dhall's point of view, the hash is the true address and the file path+-- is just a suggestion for how to obtain the import if it's not already cached.+--+-- You can disable the cache by setting @XDG_CACHE_HOME@ to `/var/empty` (an+-- empty and unwritable directory), like this:+--+-- > $ XDG_CACHE_HOME=/var/empty dhall <<< './foo'+-- > Natural+-- >+-- > 1+--+-- We'll use this trick to test changes to the protected import in the following+-- examples.+--+-- Now, suppose you add a comment to the @./bar@ file:+--+-- > $ cat ./bar+-- > -- This comment does not change the hash+-- > ./baz+--+-- ... then @./foo@ will still successfully import @./bar@ because the hash+-- only depends on the normalized value and does not depend on meaningless+-- changes to whitespace or comments:+--+-- > $ XDG_CACHE_HOME=/var/empty dhall <<< './foo'  # This still succeeds+-- > Natural+-- >+-- > 1+--+-- You can compute the Hash for any import by using the hash subcommand+-- of this package.  For example:+--+-- > $ dhall hash <<< './bar'+-- > sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+--+-- Now suppose that you actually change the value of the @./baz@ file:+--+-- > $ cat ./baz+-- > 2+--+-- ... then the @./foo@ file will fail to import @./bar@, even though the+-- text of the @./bar@ file technically never changed:+--+-- > XDG_CACHE_HOME=/var/empty dhall <<< './foo'+-- >+-- > Error: Import integrity check failed+-- >+-- > Expected hash:+-- >+-- > ↳ d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+-- >+-- > Actual hash:+-- >+-- > ↳ 4caf97e8c445d4d4b5c5b992973e098ed4ae88a355915f5a59db640a589bc9cb+--+-- This is because the @./bar@ file now represents a new value (@2@ instead of+-- @1@), even though the text of the @./bar@ file is still the same.  Since the+-- value changed the hash must change as well.  However, we could change @./baz@+-- to:+--+-- > $ cat baz+-- > if True then 1 else 2+--+-- ... and the import would now succeed again because the final result is @1@.+--+-- The integrity hash ensures that your import's final meaning can never change,+-- so an attacker can never compromise an imported value protected by a hash+-- unless they can break SHA-256 encryption.  The hash not only protects the+-- file that you immediately import, but also protects every transitive import+-- as well.+--+-- You can also safely refactor your imported dependencies knowing that the+-- refactor will not change your hash so long as your refactor is+-- behavior-preserving.  This provides an easy way to detect refactoring errors+-- that you might accidentally introduce.  The hash not only protects you+-- from attackers, but also protects against human error, too!+--+-- If you have a file which either doesn't already use hashed imports,+-- or you changed some of the imports and want to update the hashes you can use the+-- freeze command to either add or update hashes:+--+-- > $ cat foo.dhall+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in  replicate 5+-- > $+-- > $ dhall freeze ./foo.dhall+-- > $ cat ./foo.dhall+-- > let replicate =+-- >       https://prelude.dhall-lang.org/List/replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+-- >+-- > in  replicate 5++-- $rawText+--+-- Sometimes you want to import the contents of a raw text file as a Dhall+-- value of type `Dhall.Syntax.Text`.  For example, one of the fields of a+-- record might be the contents of a software license:+--+-- > { package = "dhall"+-- > , author  = "Gabriella Gonzalez"+-- > , license = ./LICENSE+-- > }+--+-- Normally if you wanted to import a text file you would need to wrap the+-- contents of the file in double single-quotes, like this:+--+-- > $ cat LICENSE+-- > ''+-- > Copyright (c) 2017 Gabriella Gonzalez+-- > All rights reserved.+-- >+-- > ...+-- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+-- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+-- > ''+--+-- ... which does not work well if you need to reuse the same text file for+-- other programs+--+-- However, Dhall supports importing a raw text file by adding @as Text@ to the+-- end of the import, like this:+--+-- > { package = "dhall"+-- > , author  = "Gabriella Gonzalez"+-- > , license = ./LICENSE as Text+-- > }+--+-- ... and then you can use the original text file unmodified:+--+-- > $ cat LICENSE+-- > Copyright (c) 2017 Gabriella Gonzalez+-- > All rights reserved.+-- >+-- > ...+-- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+-- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++-- $format+--+-- A format subcommand is also available that you can use to+-- automatically format Dhall expressions.  For example, we can take the+-- following unformatted Dhall expression:+--+-- > $ cat ./unformatted+-- > λ(a : Type) → λ(kvss : List (List { index : Natural, value : a })) →+-- > List/build { index : Natural, value : a } (λ(list : Type) → λ(cons : {+-- > index : Natural, value : a } → list → list) → λ(nil : list) →+-- > (List/fold (List { index : Natural, value : a }) kvss { count : Natural, diff :+-- > Natural → list } (λ(kvs : List { index : Natural, value : a }) → λ(y : {+-- > count : Natural, diff : Natural → list }) → { count = y.count + List/length+-- > { index : Natural, value : a } kvs, diff = λ(n : Natural) → List/fold {+-- > index : Natural, value : a } kvs list (λ(kvOld : { index : Natural, value : a+-- > }) → λ(z : list) → cons { index = kvOld.index + n, value = kvOld.value }+-- > z) (y.diff (n + List/length { index : Natural, value : a } kvs)) }) { count =+-- > 0, diff = λ(_ : Natural) → nil }).diff 0)+--+-- ... and run the expression through the formatter:+--+-- > $ dhall format < ./unformatted+-- > λ(a : Type) →+-- > λ(kvss : List (List { index : Natural, value : a })) →+-- >   List/build+-- >     { index : Natural, value : a }+-- >     ( λ(list : Type) →+-- >       λ(cons : { index : Natural, value : a } → list → list) →+-- >       λ(nil : list) →+-- >         ( List/fold+-- >             (List { index : Natural, value : a })+-- >             kvss+-- >             { count : Natural, diff : Natural → list }+-- >             ( λ(kvs : List { index : Natural, value : a }) →+-- >               λ(y : { count : Natural, diff : Natural → list }) →+-- >                 { count =+-- >                     y.count + List/length { index : Natural, value : a } kvs+-- >                 , diff =+-- >                     λ(n : Natural) →+-- >                       List/fold+-- >                         { index : Natural, value : a }+-- >                         kvs+-- >                         list+-- >                         ( λ(kvOld : { index : Natural, value : a }) →+-- >                           λ(z : list) →+-- >                             cons+-- >                               { index = kvOld.index + n, value = kvOld.value }+-- >                               z+-- >                         )+-- >                         ( y.diff+-- >                             (n + List/length { index : Natural, value : a } kvs)+-- >                         )+-- >                 }+-- >             )+-- >             { count = 0, diff = λ(_ : Natural) → nil }+-- >         ).diff+-- >           0+-- >     )+--+-- The executable formats expressions without resolving, type-checking, or+-- normalizing them:+--+-- > $ dhall format+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))+-- > <Ctrl-D>+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- >+-- > in  replicate+-- >       5+-- >       (List (List Natural))+-- >       (replicate 5 (List Natural) (replicate 5 Natural 1))+--+-- You can also use the formatter to modify files in place:+--+-- > $ dhall format ./unformatted+--+-- Carefully note that the code formatter does not preserve all comments.+-- Currently, the formatter only preserves two types of comments:+--+-- * Leading comments at the beginning of the file+-- * Comments within a @let@ binding+--+-- For example:+--+-- > $ dhall format+-- > {- This comment will be preserved by the formatter -}+-- > -- ... and this comment will be preserved, too+-- > {- This comment will *NOT* be preserved -} 1+-- > -- ... and this comment will also *NOT* be preserved+-- > <Ctrl-D>+-- > {- This comment will be preserved by the formatter -}+-- > -- ... and this comment will be preserved, too+-- > 1+--+-- Also:+--+-- > let {- This comment will be preserved -}+-- >     x {- This comment will also be preserved-} =+-- >     {- ... and this one will be preserved, too -}+-- >       1+-- >+-- > in  x+--+-- Note that you do not need to format the output of the+-- @dhall@ interpreter.  The interpreter already automatically formats+-- multi-line expressions, too:+--+-- > $ dhall+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))+-- > <Ctrl-D>+-- > [ [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > ]++-- $builtins+--+-- Dhall is a restricted programming language that only supports simple built-in+-- functions and operators.  If you want to do anything fancier you will need to+-- load your data into Haskell for further processing+--+-- This section covers types, functions, and operators that are built into the+-- language, meaning that you do not need to import any code to use them.+-- Additionally, Dhall also comes with a Prelude (covered in the next section)+-- hosted online that contains functions derived from these base utilities.  The+-- Prelude also re-exports all built-in functions for people who prefer+-- consistency.+--+-- The language provides built-in support for the following primitive types:+--+-- * @Bool@ values+-- * @Natural@ values+-- * @Integer@ values+-- * @Double@ values+-- * @Text@ values+--+-- ... as well as support for the following derived types:+--+-- * @List@s of values+-- * @Optional@ values+-- * Anonymous records+-- * Anonymous unions+--+-- You can find an up-to-date list of available built-in functions and operators+-- here:+--+-- <https://docs.dhall-lang.org/references/Built-in-types.html>++-- $caveats+--+-- Dhall differs in a few important ways from other programming languages, so+-- you should keep the following caveats in mind:+--+-- First, Dhall only supports addition and multiplication on @Natural@ numbers+-- (i.e. non-negative integers), which are not the same type of number as+-- @Integer@s (which can be negative).  An @Integer@ number is a number prefixed+-- with either a @+@ or @-@ symbol whereas a @Natural@ number has no leading+-- sign.  If you try to add or multiply two @Integer@s you will get a type+-- error:+--+-- > $ dhall+-- > +2 + +2+-- > <Ctrl-D>+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: ❰+❱ only works on ❰Natural❱s+-- >+-- > +2 + +2+-- >+-- > (input):1:1+--+-- There are no built-in functions for @Integer@ arithmetic; however, conversion+-- to and from @Natural@s is possible usinng @Integer/clamp@, @Integer/negate@+-- and @Natural/toInteger@.+--+-- For @Double@s the situation is even more extreme: there are no built-in+-- functions other than @Double/show@. As far as the language is concerned they+-- are opaque values that can only be shuffled around but not used in any+-- meaningful way until they have been loaded into Haskell.+--+-- Second, the equality @(==)@ and inequality @(!=)@ operators only work on+-- @Bool@s.  You cannot test any other types of values for equality.+--+-- However, you can extend the language with your own built-ins using the+-- Haskell API, as described in the next section.++-- $extending+--+-- You can use the Haskell API to extend the Dhall configuration language with+-- new built-in functions.  This section contains a simple Haskell recipe to add+-- a new @Natural/equal@ built-in function of type:+--+-- > Natural/equal : Natural -> Natural -> Bool+--+-- To do so, we:+--+-- * extend the type-checking context to include the type of @Natural/equal@+-- * extend the normalizer to evaluate all occurrences of @Natural/equal@+--+-- ... like this:+--+-- > -- example.hs+-- >+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > module Main where+-- >+-- > import Dhall.Core (Expr(..), ReifiedNormalizer(..))+-- >+-- > import qualified Data.Text.IO+-- > import qualified Dhall+-- > import qualified Dhall.Context+-- > import qualified Lens.Family   as Lens+-- >+-- > main :: IO ()+-- > main = do+-- >     text <- Data.Text.IO.getContents+-- >+-- >     let startingContext = transform Dhall.Context.empty+-- >           where+-- >             transform = Dhall.Context.insert "Natural/equal" naturalEqualType+-- >+-- >             naturalEqualType =+-- >                 Pi "_" Natural (Pi "_" Natural Bool)+-- >+-- >     let normalizer (App (App (Var "Natural/equal") (NaturalLit x)) (NaturalLit y)) =+-- >             Just (BoolLit (x == y))+-- >         normalizer _ =+-- >             Nothing+-- >+-- >     let inputSettings = transform Dhall.defaultInputSettings+-- >           where+-- >             transform =+-- >                   Lens.set Dhall.normalizer      (Just (ReifiedNormalizer (pure . normalizer)))+-- >                 . Lens.set Dhall.startingContext startingContext+-- >+-- >     x <- Dhall.inputWithSettings inputSettings Dhall.auto text+-- >+-- >     Data.Text.IO.putStrLn x+--+-- Here is an example use of the above program:+--+-- > $ ./example <<< 'if Natural/equal 2 (1 + 1) then "Equal" else "Not equal"'+-- > Equal+--+-- Note that existing Dhall tools that type-check expressions will reject+-- expressions containing unexpected free variable such as @Natural/equal@:+--+-- > $ dhall <<< 'Natural/equal 2 (1 + 1)'+-- >+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: Unbound variable+-- >+-- > Natural/equal+-- >+-- > (input):1:1+--+-- You will need to either:+--+-- * create your own parallel versions of these tools, or:+-- * < https://github.com/dhall-lang/dhall-lang/blob/master/.github/CONTRIBUTING.md#how-do-i-change-the-language try to upstream your built-ins into the language>+--+-- The general guidelines for adding new built-ins to the language are:+--+-- * Keep built-ins easy to implement across language bindings+-- * Prefer general purpose built-ins or built-ins appropriate for the task of program configuration+-- * Design built-ins to catch errors as early as possible (i.e. when type-checking the configuration)++-- $substitutions+--+-- Substitutions are another way to extend the language.+--+-- Suppose we have the following Haskell datatype:+--+-- > data Result = Failure Integer | Success String+-- >     deriving (Eq, Generic, Show)+-- >+-- > instance FromDhall Result+--+-- We can use it in Dhall like that:+--+-- > -- example.dhall+-- >+-- > let Result = < Failure : Integer | Success : Text >+-- > in Result.Failure +1+--+-- Right now it is quite easy to keep these two definitions (the one in Haskell source and the one in the Dhall file) synchronized:+-- If we implement a new feature in the Haskell source we update the corresponding type in the Dhall file.+-- But what happens if our application is growing and our Result type contains e.g. 10 unions with possible types embedded in it?+--+-- We can override the interpreter's @evaluateSettings@ with a custom set of+-- substitutions, like this:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > myexample :: IO Result+-- > myexample = let+-- >    evaluateSettings = Lens.over Dhall.substitutions (Dhall.Map.insert "Result" resultType) Dhall.defaultEvaluateSettings+-- >    in Dhall.inputFileWithSettings evaluateSettings resultDecoder "example.dhall"+--+-- Substitutions are a simple 'Dhall.Map.Map' mapping variables to expressions. The application of these substitutions reflect the order of the insertions in the substitution map:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > substitute (Dhall.Core.Var "Foo") (Dhall.Map.fromList [("Foo", Dhall.Core.Var "Bar"), ("Bar", Dhall.Core.BoolLit True)])+--+-- results in @Dhall.Core.Var \"Baz\"@ since we first substitute \"Foo\" with \"Bar\" and then the resulting \"Bar\" with the final @True@.+--+-- Notable differences to the other extensions of the builtin language:+--+--  * This approach works well with the inputFile/inputFileWithSettings functions while the let-wrapping will not.+--+--  * In contrast to the custom built-ins described above substitutions are made BEFORE the type-checking.++-- $prelude+--+-- There is also a Prelude available at:+--+-- <https://prelude.dhall-lang.org>+--+-- If you visit the above link you can browse the Prelude, which has a few+-- subdirectories.  For example, the @Bool@ subdirectory has a @not@ file, which+-- you can reference using this URL:+--+-- <https://prelude.dhall-lang.org/Bool/not>+--+-- The @not@ function is just a UTF8-encoded text file hosted online with the+-- following contents+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/Bool/not as Text'+-- > ''+-- > {-+-- > Flip the value of a Bool+-- > -}+-- > let not : Bool → Bool = λ(b : Bool) → b == False+-- >+-- > let example0 = assert : not True ≡ False+-- >+-- > let example1 = assert : not False ≡ True+-- >+-- > in  not+-- > ''+--+-- The file could have been much shorter, like this:+--+-- > λ(b : Bool) → b == False+--+-- ... but all the functions exported from the Prelude try to be as+-- self-documenting as possible by including:+--+-- * the name of the function+-- * the type of the function+-- * documentation+-- * tests+--+-- The performance penalty for adding these helpful features is negligible,+-- especially if you protect the import with a semantic integrity check because+-- then the import would be cached compactly as @λ(_ : Bool) → _ == False@.+--+-- You can use this @not@ function either directly:+--+-- > $ dhall+-- > https://prelude.dhall-lang.org/Bool/not True+-- > <Ctrl-D>+-- > False+--+-- ... or assign the URL to a shorter name:+--+-- > $ dhall+-- > let Bool/not = https://prelude.dhall-lang.org/Bool/not+-- > in  Bool/not True+-- > <Ctrl-D>+-- > False+--+-- Some functions in the Prelude just re-export built-in functions for+-- consistency and documentation, such as @Prelude\/Natural\/even@, which+-- re-exports the built-in @Natural/even@ function:+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/Natural/even as Text'+-- > ''+-- > {-+-- > Returns `True` if a number if even and returns `False` otherwise+-- > -}+-- > let even : Natural → Bool = Natural/even+-- >+-- > let example0 = assert : even 3 ≡ False+-- >+-- > let example1 = assert : even 0 ≡ True+-- >+-- > in  even+-- > ''+--+-- You can also clone the Prelude locally to your filesystem if you prefer+-- using `git clone`, like this:+--+-- > $ git clone https://github.com/dhall-lang/dhall-lang.git+-- > $ tree dhall-lang/Prelude+-- > dhall-lang/Prelude+-- > ├── Bool+-- > │   ├── and+-- > │   ├── build+-- > │   ├── even+-- > │   ├── fold+-- > │   ├── not+-- > │   ├── odd+-- > │   ├── or+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── Double+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── Function+-- > │   ├── compose+-- > │   └── package.dhall+-- > ├── Integer+-- > │   ├── package.dhall+-- > │   ├── show+-- > │   └── toDouble+-- > ├── JSON+-- > │   ├── Nesting+-- > │   ├── Tagged+-- > │   ├── Type+-- > │   ├── array+-- > │   ├── bool+-- > │   ├── keyText+-- > │   ├── keyValue+-- > │   ├── null+-- > │   ├── number+-- > │   ├── object+-- > │   ├── package.dhall+-- > │   ├── render+-- > │   └── string+-- > ├── List+-- > │   ├── all+-- > │   ├── any+-- > │   ├── build+-- > │   ├── concat+-- > │   ├── concatMap+-- > │   ├── default+-- > │   ├── empty+-- > │   ├── filter+-- > │   ├── fold+-- > │   ├── generate+-- > │   ├── head+-- > │   ├── indexed+-- > │   ├── iterate+-- > │   ├── last+-- > │   ├── length+-- > │   ├── map+-- > │   ├── null+-- > │   ├── package.dhall+-- > │   ├── replicate+-- > │   ├── reverse+-- > │   ├── shifted+-- > │   └── unzip+-- > ├── Location+-- > │   ├── Type+-- > │   └── package.dhall+-- > ├── Map+-- > │   ├── Entry+-- > │   ├── Type+-- > │   ├── empty+-- > │   ├── keyText+-- > │   ├── keyValue+-- > │   ├── keys+-- > │   ├── map+-- > │   ├── package.dhall+-- > │   └── values+-- > ├── Monoid+-- > ├── Natural+-- > │   ├── build+-- > │   ├── enumerate+-- > │   ├── equal+-- > │   ├── even+-- > │   ├── fold+-- > │   ├── greaterThan+-- > │   ├── greaterThanEqual+-- > │   ├── isZero+-- > │   ├── lessThan+-- > │   ├── lessThanEqual+-- > │   ├── odd+-- > │   ├── package.dhall+-- > │   ├── product+-- > │   ├── show+-- > │   ├── subtract+-- > │   ├── sum+-- > │   ├── toDouble+-- > │   └── toInteger+-- > ├── Optional+-- > │   ├── all+-- > │   ├── any+-- > │   ├── build+-- > │   ├── concat+-- > │   ├── default+-- > │   ├── filter+-- > │   ├── fold+-- > │   ├── head+-- > │   ├── last+-- > │   ├── length+-- > │   ├── map+-- > │   ├── null+-- > │   ├── package.dhall+-- > │   ├── toList+-- > │   └── unzip+-- > ├── Text+-- > │   ├── concat+-- > │   ├── concatMap+-- > │   ├── concatMapSep+-- > │   ├── concatSep+-- > │   ├── default+-- > │   ├── defaultMap+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── XML+-- > │   ├── Type+-- > │   ├── attribute+-- > │   ├── element+-- > │   ├── emptyAttributes+-- > │   ├── leaf+-- > │   ├── package.dhall+-- > │   ├── render+-- > │   └── text+-- > └── package.dhall+--+-- Browse the Prelude online to learn more by seeing what functions are+-- available and reading their inline documentation:+--+-- <https://prelude.dhall-lang.org>+--+-- __Exercise__: Try to use a new Prelude function that has not been covered+-- previously in this tutorial+--+-- You can also import the entire Prelude as a single large record for+-- convenience:+--+-- > $ dhall+-- > let Prelude = https://prelude.dhall-lang.org/package.dhall+-- >+-- > in  \(x : Text) ->+-- >       Prelude.List.length Text (Prelude.List.replicate 10 Text x)+-- > <Ctrl-D>+-- > ∀(x : Text) → Natural+-- >+-- > λ(x : Text) → 10+--+-- The organization of the package mirrors the layout of the Prelude, meaning+-- that every directory is stored as a record whose children are the fields of+-- that record.+--+-- __Exercise__: Browse the Prelude by running:+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/package.dhall'++-- $limitations+-- #limitations#+--+-- `FromDhall` has a limitiation: It won't work for recursive types.+-- If you instantiate these using their Generic instance you end up with one of+-- the following two cases:+--+-- If the type appears in it's own definition like+--+-- > data Foo = Foo Foo+-- >     deriving Generic+-- >+-- > instance FromDhall Foo+--+-- the resulting Decoder will throw an exception /ON USAGE/.+-- However, if the recursion is indirect like+--+-- > data Foo = Foo Bar+-- >     deriving Generic+-- >+-- > instance FromDhall Foo+-- >+-- > data Bar = Bar Foo+-- >     deriving Generic+-- >+-- > instance FromDhall Bar+--+-- the resulting Decoder will __NOT TERMINATE__ /ON USAGE/.++-- $conclusion+--+-- By this point you should be able to use the Dhall configuration language to+-- author, import, and program configuration files.  If you run into any issues+-- you can report them at:+--+-- <https://github.com/dhall-lang/dhall-haskell/issues>+--+-- Also, you might want to check out the+-- <https://docs.dhall-lang.org/tutorials/Language-Tour.html Language Tour>, a+-- more comprehensive tour of Dhall which may cover features missing from this+-- Haskell tutorial.+--+-- You can also request features, support, or documentation improvements on the+-- above issue tracker.+--+-- If you would like to contribute to the Dhall project you can try to port+-- Dhall to languages that do not yet have Dhall integrations so that Dhall configuration files+-- can be read into those languages, too.++-- $faq+--+-- <https://docs.dhall-lang.org/howtos/FAQ.html>
src/Dhall/TypeCheck.hs view
@@ -1,3155 +1,4851 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RankNTypes         #-}-{-# LANGUAGE RecordWildCards    #-}-{-# OPTIONS_GHC -Wall #-}---- | This module contains the logic for type checking Dhall code--module Dhall.TypeCheck (-    -- * Type-checking-      typeWith-    , typeOf-    , typeWithA-    , checkContext--    -- * Types-    , Typer-    , X(..)-    , TypeError(..)-    , DetailedTypeError(..)-    , TypeMessage(..)-    ) where--import Control.Exception (Exception)-import Data.Foldable (forM_, toList)-import Data.Monoid ((<>))-import Data.Sequence (Seq, ViewL(..))-import Data.Set (Set)-import Data.Text.Buildable (Buildable(..))-import Data.Text.Lazy (Text)-import Data.Text.Lazy.Builder (Builder)-import Data.Text.Prettyprint.Doc (Pretty(..))-import Data.Traversable (forM)-import Data.Typeable (Typeable)-import Dhall.Core (Const(..), Chunks(..), Expr(..), Var(..))-import Dhall.Context (Context)--import qualified Data.Foldable-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text.Lazy                   as Text-import qualified Data.Text.Lazy.Builder           as Builder-import qualified Dhall.Context-import qualified Dhall.Core--traverseWithIndex_ :: Applicative f => (Int -> a -> f b) -> Seq a -> f ()-traverseWithIndex_ k xs =-    Data.Foldable.sequenceA_ (Data.Sequence.mapWithIndex k xs)--axiom :: Const -> Either (TypeError s a) Const-axiom Type = return Kind-axiom Kind = Left (TypeError Dhall.Context.empty (Const Kind) Untyped)--rule :: Const -> Const -> Either () Const-rule Type Kind = Left ()-rule Type Type = return Type-rule Kind Kind = return Kind-rule Kind Type = return Type--{-| Type-check an expression and return the expression's type if type-checking-    succeeds or an error if type-checking fails--    `typeWith` does not necessarily normalize the type since full normalization-    is not necessary for just type-checking.  If you actually care about the-    returned type then you may want to `Dhall.Core.normalize` it afterwards.--}-typeWith :: Context (Expr s X) -> Expr s X -> Either (TypeError s X) (Expr s X)-typeWith ctx expr = do-    checkContext ctx-    typeWithA absurd ctx expr--{-| Function that converts the value inside an `Embed` constructor into a new-    expression--}-type Typer a = forall s. a -> Expr s a--{-| Generalization of `typeWith` that allows type-checking the `Embed`-    constructor with custom logic--}-typeWithA-    :: Eq a-    => Typer a-    -> Context (Expr s a)-    -> Expr s a-    -> Either (TypeError s a) (Expr s a)-typeWithA tpa = loop-  where-    loop _     (Const c         ) = do-        fmap Const (axiom c)-    loop ctx e@(Var (V x n)     ) = do-        case Dhall.Context.lookup x n ctx of-            Nothing -> Left (TypeError ctx e (UnboundVariable x))-            Just a  -> do-                _ <- loop ctx a-                return a-    loop ctx   (Lam x _A  b     ) = do-        _ <- loop ctx _A-        let ctx' = fmap (Dhall.Core.shift 1 (V x 0)) (Dhall.Context.insert x (Dhall.Core.normalize _A) ctx)-        _B <- loop ctx' b-        let p = Pi x _A _B-        _t <- loop ctx p-        return p-    loop ctx e@(Pi  x _A _B     ) = do-        tA <- fmap Dhall.Core.normalize (loop ctx _A)-        kA <- case tA of-            Const k -> return k-            _       -> Left (TypeError ctx e (InvalidInputType _A))--        _ <- loop ctx _A-        let ctx' = fmap (Dhall.Core.shift 1 (V x 0)) (Dhall.Context.insert x (Dhall.Core.normalize _A) ctx)-        tB <- fmap Dhall.Core.normalize (loop ctx' _B)-        kB <- case tB of-            Const k -> return k-            _       -> Left (TypeError ctx' e (InvalidOutputType _B))--        case rule kA kB of-            Left () -> Left (TypeError ctx e (NoDependentTypes _A _B))-            Right k -> Right (Const k)-    loop ctx e@(App f a         ) = do-        tf <- fmap Dhall.Core.normalize (loop ctx f)-        (x, _A, _B) <- case tf of-            Pi x _A _B -> return (x, _A, _B)-            _          -> Left (TypeError ctx e (NotAFunction f tf))-        _A' <- loop ctx a-        if Dhall.Core.judgmentallyEqual _A _A'-            then do-                let a'   = Dhall.Core.shift   1  (V x 0) a-                let _B'  = Dhall.Core.subst (V x 0) a' _B-                let _B'' = Dhall.Core.shift (-1) (V x 0) _B'-                return _B''-            else do-                let nf_A  = Dhall.Core.normalize _A-                let nf_A' = Dhall.Core.normalize _A'-                Left (TypeError ctx e (TypeMismatch f nf_A a nf_A'))-    loop ctx e@(Let x mA a0 b0) = do-        _A1 <- loop ctx a0-        case mA of-            Just _A0 -> do-                _ <- loop ctx _A0-                let nf_A0 = Dhall.Core.normalize _A0-                let nf_A1 = Dhall.Core.normalize _A1-                if Dhall.Core.judgmentallyEqual _A0 _A1-                    then return ()-                    else Left (TypeError ctx e (AnnotMismatch a0 nf_A0 nf_A1))-            Nothing -> return ()-        let a1 = Dhall.Core.normalize a0-        let a2 = Dhall.Core.shift 1 (V x 0) a1-        let b1 = Dhall.Core.subst (V x 0) a2 b0-        let b2 = Dhall.Core.shift (-1) (V x 0) b1-        loop ctx b2-    loop ctx e@(Annot x t       ) = do-        _ <- loop ctx t--        t' <- loop ctx x-        if Dhall.Core.judgmentallyEqual t t'-            then do-                return t-            else do-                let nf_t  = Dhall.Core.normalize t-                let nf_t' = Dhall.Core.normalize t'-                Left (TypeError ctx e (AnnotMismatch x nf_t nf_t'))-    loop _      Bool              = do-        return (Const Type)-    loop _     (BoolLit _       ) = do-        return Bool-    loop ctx e@(BoolAnd l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantAnd l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantAnd r tr))--        return Bool-    loop ctx e@(BoolOr  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantOr l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantOr r tr))--        return Bool-    loop ctx e@(BoolEQ  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantEQ l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantEQ r tr))--        return Bool-    loop ctx e@(BoolNE  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantNE l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantNE r tr))--        return Bool-    loop ctx e@(BoolIf x y z    ) = do-        tx <- fmap Dhall.Core.normalize (loop ctx x)-        case tx of-            Bool -> return ()-            _    -> Left (TypeError ctx e (InvalidPredicate x tx))-        ty  <- fmap Dhall.Core.normalize (loop ctx y )-        tty <- fmap Dhall.Core.normalize (loop ctx ty)-        case tty of-            Const Type -> return ()-            _          -> Left (TypeError ctx e (IfBranchMustBeTerm True y ty tty))--        tz <- fmap Dhall.Core.normalize (loop ctx z)-        ttz <- fmap Dhall.Core.normalize (loop ctx tz)-        case ttz of-            Const Type -> return ()-            _          -> Left (TypeError ctx e (IfBranchMustBeTerm False z tz ttz))--        if Dhall.Core.judgmentallyEqual ty tz-            then return ()-            else Left (TypeError ctx e (IfBranchMismatch y z ty tz))-        return ty-    loop _      Natural           = do-        return (Const Type)-    loop _     (NaturalLit _    ) = do-        return Natural-    loop _      NaturalFold       = do-        return-            (Pi "_" Natural-                (Pi "natural" (Const Type)-                    (Pi "succ" (Pi "_" "natural" "natural")-                        (Pi "zero" "natural" "natural") ) ) )-    loop _      NaturalBuild      = do-        return-            (Pi "_"-                (Pi "natural" (Const Type)-                    (Pi "succ" (Pi "_" "natural" "natural")-                        (Pi "zero" "natural" "natural") ) )-                Natural )-    loop _      NaturalIsZero     = do-        return (Pi "_" Natural Bool)-    loop _      NaturalEven       = do-        return (Pi "_" Natural Bool)-    loop _      NaturalOdd        = do-        return (Pi "_" Natural Bool)-    loop _      NaturalToInteger  = do-        return (Pi "_" Natural Integer)-    loop _      NaturalShow  = do-        return (Pi "_" Natural Text)-    loop ctx e@(NaturalPlus  l r) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantAdd l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantAdd r tr))-        return Natural-    loop ctx e@(NaturalTimes l r) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantMultiply l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantMultiply r tr))-        return Natural-    loop _      Integer           = do-        return (Const Type)-    loop _     (IntegerLit _    ) = do-        return Integer-    loop _      IntegerShow  = do-        return (Pi "_" Integer Text)-    loop _      Double            = do-        return (Const Type)-    loop _     (DoubleLit _     ) = do-        return Double-    loop _     DoubleShow         = do-        return (Pi "_" Double Text)-    loop _      Text              = do-        return (Const Type)-    loop ctx e@(TextLit (Chunks xys _)) = do-        let process (_, y) = do-                ty <- fmap Dhall.Core.normalize (loop ctx y)-                case ty of-                    Text -> return ()-                    _    -> Left (TypeError ctx e (CantInterpolate y ty))-        mapM_ process xys-        return Text-    loop ctx e@(TextAppend l r  ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Text -> return ()-            _    -> Left (TypeError ctx e (CantTextAppend l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Text -> return ()-            _    -> Left (TypeError ctx e (CantTextAppend r tr))-        return Text-    loop _      List              = do-        return (Pi "_" (Const Type) (Const Type))-    loop ctx e@(ListLit  Nothing  xs) = do-        case Data.Sequence.viewl xs of-            x0 :< _ -> do-                t <- loop ctx x0-                s <- fmap Dhall.Core.normalize (loop ctx t)-                case s of-                    Const Type -> return ()-                    _ -> Left (TypeError ctx e (InvalidListType t))-                flip traverseWithIndex_ xs (\i x -> do-                    t' <- loop ctx x-                    if Dhall.Core.judgmentallyEqual t t'-                        then return ()-                        else do-                            let nf_t  = Dhall.Core.normalize t-                            let nf_t' = Dhall.Core.normalize t'-                            let err   = MismatchedListElements i nf_t x nf_t'-                            Left (TypeError ctx x err) )-                return (App List t)-            _ -> Left (TypeError ctx e MissingListType)-    loop ctx e@(ListLit (Just t ) xs) = do-        s <- fmap Dhall.Core.normalize (loop ctx t)-        case s of-            Const Type -> return ()-            _ -> Left (TypeError ctx e (InvalidListType t))-        flip traverseWithIndex_ xs (\i x -> do-            t' <- loop ctx x-            if Dhall.Core.judgmentallyEqual t t'-                then return ()-                else do-                    let nf_t  = Dhall.Core.normalize t-                    let nf_t' = Dhall.Core.normalize t'-                    Left (TypeError ctx x (InvalidListElement i nf_t x nf_t')) )-        return (App List t)-    loop ctx e@(ListAppend l r  ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        el <- case tl of-            App List el -> return el-            _           -> Left (TypeError ctx e (CantListAppend l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        er <- case tr of-            App List er -> return er-            _           -> Left (TypeError ctx e (CantListAppend r tr))--        if Dhall.Core.judgmentallyEqual el er-            then return (App List el)-            else Left (TypeError ctx e (ListAppendMismatch el er))-    loop _      ListBuild         = do-        return-            (Pi "a" (Const Type)-                (Pi "_"-                    (Pi "list" (Const Type)-                        (Pi "cons" (Pi "_" "a" (Pi "_" "list" "list"))-                            (Pi "nil" "list" "list") ) )-                    (App List "a") ) )-    loop _      ListFold          = do-        return-            (Pi "a" (Const Type)-                (Pi "_" (App List "a")-                    (Pi "list" (Const Type)-                        (Pi "cons" (Pi "_" "a" (Pi "_" "list" "list"))-                            (Pi "nil" "list" "list")) ) ) )-    loop _      ListLength        = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") Natural))-    loop _      ListHead          = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App Optional "a")))-    loop _      ListLast          = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App Optional "a")))-    loop _      ListIndexed       = do-        let kts = [("index", Natural), ("value", "a")]-        return-            (Pi "a" (Const Type)-                (Pi "_" (App List "a")-                    (App List (Record (Data.HashMap.Strict.InsOrd.fromList kts))) ) )-    loop _      ListReverse       = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App List "a")))-    loop _      Optional          = do-        return (Pi "_" (Const Type) (Const Type))-    loop ctx e@(OptionalLit t xs) = do-        s <- fmap Dhall.Core.normalize (loop ctx t)-        case s of-            Const Type -> return ()-            _ -> Left (TypeError ctx e (InvalidOptionalType t))-        forM_ xs (\x -> do-            t' <- loop ctx x-            if Dhall.Core.judgmentallyEqual t t'-                then return ()-                else do-                    let nf_t  = Dhall.Core.normalize t-                    let nf_t' = Dhall.Core.normalize t'-                    Left (TypeError ctx e (InvalidOptionalElement nf_t x nf_t')) )-        return (App Optional t)-    loop _      OptionalFold      = do-        return-            (Pi "a" (Const Type)-                (Pi "_" (App Optional "a")-                    (Pi "optional" (Const Type)-                        (Pi "just" (Pi "_" "a" "optional")-                            (Pi "nothing" "optional" "optional") ) ) ) )-    loop _      OptionalBuild     = do-        return-            (Pi "a" (Const Type)-                (Pi "_" f (App Optional "a") ) )-        where f = Pi "optional" (Const Type)-                      (Pi "just" (Pi "_" "a" "optional")-                          (Pi "nothing" "optional" "optional") )-    loop ctx e@(Record    kts   ) = do-        let process (k, t) = do-                s <- fmap Dhall.Core.normalize (loop ctx t)-                case s of-                    Const Type -> return ()-                    Const Kind -> return ()-                    _          -> Left (TypeError ctx e (InvalidFieldType k t))-        mapM_ process (Data.HashMap.Strict.InsOrd.toList kts)-        return (Const Type)-    loop ctx e@(RecordLit kvs   ) = do-        let process k v = do-                t <- loop ctx v-                s <- fmap Dhall.Core.normalize (loop ctx t)-                case s of-                    Const Type -> return ()-                    Const Kind -> return ()-                    _          -> Left (TypeError ctx e (InvalidField k v))-                return t-        kts <- Data.HashMap.Strict.InsOrd.traverseWithKey process kvs-        return (Record kts)-    loop ctx e@(Union     kts   ) = do-        let process (k, t) = do-                s <- fmap Dhall.Core.normalize (loop ctx t)-                case s of-                    Const Type -> return ()-                    Const Kind -> return ()-                    _          -> Left (TypeError ctx e (InvalidAlternativeType k t))-        mapM_ process (Data.HashMap.Strict.InsOrd.toList kts)-        return (Const Type)-    loop ctx e@(UnionLit k v kts) = do-        case Data.HashMap.Strict.InsOrd.lookup k kts of-            Just _  -> Left (TypeError ctx e (DuplicateAlternative k))-            Nothing -> return ()-        t <- loop ctx v-        let union = Union (Data.HashMap.Strict.InsOrd.insert k (Dhall.Core.normalize t) kts)-        _ <- loop ctx union-        return union-    loop ctx e@(Combine kvsX kvsY) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '∧' kvsX tKvsX))--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '∧' kvsY tKvsY))--        let combineTypes ktsL ktsR = do-                let ksL =-                        Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsL)-                let ksR =-                        Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsR)-                let ks = Data.Set.union ksL ksR-                kts <- forM (toList ks) (\k -> do-                    case (Data.HashMap.Strict.InsOrd.lookup k ktsL, Data.HashMap.Strict.InsOrd.lookup k ktsR) of-                        (Just (Record ktsL'), Just (Record ktsR')) -> do-                            t <- combineTypes ktsL' ktsR'-                            return (k, t)-                        (Nothing, Just t) -> do-                            return (k, t)-                        (Just t, Nothing) -> do-                            return (k, t)-                        _ -> do-                            Left (TypeError ctx e (FieldCollision k)) )-                return (Record (Data.HashMap.Strict.InsOrd.fromList kts))--        combineTypes ktsX ktsY-    loop ctx e@(Prefer kvsX kvsY) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsX tKvsX))--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsY tKvsY))-        return (Record (Data.HashMap.Strict.InsOrd.union ktsY ktsX))-    loop ctx e@(Merge kvsX kvsY (Just t)) = do-        _ <- loop ctx t--        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX))-        let ksX = Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsX)--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Union kts -> return kts-            _         -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY))-        let ksY = Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsY)--        let diffX = Data.Set.difference ksX ksY-        let diffY = Data.Set.difference ksY ksX--        if Data.Set.null diffX-            then return ()-            else Left (TypeError ctx e (UnusedHandler diffX))--        let process (kY, tY) = do-                case Data.HashMap.Strict.InsOrd.lookup kY ktsX of-                    Nothing  -> Left (TypeError ctx e (MissingHandler diffY))-                    Just tX  ->-                        case tX of-                            Pi _ tY' t' -> do-                                if Dhall.Core.judgmentallyEqual tY tY'-                                    then return ()-                                    else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY'))-                                if Dhall.Core.judgmentallyEqual t t'-                                    then return ()-                                    else Left (TypeError ctx e (InvalidHandlerOutputType kY t t'))-                            _ -> Left (TypeError ctx e (HandlerNotAFunction kY tX))-        mapM_ process (Data.HashMap.Strict.InsOrd.toList ktsY)-        return t-    loop ctx e@(Merge kvsX kvsY Nothing) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX))-        let ksX = Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsX)--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Union kts -> return kts-            _         -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY))-        let ksY = Data.Set.fromList (Data.HashMap.Strict.InsOrd.keys ktsY)--        let diffX = Data.Set.difference ksX ksY-        let diffY = Data.Set.difference ksY ksX--        if Data.Set.null diffX-            then return ()-            else Left (TypeError ctx e (UnusedHandler diffX))--        (kX, t) <- case Data.HashMap.Strict.InsOrd.toList ktsX of-            []               -> Left (TypeError ctx e MissingMergeType)-            (kX, Pi _ _ t):_ -> return (kX, t)-            (kX, tX      ):_ -> Left (TypeError ctx e (HandlerNotAFunction kX tX))-        let process (kY, tY) = do-                case Data.HashMap.Strict.InsOrd.lookup kY ktsX of-                    Nothing  -> Left (TypeError ctx e (MissingHandler diffY))-                    Just tX  ->-                        case tX of-                            Pi _ tY' t' -> do-                                if Dhall.Core.judgmentallyEqual tY tY'-                                    then return ()-                                    else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY'))-                                if Dhall.Core.judgmentallyEqual t t'-                                    then return ()-                                    else Left (TypeError ctx e (HandlerOutputTypeMismatch kX t kY t'))-                            _ -> Left (TypeError ctx e (HandlerNotAFunction kY tX))-        mapM_ process (Data.HashMap.Strict.InsOrd.toList ktsY)-        return t-    loop ctx e@(Constructors t  ) = do-        _ <- loop ctx t--        kts <- case Dhall.Core.normalize t of-            Union kts -> return kts-            t'        -> Left (TypeError ctx e (ConstructorsRequiresAUnionType t t'))--        let adapt k t_ = Pi k t_ (Union kts)--        return (Record (Data.HashMap.Strict.InsOrd.mapWithKey adapt kts))-    loop ctx e@(Field r x       ) = do-        t <- fmap Dhall.Core.normalize (loop ctx r)-        case t of-            Record kts -> do-                _ <- loop ctx t--                case Data.HashMap.Strict.InsOrd.lookup x kts of-                    Just t' -> return t'-                    Nothing -> Left (TypeError ctx e (MissingField x t))-            _          -> Left (TypeError ctx e (NotARecord x r t))-    loop ctx   (Note s e'       ) = case loop ctx e' of-        Left (TypeError ctx' (Note s' e'') m) -> Left (TypeError ctx' (Note s' e'') m)-        Left (TypeError ctx'          e''  m) -> Left (TypeError ctx' (Note s  e'') m)-        Right r                               -> Right r-    loop _     (Embed p         ) = Right $ tpa p--{-| `typeOf` is the same as `typeWith` with an empty context, meaning that the-    expression must be closed (i.e. no free variables), otherwise type-checking-    will fail.--}-typeOf :: Expr s X -> Either (TypeError s X) (Expr s X)-typeOf = typeWith Dhall.Context.empty---- | Like `Data.Void.Void`, except with a shorter inferred type-newtype X = X { absurd :: forall a . a }--instance Show X where-    show = absurd--instance Eq X where-  _ == _ = True--instance Buildable X where-    build = absurd--instance Pretty X where-    pretty = absurd---- | The specific type error-data TypeMessage s a-    = UnboundVariable Text-    | InvalidInputType (Expr s a)-    | InvalidOutputType (Expr s a)-    | NotAFunction (Expr s a) (Expr s a)-    | TypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)-    | AnnotMismatch (Expr s a) (Expr s a) (Expr s a)-    | Untyped-    | MissingListType-    | MismatchedListElements Int (Expr s a) (Expr s a) (Expr s a)-    | InvalidListElement Int (Expr s a) (Expr s a) (Expr s a)-    | InvalidListType (Expr s a)-    | InvalidOptionalElement (Expr s a) (Expr s a) (Expr s a)-    | InvalidOptionalType (Expr s a)-    | InvalidPredicate (Expr s a) (Expr s a)-    | IfBranchMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)-    | IfBranchMustBeTerm Bool (Expr s a) (Expr s a) (Expr s a)-    | InvalidField Text (Expr s a)-    | InvalidFieldType Text (Expr s a)-    | InvalidAlternative Text (Expr s a)-    | InvalidAlternativeType Text (Expr s a)-    | ListAppendMismatch (Expr s a) (Expr s a)-    | DuplicateAlternative Text-    | MustCombineARecord Char (Expr s a) (Expr s a)-    | FieldCollision Text-    | MustMergeARecord (Expr s a) (Expr s a)-    | MustMergeUnion (Expr s a) (Expr s a)-    | UnusedHandler (Set Text)-    | MissingHandler (Set Text)-    | HandlerInputTypeMismatch Text (Expr s a) (Expr s a)-    | HandlerOutputTypeMismatch Text (Expr s a) Text (Expr s a)-    | InvalidHandlerOutputType Text (Expr s a) (Expr s a)-    | MissingMergeType-    | HandlerNotAFunction Text (Expr s a)-    | ConstructorsRequiresAUnionType (Expr s a) (Expr s a)-    | NotARecord Text (Expr s a) (Expr s a)-    | MissingField Text (Expr s a)-    | CantAnd (Expr s a) (Expr s a)-    | CantOr (Expr s a) (Expr s a)-    | CantEQ (Expr s a) (Expr s a)-    | CantNE (Expr s a) (Expr s a)-    | CantInterpolate (Expr s a) (Expr s a)-    | CantTextAppend (Expr s a) (Expr s a)-    | CantListAppend (Expr s a) (Expr s a)-    | CantAdd (Expr s a) (Expr s a)-    | CantMultiply (Expr s a) (Expr s a)-    | NoDependentTypes (Expr s a) (Expr s a)-    deriving (Show)--shortTypeMessage :: Buildable a => TypeMessage s a -> Builder-shortTypeMessage msg =-    "\ESC[1;31mError\ESC[0m: " <> build short <> "\n"-  where-    ErrorMessages {..} = prettyTypeMessage msg--longTypeMessage :: Buildable a => TypeMessage s a -> Builder-longTypeMessage msg =-        "\ESC[1;31mError\ESC[0m: " <> build short <> "\n"-    <>  "\n"-    <>  long-  where-    ErrorMessages {..} = prettyTypeMessage msg--data ErrorMessages = ErrorMessages-    { short :: Builder-    -- ^ Default succinct 1-line explanation of what went wrong-    , long  :: Builder-    -- ^ Longer and more detailed explanation of the error-    }--_NOT :: Builder-_NOT = "\ESC[1mnot\ESC[0m"--prettyTypeMessage :: Buildable a => TypeMessage s a -> ErrorMessages-prettyTypeMessage (UnboundVariable _) = ErrorMessages {..}-  -- We do not need to print variable name here. For the discussion see:-  -- https://github.com/dhall-lang/dhall-haskell/pull/116-  where-    short = "Unbound variable"--    long =-        "Explanation: Expressions can only reference previously introduced (i.e. \"bound\")\n\-        \variables that are still \"in scope\"                                           \n\-        \                                                                                \n\-        \For example, the following valid expressions introduce a \"bound\" variable named\n\-        \❰x❱:                                                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ λ(x : Bool) → x │  Anonymous functions introduce \"bound\" variables      \n\-        \    └─────────────────┘                                                         \n\-        \        ⇧                                                                       \n\-        \        This is the bound variable                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ let x = 1 in x  │  ❰let❱ expressions introduce \"bound\" variables        \n\-        \    └─────────────────┘                                                         \n\-        \          ⇧                                                                     \n\-        \          This is the bound variable                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, the following expressions are not valid because they all reference a   \n\-        \variable that has not been introduced yet (i.e. an \"unbound\" variable):       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ λ(x : Bool) → y │  The variable ❰y❱ hasn't been introduced yet            \n\-        \    └─────────────────┘                                                         \n\-        \                    ⇧                                                           \n\-        \                    This is the unbound variable                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────┐                                                \n\-        \    │ (let x = True in x) && x │  ❰x❱ is undefined outside the parentheses      \n\-        \    └──────────────────────────┘                                                \n\-        \                             ⇧                                                  \n\-        \                             This is the unbound variable                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ let x = x in x │  The definition for ❰x❱ cannot reference itself          \n\-        \    └────────────────┘                                                          \n\-        \              ⇧                                                                 \n\-        \              This is the unbound variable                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You misspell a variable name, like this:                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────────────────┐                      \n\-        \    │ λ(empty : Bool) → if emty then \"Empty\" else \"Full\" │                  \n\-        \    └────────────────────────────────────────────────────┘                      \n\-        \                           ⇧                                                    \n\-        \                           Typo                                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You misspell a reserved identifier, like this:                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────┐                                                \n\-        \    │ foral (a : Type) → a → a │                                                \n\-        \    └──────────────────────────┘                                                \n\-        \      ⇧                                                                         \n\-        \      Typo                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You tried to define a recursive value, like this:                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────┐                                                     \n\-        \    │ let x = x + +1 in x │                                                     \n\-        \    └─────────────────────┘                                                     \n\-        \              ⇧                                                                 \n\-        \              Recursive definitions are not allowed                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You accidentally forgot a ❰λ❱ or ❰∀❱/❰forall❱                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \        Unbound variable                                                        \n\-        \        ⇩                                                                       \n\-        \    ┌─────────────────┐                                                         \n\-        \    │  (x : Bool) → x │                                                         \n\-        \    └─────────────────┘                                                         \n\-        \      ⇧                                                                         \n\-        \      A ❰λ❱ here would transform this into a valid anonymous function           \n\-        \                                                                                \n\-        \                                                                                \n\-        \        Unbound variable                                                        \n\-        \        ⇩                                                                       \n\-        \    ┌────────────────────┐                                                      \n\-        \    │  (x : Bool) → Bool │                                                      \n\-        \    └────────────────────┘                                                      \n\-        \      ⇧                                                                         \n\-        \      A ❰∀❱ or ❰forall❱ here would transform this into a valid function type    \n"--prettyTypeMessage (InvalidInputType expr) = ErrorMessages {..}-  where-    short = "Invalid function input"--    long =-        "Explanation: A function can accept an input \"term\" that has a given \"type\", like\n\-        \this:                                                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \        This is the input term that the function accepts                        \n\-        \        ⇩                                                                       \n\-        \    ┌───────────────────────┐                                                   \n\-        \    │ ∀(x : Natural) → Bool │  This is the type of a function that accepts an   \n\-        \    └───────────────────────┘  input term named ❰x❱ that has type ❰Natural❱     \n\-        \            ⇧                                                                   \n\-        \            This is the type of the input term                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ Bool → Integer │  This is the type of a function that accepts an anonymous\n\-        \    └────────────────┘  input term that has type ❰Bool❱                         \n\-        \      ⇧                                                                         \n\-        \      This is the type of the input term                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \... or a function can accept an input \"type\" that has a given \"kind\", like this:\n\-        \                                                                                \n\-        \                                                                                \n\-        \        This is the input type that the function accepts                        \n\-        \        ⇩                                                                       \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ ∀(a : Type) → Type │  This is the type of a function that accepts an input\n\-        \    └────────────────────┘  type named ❰a❱ that has kind ❰Type❱                 \n\-        \            ⇧                                                                   \n\-        \            This is the kind of the input type                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────┐                                                    \n\-        \    │ (Type → Type) → Type │  This is the type of a function that accepts an    \n\-        \    └──────────────────────┘  anonymous input type that has kind ❰Type → Type❱  \n\-        \       ⇧                                                                        \n\-        \       This is the kind of the input type                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \Other function inputs are " <> _NOT <> " valid, like this:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────┐                                                            \n\-        \    │ ∀(x : 1) → x │  ❰1❱ is a \"term\" and not a \"type\" nor a \"kind\" so ❰x❱\n\-        \    └──────────────┘  cannot have \"type\" ❰1❱ or \"kind\" ❰1❱                  \n\-        \            ⇧                                                                   \n\-        \            This is not a type or kind                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────┐                                                                \n\-        \    │ True → x │  ❰True❱ is a \"term\" and not a \"type\" nor a \"kind\" so the \n\-        \    └──────────┘  anonymous input cannot have \"type\" ❰True❱ or \"kind\" ❰True❱\n\-        \      ⇧                                                                         \n\-        \      This is not a type or kind                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \You annotated a function input with the following expression:                   \n\-        \                                                                                \n\-        \↳ " <> txt <> "                                                                 \n\-        \                                                                                \n\-        \... which is neither a type nor a kind                                          \n"-      where-        txt  = build expr--prettyTypeMessage (InvalidOutputType expr) = ErrorMessages {..}-  where-    short = "Invalid function output"--    long =-        "Explanation: A function can return an output \"term\" that has a given \"type\",\n\-        \like this:                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ ∀(x : Text) → Bool │  This is the type of a function that returns an      \n\-        \    └────────────────────┘  output term that has type ❰Bool❱                    \n\-        \                    ⇧                                                           \n\-        \                    This is the type of the output term                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ Bool → Integer │  This is the type of a function that returns an output   \n\-        \    └────────────────┘  term that has type ❰Int❱                                \n\-        \             ⇧                                                                  \n\-        \             This is the type of the output term                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \... or a function can return an output \"type\" that has a given \"kind\", like \n\-        \this:                                                                           \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ ∀(a : Type) → Type │  This is the type of a function that returns an      \n\-        \    └────────────────────┘  output type that has kind ❰Type❱                    \n\-        \                    ⇧                                                           \n\-        \                    This is the kind of the output type                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────┐                                                    \n\-        \    │ (Type → Type) → Type │  This is the type of a function that returns an    \n\-        \    └──────────────────────┘  output type that has kind ❰Type❱                  \n\-        \                      ⇧                                                         \n\-        \                      This is the kind of the output type                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \Other outputs are " <> _NOT <> " valid, like this:                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ ∀(x : Bool) → x │  ❰x❱ is a \"term\" and not a \"type\" nor a \"kind\" so the\n\-        \    └─────────────────┘  output cannot have \"type\" ❰x❱ or \"kind\" ❰x❱        \n\-        \                    ⇧                                                           \n\-        \                    This is not a type or kind                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ Text → True │  ❰True❱ is a \"term\" and not a \"type\" nor a \"kind\" so the\n\-        \    └─────────────┘  output cannot have \"type\" ❰True❱ or \"kind\" ❰True❱      \n\-        \             ⇧                                                                  \n\-        \             This is not a type or kind                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You use ❰∀❱ instead of ❰λ❱ by mistake, like this:                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ ∀(x: Bool) → x │                                                          \n\-        \    └────────────────┘                                                          \n\-        \      ⇧                                                                         \n\-        \      Using ❰λ❱ here instead of ❰∀❱ would transform this into a valid function  \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You specified that your function outputs a:                                     \n\-        \                                                                                \n\-        \↳ " <> txt <> "                                                                 \n\-        \                                                                                \n\-        \... which is neither a type nor a kind:                                         \n"-      where-        txt = build expr--prettyTypeMessage (NotAFunction expr0 expr1) = ErrorMessages {..}-  where-    short = "Not a function"--    long =-        "Explanation: Expressions separated by whitespace denote function application,   \n\-        \like this:                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────┐                                                                     \n\-        \    │ f x │  This denotes the function ❰f❱ applied to an argument named ❰x❱     \n\-        \    └─────┘                                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \A function is a term that has type ❰a → b❱ for some ❰a❱ or ❰b❱.  For example,   \n\-        \the following expressions are all functions because they have a function type:  \n\-        \                                                                                \n\-        \                                                                                \n\-        \                        The function's input type is ❰Bool❱                     \n\-        \                        ⇩                                                       \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ λ(x : Bool) → x : Bool → Bool │  User-defined anonymous function          \n\-        \    └───────────────────────────────┘                                           \n\-        \                               ⇧                                                \n\-        \                               The function's output type is ❰Bool❱             \n\-        \                                                                                \n\-        \                                                                                \n\-        \                     The function's input type is ❰Natural❱                     \n\-        \                     ⇩                                                          \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ Natural/even : Natural → Bool │  Built-in function                        \n\-        \    └───────────────────────────────┘                                           \n\-        \                               ⇧                                                \n\-        \                               The function's output type is ❰Bool❱             \n\-        \                                                                                \n\-        \                                                                                \n\-        \                        The function's input kind is ❰Type❱                     \n\-        \                        ⇩                                                       \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ λ(a : Type) → a : Type → Type │  Type-level functions are still functions \n\-        \    └───────────────────────────────┘                                           \n\-        \                               ⇧                                                \n\-        \                               The function's output kind is ❰Type❱             \n\-        \                                                                                \n\-        \                                                                                \n\-        \             The function's input kind is ❰Type❱                                \n\-        \             ⇩                                                                  \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ List : Type → Type │  Built-in type-level function                        \n\-        \    └────────────────────┘                                                      \n\-        \                    ⇧                                                           \n\-        \                    The function's output kind is ❰Type❱                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \                        Function's input has kind ❰Type❱                        \n\-        \                        ⇩                                                       \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │ List/head : ∀(a : Type) → (List a → Optional a) │  A function can return  \n\-        \    └─────────────────────────────────────────────────┘  another function       \n\-        \                                ⇧                                               \n\-        \                                Function's output has type ❰List a → Optional a❱\n\-        \                                                                                \n\-        \                                                                                \n\-        \                       The function's input type is ❰List Text❱                 \n\-        \                       ⇩                                                        \n\-        \    ┌────────────────────────────────────────────┐                              \n\-        \    │ List/head Text : List Text → Optional Text │  A function applied to an    \n\-        \    └────────────────────────────────────────────┘  argument can be a function  \n\-        \                                   ⇧                                            \n\-        \                                   The function's output type is ❰Optional Text❱\n\-        \                                                                                \n\-        \                                                                                \n\-        \An expression is not a function if the expression's type is not of the form     \n\-        \❰a → b❱.  For example, these are " <> _NOT <> " functions:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ 1 : Integer │  ❰1❱ is not a function because ❰Integer❱ is not the type of \n\-        \    └─────────────┘  a function                                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ Natural/even +2 : Bool │  ❰Natural/even +2❱ is not a function because     \n\-        \    └────────────────────────┘  ❰Bool❱ is not the type of a function            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ List Text : Type │  ❰List Text❱ is not a function because ❰Type❱ is not   \n\-        \    └──────────────────┘  the type of a function                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You tried to add two ❰Integer❱s without a space around the ❰+❱, like this:    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────┐                                                                     \n\-        \    │ 2+2 │                                                                     \n\-        \    └─────┘                                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \  The above code is parsed as:                                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────┐                                                                  \n\-        \    │ 2 (+2) │                                                                  \n\-        \    └────────┘                                                                  \n\-        \      ⇧                                                                         \n\-        \      The compiler thinks that this ❰2❱ is a function whose argument is ❰+2❱    \n\-        \                                                                                \n\-        \                                                                                \n\-        \  This is because the ❰+❱ symbol has two meanings: you use ❰+❱ to add two       \n\-        \  numbers, but you also can prefix ❰Integer❱ literals with a ❰+❱ to turn them   \n\-        \  into ❰Natural❱ literals (like ❰+2❱)                                           \n\-        \                                                                                \n\-        \  To fix the code, you need to put spaces around the ❰+❱ and also prefix each   \n\-        \  ❰2❱ with a ❰+❱, like this:                                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────┐                                                                 \n\-        \    │ +2 + +2 │                                                                 \n\-        \    └─────────┘                                                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \  You can only add ❰Natural❱ numbers, which is why you must also change each    \n\-        \  ❰2❱ to ❰+2❱                                                                   \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to use the following expression as a function:                        \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... but this expression's type is:                                              \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a function type                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (TypeMismatch expr0 expr1 expr2 expr3) = ErrorMessages {..}-  where-    short = "Wrong type of function argument"--    long =-        "Explanation: Every function declares what type or kind of argument to accept    \n\-        \                                                                                \n\-        \For example:                                                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ λ(x : Bool) → x : Bool → Bool │  This anonymous function only accepts     \n\-        \    └───────────────────────────────┘  arguments that have type ❰Bool❱          \n\-        \                        ⇧                                                       \n\-        \                        The function's input type                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ Natural/even : Natural → Bool │  This built-in function only accepts      \n\-        \    └───────────────────────────────┘  arguments that have type ❰Natural❱       \n\-        \                     ⇧                                                          \n\-        \                     The function's input type                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ λ(a : Type) → a : Type → Type │  This anonymous function only accepts     \n\-        \    └───────────────────────────────┘  arguments that have kind ❰Type❱          \n\-        \                        ⇧                                                       \n\-        \                        The function's input kind                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ List : Type → Type │  This built-in function only accepts arguments that  \n\-        \    └────────────────────┘  have kind ❰Type❱                                    \n\-        \             ⇧                                                                  \n\-        \             The function's input kind                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expressions are valid:                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ (λ(x : Bool) → x) True │  ❰True❱ has type ❰Bool❱, which matches the type  \n\-        \    └────────────────────────┘  of argument that the anonymous function accepts \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ Natural/even +2 │  ❰+2❱ has type ❰Natural❱, which matches the type of     \n\-        \    └─────────────────┘  argument that the ❰Natural/even❱ function accepts,     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ (λ(a : Type) → a) Bool │  ❰Bool❱ has kind ❰Type❱, which matches the kind  \n\-        \    └────────────────────────┘  of argument that the anonymous function accepts \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────┐                                                               \n\-        \    │ List Text │  ❰Text❱ has kind ❰Type❱, which matches the kind of argument   \n\-        \    └───────────┘  that that the ❰List❱ function accepts                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you can " <> _NOT <> " apply a function to the wrong type or kind of argument\n\-        \                                                                                \n\-        \For example, the following expressions are not valid:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────┐                                                   \n\-        \    │ (λ(x : Bool) → x) \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the anonymous function\n\-        \    └───────────────────────┘  expects an argument that has type ❰Bool❱         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ Natural/even \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the ❰Natural/even❱ function\n\-        \    └──────────────────┘  expects an argument that has type ❰Natural❱           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ (λ(a : Type) → a) True │  ❰True❱ has type ❰Bool❱, but the anonymous       \n\-        \    └────────────────────────┘  function expects an argument of kind ❰Type❱     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────┐                                                                  \n\-        \    │ List 1 │  ❰1❱ has type ❰Integer❱, but the ❰List❱ function expects an      \n\-        \    └────────┘  argument that has kind ❰Type❱                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You omit a function argument by mistake:                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────┐                                                   \n\-        \    │ List/head   [1, 2, 3] │                                                   \n\-        \    └───────────────────────┘                                                   \n\-        \                ⇧                                                               \n\-        \                ❰List/head❱ is missing the first argument,                      \n\-        \                which should be: ❰Integer❱                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You supply an ❰Integer❱ literal to a function that expects a ❰Natural❱        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ Natural/even 2 │                                                          \n\-        \    └────────────────┘                                                          \n\-        \                   ⇧                                                            \n\-        \                   This should be ❰+2❱                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to invoke the following function:                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which expects an argument of type or kind:                                  \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... on the following argument:                                                  \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n\-        \                                                                                \n\-        \... which has a different type or kind:                                         \n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2-        txt3 = build expr3--prettyTypeMessage (AnnotMismatch expr0 expr1 expr2) = ErrorMessages {..}-  where-    short = "Expression doesn't match annotation"--    long =-        "Explanation: You can annotate an expression with its type or kind using the     \n\-        \❰:❱ symbol, like this:                                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────┐                                                                   \n\-        \    │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱\n\-        \    └───────┘                                                                   \n\-        \                                                                                \n\-        \The type checker verifies that the expression's type or kind matches the        \n\-        \provided annotation                                                             \n\-        \                                                                                \n\-        \For example, all of the following are valid annotations that the type checker   \n\-        \accepts:                                                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ 1 : Integer │  ❰1❱ is an expression that has type ❰Integer❱, so the type  \n\-        \    └─────────────┘  checker accepts the annotation                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ Natural/even +2 : Bool │  ❰Natural/even +2❱ has type ❰Bool❱, so the type  \n\-        \    └────────────────────────┘  checker accepts the annotation                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ List : Type → Type │  ❰List❱ is an expression that has kind ❰Type → Type❱,\n\-        \    └────────────────────┘  so the type checker accepts the annotation          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ List Text : Type │  ❰List Text❱ is an expression that has kind ❰Type❱, so \n\-        \    └──────────────────┘  the type checker accepts the annotation               \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, the following annotations are " <> _NOT <> " valid and the type checker will\n\-        \reject them:                                                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────┐                                                                \n\-        \    │ 1 : Text │  The type checker rejects this because ❰1❱ does not have type  \n\-        \    └──────────┘  ❰Text❱                                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ List : Type │  ❰List❱ does not have kind ❰Type❱                           \n\-        \    └─────────────┘                                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● The Haskell Dhall interpreter implicitly inserts a top-level annotation       \n\-        \  matching the expected type                                                    \n\-        \                                                                                \n\-        \  For example, if you run the following Haskell code:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ >>> input auto \"1\" :: IO Text │                                         \n\-        \    └───────────────────────────────┘                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \  ... then the interpreter will actually type check the following annotated     \n\-        \  expression:                                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────┐                                                                \n\-        \    │ 1 : Text │                                                                \n\-        \    └──────────┘                                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \  ... and then type-checking will fail                                          \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You or the interpreter annotated this expression:                               \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... with this type or kind:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but the inferred type or kind of the expression is actually:                \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2--prettyTypeMessage Untyped = ErrorMessages {..}-  where-    short = "❰Kind❱ has no type or kind"--    long =-        "Explanation: There are four levels of expressions that form a hierarchy:        \n\-        \                                                                                \n\-        \● terms                                                                         \n\-        \● types                                                                         \n\-        \● kinds                                                                         \n\-        \● sorts                                                                         \n\-        \                                                                                \n\-        \The following example illustrates this hierarchy:                               \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ \"ABC\" : Text : Type : Kind │                                            \n\-        \    └────────────────────────────┘                                              \n\-        \       ⇧      ⇧      ⇧      ⇧                                                   \n\-        \       term   type   kind   sort                                                \n\-        \                                                                                \n\-        \There is nothing above ❰Kind❱ in this hierarchy, so if you try to type check any\n\-        \expression containing ❰Kind❱ anywhere in the expression then type checking fails\n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You supplied a kind where a type was expected                                 \n\-        \                                                                                \n\-        \  For example, the following expression will fail to type check:                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ [] : List Type │                                                          \n\-        \    └────────────────┘                                                          \n\-        \                ⇧                                                               \n\-        \                ❰Type❱ is a kind, not a type                                    \n"--prettyTypeMessage (InvalidPredicate expr0 expr1) = ErrorMessages {..}-  where-    short = "Invalid predicate for ❰if❱"--    long =-        "Explanation: Every ❰if❱ expression begins with a predicate which must have type \n\-        \❰Bool❱                                                                          \n\-        \                                                                                \n\-        \For example, these are valid ❰if❱ expressions:                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ if True then \"Yes\" else \"No\" │                                        \n\-        \    └──────────────────────────────┘                                            \n\-        \         ⇧                                                                      \n\-        \         Predicate                                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ λ(x : Bool) → if x then False else True │                                 \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                       ⇧                                                        \n\-        \                       Predicate                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but these are " <> _NOT <> " valid ❰if❱ expressions:                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────┐                                               \n\-        \    │ if 0 then \"Yes\" else \"No\" │  ❰0❱ does not have type ❰Bool❱            \n\-        \    └───────────────────────────┘                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ if \"\" then False else True │  ❰\"\"❱ does not have type ❰Bool❱          \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You might be used to other programming languages that accept predicates other \n\-        \  than ❰Bool❱                                                                   \n\-        \                                                                                \n\-        \  For example, some languages permit ❰0❱ or ❰\"\"❱ as valid predicates and treat\n\-        \  them as equivalent to ❰False❱.  However, the Dhall language does not permit   \n\-        \  this                                                                          \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \Your ❰if❱ expression begins with the following predicate:                       \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... that has type:                                                              \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but the predicate must instead have type ❰Bool❱                             \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (IfBranchMustBeTerm b expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "❰if❱ branch is not a term"--    long =-        "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\-        \is an expression:                                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \                   Expression for ❰then❱ branch                                 \n\-        \                   ⇩                                                            \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ if True then \"Hello, world!\"   │                                        \n\-        \    │         else \"Goodbye, world!\" │                                        \n\-        \    └────────────────────────────────┘                                          \n\-        \                   ⇧                                                            \n\-        \                   Expression for ❰else❱ branch                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \These expressions must be a \"term\", where a \"term\" is defined as an expression\n\-        \that has a type thas has kind ❰Type❱                                            \n\-        \                                                                                \n\-        \For example, the following expressions are all valid \"terms\":                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ 1 : Integer : Type │  ❰1❱ is a term with a type (❰Integer❱) of kind ❰Type❱\n\-        \    └────────────────────┘                                                      \n\-        \      ⇧                                                                         \n\-        \      term                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────┐                                     \n\-        \    │ Natural/odd : Natural → Bool : Type │  ❰Natural/odd❱ is a term with a type\n\-        \    └─────────────────────────────────────┘  (❰Natural → Bool❱) of kind ❰Type❱  \n\-        \      ⇧                                                                         \n\-        \      term                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, the following expressions are " <> _NOT <> " valid terms:              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ Text : Type : Kind │  ❰Text❱ has kind (❰Type❱) of sort ❰Kind❱ and is      \n\-        \    └────────────────────┘  therefore not a term                                \n\-        \      ⇧                                                                         \n\-        \      type                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────┐                                               \n\-        \    │ List : Type → Type : Kind │  ❰List❱ has kind (❰Type → Type❱) of sort      \n\-        \    └───────────────────────────┘  ❰Kind❱ and is therefore not a term           \n\-        \      ⇧                                                                         \n\-        \      type-level function                                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \This means that you cannot define an ❰if❱ expression that returns a type.  For  \n\-        \example, the following ❰if❱ expression is " <> _NOT <> " valid:                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────┐                                             \n\-        \    │ if True then Text else Bool │  Invalid ❰if❱ expression                    \n\-        \    └─────────────────────────────┘                                             \n\-        \                   ⇧         ⇧                                                  \n\-        \                   type      type                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your ❰" <> txt0 <> "❱ branch of your ❰if❱ expression is:                        \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which has kind:                                                             \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n\-        \                                                                                \n\-        \... of sort:                                                                    \n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n\-        \                                                                                \n\-        \... and is not a term.  Therefore your ❰if❱ expression is not valid             \n"-      where-        txt0 = if b then "then" else "else"-        txt1 = build expr0-        txt2 = build expr1-        txt3 = build expr2--prettyTypeMessage (IfBranchMismatch expr0 expr1 expr2 expr3) =-    ErrorMessages {..}-  where-    short = "❰if❱ branches must have matching types"--    long =-        "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\-        \is an expression:                                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \                   Expression for ❰then❱ branch                                 \n\-        \                   ⇩                                                            \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ if True then \"Hello, world!\"   │                                        \n\-        \    │         else \"Goodbye, world!\" │                                        \n\-        \    └────────────────────────────────┘                                          \n\-        \                   ⇧                                                            \n\-        \                   Expression for ❰else❱ branch                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \These two expressions must have the same type.  For example, the following ❰if❱ \n\-        \expressions are all valid:                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ λ(b : Bool) → if b then 0 else 1 │ Both branches have type ❰Integer❱      \n\-        \    └──────────────────────────────────┘                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ λ(b : Bool) →              │                                              \n\-        \    │     if b then Natural/even │ Both branches have type ❰Natural → Bool❱     \n\-        \    │          else Natural/odd  │                                              \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, the following expression is " <> _NOT <> " valid:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \                   This branch has type ❰Integer❱                               \n\-        \                   ⇩                                                            \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ if True then 0         │                                                  \n\-        \    │         else \"ABC\"     │                                                \n\-        \    └────────────────────────┘                                                  \n\-        \                   ⇧                                                            \n\-        \                   This branch has type ❰Text❱                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \The ❰then❱ and ❰else❱ branches must have matching types, even if the predicate  \n\-        \is always ❰True❱ or ❰False❱                                                     \n\-        \                                                                                \n\-        \Your ❰if❱ expression has the following ❰then❱ branch:                           \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which has type:                                                             \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n\-        \                                                                                \n\-        \... and the following ❰else❱ branch:                                            \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which has a different type:                                                 \n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n\-        \                                                                                \n\-        \Fix your ❰then❱ and ❰else❱ branches to have matching types                      \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2-        txt3 = build expr3--prettyTypeMessage (InvalidListType expr0) = ErrorMessages {..}-  where-    short = "Invalid type for ❰List❱ elements"--    long =-        "Explanation: ❰List❱s can optionally document the type of their elements with a  \n\-        \type annotation, like this:                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────┐                                                \n\-        \    │ [1, 2, 3] : List Integer │  A ❰List❱ of three ❰Integer❱s                  \n\-        \    └──────────────────────────┘                                                \n\-        \                       ⇧                                                        \n\-        \                       The type of the ❰List❱'s elements, which are ❰Integer❱s  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────┐                                                       \n\-        \    │ [] : List Integer │  An empty ❰List❱                                      \n\-        \    └───────────────────┘                                                       \n\-        \                ⇧                                                               \n\-        \                You must specify the type when the ❰List❱ is empty              \n\-        \                                                                                \n\-        \                                                                                \n\-        \The element type must be a type and not something else.  For example, the       \n\-        \following element types are " <> _NOT <> " valid:                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────┐                                                            \n\-        \    │ ... : List 1 │                                                            \n\-        \    └──────────────┘                                                            \n\-        \                 ⇧                                                              \n\-        \                 This is an ❰Integer❱ and not a ❰Type❱                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ ... : List Type │                                                         \n\-        \    └─────────────────┘                                                         \n\-        \                 ⇧                                                              \n\-        \                 This is a ❰Kind❱ and not a ❰Type❱                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \You declared that the ❰List❱'s elements should have type:                       \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a ❰Type❱                                                       \n"-      where-        txt0 = build expr0--prettyTypeMessage MissingListType = do-    ErrorMessages {..}-  where-    short = "An empty list requires a type annotation"--    long =-        "Explanation: Lists do not require a type annotation if they have at least one   \n\-        \element:                                                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────┐                                                               \n\-        \    │ [1, 2, 3] │  The compiler can infer that this list has type ❰List Integer❱\n\-        \    └───────────┘                                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, empty lists still require a type annotation:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────┐                                                       \n\-        \    │ [] : List Integer │  This type annotation is mandatory                    \n\-        \    └───────────────────┘                                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \You cannot supply an empty list without a type annotation                       \n"--prettyTypeMessage (MismatchedListElements i expr0 _expr1 expr2) =-    ErrorMessages {..}-  where-    short = "List elements should all have the same type"--    long =-        "Explanation: Every element in a list must have the same type                    \n\-        \                                                                                \n\-        \For example, this is a valid ❰List❱:                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────┐                                                               \n\-        \    │ [1, 2, 3] │  Every element in this ❰List❱ is an ❰Integer❱                 \n\-        \    └───────────┘                                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \.. but this is " <> _NOT <> " a valid ❰List❱:                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────┐                                                           \n\-        \    │ [1, \"ABC\", 3] │  The first and second element have different types      \n\-        \    └───────────────┘                                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your first ❰List❱ element has this type:                                        \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... but the element at index #" <> txt1 <> " has this type instead:             \n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build i-        txt3 = build expr2--prettyTypeMessage (InvalidListElement i expr0 _expr1 expr2) =-    ErrorMessages {..}-  where-    short = "List element has the wrong type"--    long =-        "Explanation: Every element in the list must have a type matching the type       \n\-        \annotation at the end of the list                                               \n\-        \                                                                                \n\-        \For example, this is a valid ❰List❱:                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────┐                                                \n\-        \    │ [1, 2, 3] : List Integer │  Every element in this ❰List❱ is an ❰Integer❱  \n\-        \    └──────────────────────────┘                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \.. but this is " <> _NOT <> " a valid ❰List❱:                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ [1, \"ABC\", 3] : List Integer │  The second element is not an ❰Integer❱  \n\-        \    └──────────────────────────────┘                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your ❰List❱ elements should have this type:                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... but the element at index #" <> txt1 <> " has this type instead:             \n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build i-        txt3 = build expr2--prettyTypeMessage (InvalidOptionalType expr0) = ErrorMessages {..}-  where-    short = "Invalid type for ❰Optional❱ element"--    long =-        "Explanation: Every optional element ends with a type annotation for the element \n\-        \that might be present, like this:                                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [1] : Optional Integer │  An optional element that's present              \n\-        \    └────────────────────────┘                                                  \n\-        \                     ⇧                                                          \n\-        \                     The type of the ❰Optional❱ element, which is an ❰Integer❱  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [] : Optional Integer  │  An optional element that's absent               \n\-        \    └────────────────────────┘                                                  \n\-        \                    ⇧                                                           \n\-        \                    You still specify the type even when the element is absent  \n\-        \                                                                                \n\-        \                                                                                \n\-        \The element type must be a type and not something else.  For example, the       \n\-        \following element types are " <> _NOT <> " valid:                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ ... : Optional 1 │                                                        \n\-        \    └──────────────────┘                                                        \n\-        \                     ⇧                                                          \n\-        \                     This is an ❰Integer❱ and not a ❰Type❱                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────┐                                                     \n\-        \    │ ... : Optional Type │                                                     \n\-        \    └─────────────────────┘                                                     \n\-        \                     ⇧                                                          \n\-        \                     This is a ❰Kind❱ and not a ❰Type❱                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \Even if the element is absent you still must specify a valid type               \n\-        \                                                                                \n\-        \You declared that the ❰Optional❱ element should have type:                      \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a ❰Type❱                                                       \n"-      where-        txt0 = build expr0--prettyTypeMessage (InvalidOptionalElement expr0 expr1 expr2) = ErrorMessages {..}-  where-    short = "❰Optional❱ element has the wrong type"--    long =-        "Explanation: An ❰Optional❱ element must have a type matching the type annotation\n\-        \                                                                                \n\-        \For example, this is a valid ❰Optional❱ value:                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [1] : Optional Integer │  ❰1❱ is an ❰Integer❱, which matches the type     \n\-        \    └────────────────────────┘                                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but this is " <> _NOT <> " a valid ❰Optional❱ value:                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ [\"ABC\"] : Optional Integer │  ❰\"ABC\"❱ is not an ❰Integer❱             \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your ❰Optional❱ element should have this type:                                  \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... but the element you provided:                                               \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... has this type instead:                                                      \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2--prettyTypeMessage (InvalidFieldType k expr0) = ErrorMessages {..}-  where-    short = "Invalid field type"--    long =-        "Explanation: Every record type documents the type of each field, like this:     \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────────┐                            \n\-        \    │ { foo : Integer, bar : Integer, baz : Text } │                            \n\-        \    └──────────────────────────────────────────────┘                            \n\-        \                                                                                \n\-        \However, fields cannot be annotated with expressions other than types           \n\-        \                                                                                \n\-        \For example, these record types are " <> _NOT <> " valid:                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ { foo : Integer, bar : 1 } │                                              \n\-        \    └────────────────────────────┘                                              \n\-        \                             ⇧                                                  \n\-        \                             ❰1❱ is an ❰Integer❱ and not a ❰Type❱               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ { foo : Integer, bar : Type } │                                           \n\-        \    └───────────────────────────────┘                                           \n\-        \                             ⇧                                                  \n\-        \                             ❰Type❱ is a ❰Kind❱ and not a ❰Type❱                \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided a record type with a key named:                                    \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... annotated with the following expression:                                    \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a type                                                         \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (InvalidField k expr0) = ErrorMessages {..}-  where-    short = "Invalid field"--    long =-        "Explanation: Every record literal is a set of fields assigned to values, like   \n\-        \this:                                                                           \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ { foo = 100, bar = True, baz = \"ABC\" } │                                \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                                                                \n\-        \However, fields can only be terms and cannot be types or kinds                  \n\-        \                                                                                \n\-        \For example, these record literals are " <> _NOT <> " valid:                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────┐                                               \n\-        \    │ { foo = 100, bar = Text } │                                               \n\-        \    └───────────────────────────┘                                               \n\-        \                         ⇧                                                      \n\-        \                         ❰Text❱ is a type and not a term                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────┐                                               \n\-        \    │ { foo = 100, bar = Type } │                                               \n\-        \    └───────────────────────────┘                                               \n\-        \                         ⇧                                                      \n\-        \                         ❰Type❱ is a kind and not a term                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided a record literal with a key named:                                 \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... whose value is:                                                             \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a term                                                         \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (InvalidAlternativeType k expr0) = ErrorMessages {..}-  where-    short = "Invalid alternative"--    long =-        "Explanation: Every union literal begins by selecting one alternative and        \n\-        \specifying the value for that alternative, like this:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \        Select the ❰Left❱ alternative, whose value is ❰True❱                    \n\-        \        ⇩                                                                       \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ < Left = True, Right : Natural > │  A union literal with two alternatives \n\-        \    └──────────────────────────────────┘                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, this value must be a term and not a type.  For example, the following  \n\-        \values are " <> _NOT <> " valid:                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ < Left = Text, Right : Natural > │  Invalid union literal                 \n\-        \    └──────────────────────────────────┘                                        \n\-        \               ⇧                                                                \n\-        \               This is a type and not a term                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ < Left = Type, Right : Type > │  Invalid union type                       \n\-        \    └───────────────────────────────┘                                           \n\-        \               ⇧                                                                \n\-        \               This is a kind and not a term                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You accidentally typed ❰=❱ instead of ❰:❱ for a union literal with one        \n\-        \  alternative:                                                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ < Example = Text > │                                                      \n\-        \    └────────────────────┘                                                      \n\-        \                ⇧                                                               \n\-        \                This could be ❰:❱ instead                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided a union literal with an alternative named:                         \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... whose value is:                                                             \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a term                                                         \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (InvalidAlternative k expr0) = ErrorMessages {..}-  where-    short = "Invalid alternative"--    long =-        "Explanation: Every union type specifies the type of each alternative, like this:\n\-        \                                                                                \n\-        \                                                                                \n\-        \               The type of the first alternative is ❰Bool❱                      \n\-        \               ⇩                                                                \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ < Left : Bool, Right : Natural > │  A union type with two alternatives    \n\-        \    └──────────────────────────────────┘                                        \n\-        \                             ⇧                                                  \n\-        \                             The type of the second alternative is ❰Natural❱    \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, these alternatives can only be annotated with types.  For example, the \n\-        \following union types are " <> _NOT <> " valid:                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ < Left : Bool, Right : 1 > │  Invalid union type                          \n\-        \    └────────────────────────────┘                                              \n\-        \                             ⇧                                                  \n\-        \                             This is a term and not a type                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ < Left : Bool, Right : Type > │  Invalid union type                       \n\-        \    └───────────────────────────────┘                                           \n\-        \                             ⇧                                                  \n\-        \                             This is a kind and not a type                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You accidentally typed ❰:❱ instead of ❰=❱ for a union literal with one        \n\-        \  alternative:                                                                  \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ < Example : 1 > │                                                         \n\-        \    └─────────────────┘                                                         \n\-        \                ⇧                                                               \n\-        \                This could be ❰=❱ instead                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided a union type with an alternative named:                            \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... annotated with the following expression which is not a type:                \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (ListAppendMismatch expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only append ❰List❱s with matching element types"--    long =-        "Explanation: You can append two ❰List❱s using the ❰#❱ operator, like this:      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────┐                                                      \n\-        \    │ [1, 2, 3] # [4, 5] │                                                      \n\-        \    └────────────────────┘                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot append two ❰List❱s if they have different element types.     \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \       These elements have type ❰Integer❱                                       \n\-        \       ⇩                                                                        \n\-        \    ┌───────────────────────────┐                                               \n\-        \    │ [1, 2, 3] # [True, False] │  Invalid: the element types don't match       \n\-        \    └───────────────────────────┘                                               \n\-        \                  ⇧                                                             \n\-        \                  These elements have type ❰Bool❱                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to append a ❰List❱ thas has elements of type:                         \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... with another ❰List❱ that has elements of type:                              \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... and those two types do not match                                            \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (DuplicateAlternative k) = ErrorMessages {..}-  where-    short = "Duplicate union alternative"--    long =-        "Explanation: Unions may not have two alternatives that share the same name      \n\-        \                                                                                \n\-        \For example, the following expressions are " <> _NOT <> " valid:                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────┐                                             \n\-        \    │ < foo = True | foo : Text > │  Invalid: ❰foo❱ appears twice               \n\-        \    └─────────────────────────────┘                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────┐                                   \n\-        \    │ < foo = 1 | bar : Bool | bar : Text > │  Invalid: ❰bar❱ appears twice     \n\-        \    └───────────────────────────────────────┘                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \You have more than one alternative named:                                       \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n"-      where-        txt0 = build k--prettyTypeMessage (MustCombineARecord c expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only combine records"--    long =-        "Explanation: You can combine records using the ❰" <> op <> "❱ operator, like this:\n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz = True } │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────┐                             \n\-        \    │ λ(r : { foo : Bool }) → r " <> op <> " { bar = \"ABC\" } │                \n\-        \    └─────────────────────────────────────────────┘                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot combine values that are not records.                         \n\-        \                                                                                \n\-        \For example, the following expressions are " <> _NOT <> " valid:                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " 1 │                               \n\-        \    └──────────────────────────────┘                                            \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: Not a record                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz : Bool } │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: This is a record type and not a record\n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " < baz = True > │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: This is a union and not a record      \n\-        \                                                                                \n\-        \                                                                                \n\-        \You tried to combine the following value:                                       \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a record, but is actually a:                                   \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        op   = build c-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (FieldCollision k) = ErrorMessages {..}-  where-    short = "Field collision"--    long =-        "Explanation: You can combine records if they don't share any fields in common,  \n\-        \like this:                                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { baz = True } │                             \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ λ(r : { baz : Bool}) → { foo = 1 } ∧ r │                                  \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot merge two records that share the same field                  \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = True } │  Invalid: Colliding ❰foo❱ fields\n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You tried to use ❰∧❱ to update a field's value, like this:                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = 2 } │                                \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                   ⇧                                            \n\-        \                                   Invalid attempt to update ❰foo❱'s value to ❰2❱\n\-        \                                                                                \n\-        \  Field updates are intentionally not allowed as the Dhall language discourages \n\-        \  patch-oriented programming                                                    \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You combined two records that share the following field:                        \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not allowed                                                        \n"-      where-        txt0 = build k--prettyTypeMessage (MustMergeARecord expr0 expr1) = ErrorMessages {..}-  where-    short = "❰merge❱ expects a record of handlers"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but the first argument to ❰merge❱ must be a record and not some other type. \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ let handler = λ(x : Bool) → x           │                                 \n\-        \    │ in  merge handler < Foo = True > : True │                                 \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                ⇧                                                               \n\-        \                Invalid: ❰handler❱ isn't a record                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You accidentally provide an empty record type instead of an empty record when \n\-        \  you ❰merge❱ an empty union:                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────┐                                \n\-        \    │ λ(x : <>) → λ(a : Type) → merge {} x : a │                                \n\-        \    └──────────────────────────────────────────┘                                \n\-        \                                      ⇧                                         \n\-        \                                      This should be ❰{=}❱ instead              \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided the following handler:                                             \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a record, but is actually a value of type:                     \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (MustMergeUnion expr0 expr1) = ErrorMessages {..}-  where-    short = "❰merge❱ expects a union"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but the second argument to ❰merge❱ must be a union and not some other type. \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────┐                                \n\-        \    │ let handlers = { Foo = λ(x : Bool) → x } │                                \n\-        \    │ in  merge handlers True : True           │                                \n\-        \    └──────────────────────────────────────────┘                                \n\-        \                         ⇧                                                      \n\-        \                         Invalid: ❰True❱ isn't a union                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \You tried to ❰merge❱ this expression:                                           \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a union, but is actually a value of type:                      \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (UnusedHandler ks) = ErrorMessages {..}-  where-    short = "Unused handler"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you must provide exactly one handler per alternative in the union.  You \n\-        \cannot supply extra handlers                                                    \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────┐                                   \n\-        \    │     let union    = < Left = +2 >      │  The ❰Right❱ alternative is missing\n\-        \    │ in  let handlers =                    │                                   \n\-        \    │             { Left  = Natural/even    │                                   \n\-        \    │             , Right = λ(x : Bool) → x │  Invalid: ❰Right❱ handler isn't used\n\-        \    │             }                         │                                   \n\-        \    │ in  merge handlers union : Bool       │                                   \n\-        \    └───────────────────────────────────────┘                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided the following handlers:                                            \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which had no matching alternatives in the union you tried to ❰merge❱        \n"-      where-        txt0 = build (Text.intercalate ", " (Data.Set.toList ks))--prettyTypeMessage (MissingHandler ks) = ErrorMessages {..}-  where-    short = "Missing handler"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you must provide exactly one handler per alternative in the union.  You \n\-        \cannot omit any handlers                                                        \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \                                              Invalid: Missing ❰Right❱ handler  \n\-        \                                              ⇩                                 \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │     let handlers = { Left = Natural/even }      │                         \n\-        \    │ in  let union    = < Left = +2 | Right : Bool > │                         \n\-        \    │ in  merge handlers union : Bool                 │                         \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \Note that you need to provide handlers for other alternatives even if those     \n\-        \alternatives are never used                                                     \n\-        \                                                                                \n\-        \You need to supply the following handlers:                                      \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n"-      where-        txt0 = build (Text.intercalate ", " (Data.Set.toList ks))--prettyTypeMessage MissingMergeType =-    ErrorMessages {..}-  where-    short = "An empty ❰merge❱ requires a type annotation"--    long =-        "Explanation: A ❰merge❱ does not require a type annotation if the union has at   \n\-        \least one alternative, like this                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union                                            │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you must provide a type annotation when merging an empty union:        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ λ(a : <>) → merge {=} a : Bool │                                          \n\-        \    └────────────────────────────────┘                                          \n\-        \                                ⇧                                               \n\-        \                                This can be any type                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \You can provide any type at all as the annotation, since merging an empty       \n\-        \union can produce any type of output                                            \n"--prettyTypeMessage (HandlerInputTypeMismatch expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "Wrong handler input type"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the input type of each handler function matches the type of the  \n\-        \corresponding alternative:                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ union    : < Left : Natural       | Right : Bool        > │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                          ⇧                       ⇧                             \n\-        \                   These must match        These must match                     \n\-        \                          ⇩                       ⇩                             \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \      Invalid: Doesn't match the type of the ❰Right❱ alternative                \n\-        \                                                               ⇩                \n\-        \    ┌──────────────────────────────────────────────────────────────────────┐    \n\-        \    │     let handlers = { Left = Natural/even | Right = λ(x : Text) → x } │    \n\-        \    │ in  let union    = < Left = +2 | Right : Bool >                      │    \n\-        \    │ in  merge handlers union : Bool                                      │    \n\-        \    └──────────────────────────────────────────────────────────────────────┘    \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for the following alternative:                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... needs to accept an input value of type:                                     \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but actually accepts an input value of a different type:                    \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2--prettyTypeMessage (InvalidHandlerOutputType expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "Wrong handler output type"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the output type of each handler function matches the declared type\n\-        \of the result:                                                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                                    ⇧                    ⇧                      \n\-        \                                    These output types ...                      \n\-        \                                                                                \n\-        \                             ... must match the declared type of the ❰merge❱    \n\-        \                             ⇩                                                  \n\-        \    ┌─────────────────────────────┐                                             \n\-        \    │ merge handlers union : Bool │                                             \n\-        \    └─────────────────────────────┘                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────────────────────────────────┐    \n\-        \    │     let union    = < Left = +2 | Right : Bool >                      │    \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x }  │    \n\-        \    │ in  merge handlers union : Text                                      │    \n\-        \    └──────────────────────────────────────────────────────────────────────┘    \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: Doesn't match output of either handler\n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for the following alternative:                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... needs to return an output value of type:                                    \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but actually returns an output value of a different type:                   \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-        txt2 = build expr2--prettyTypeMessage (HandlerOutputTypeMismatch key0 expr0 key1 expr1) =-    ErrorMessages {..}-  where-    short = "Handlers should have the same output type"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union                                            │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the output type of each handler function is the same:            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                                    ⇧                    ⇧                      \n\-        \                                These output types both match                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │     let union    = < Left = +2 | Right : Bool > │                         \n\-        \    │ in  let handlers =                              │                         \n\-        \    │              { Left  = λ(x : Natural) → x       │  This outputs ❰Natural❱ \n\-        \    │              , Right = λ(x : Bool   ) → x       │  This outputs ❰Bool❱    \n\-        \    │              }                                  │                         \n\-        \    │ in  merge handlers union                        │                         \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                ⇧                                                               \n\-        \                Invalid: The handlers in this record don't have matching outputs\n\-        \                                                                                \n\-        \                                                                                \n\-        \The handler for the ❰" <> txt0 <> "❱ alternative has this output type:          \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but the handler for the ❰" <> txt2 <> "❱ alternative has this output type instead:\n\-        \                                                                                \n\-        \↳ " <> txt3 <> "                                                                \n"-      where-        txt0 = build key0-        txt1 = build expr0-        txt2 = build key1-        txt3 = build expr1--prettyTypeMessage (HandlerNotAFunction k expr0) = ErrorMessages {..}-  where-    short = "Handler is not a function"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = +2 | Right : Bool >                     │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as each handler is a function                                       \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ merge { Foo = True } < Foo = 1 > : Bool │                                 \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                    ⇧                                                           \n\-        \                    Invalid: Not a function                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for this alternative:                                              \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... has the following type:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not the type of a function                                         \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (ConstructorsRequiresAUnionType expr0 expr1) = ErrorMessages {..}-  where-    short = "❰constructors❱ requires a union type"--    long =-        "Explanation: You can only use the ❰constructors❱ keyword on an argument that is \n\-        \a union type literal, like this:                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────┐                           \n\-        \    │ constructors < Left : Natural, Right : Bool > │                           \n\-        \    └───────────────────────────────────────────────┘                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot use the ❰constructors❱ keyword on any other type of argument.\n\-        \For example, you cannot use a variable argument:                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ λ(t : Type) → constructors t │  Invalid: ❰t❱ might not be a union type    \n\-        \    └──────────────────────────────┘                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │ let t : Type = < Left : Natural, Right : Bool > │  Invalid: Type-checking \n\-        \    │ in  constructors t                              │  precedes normalization \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you can import the union type argument:                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ constructors ./unionType.dhall │ Valid: Import resolution precedes        \n\-        \    └────────────────────────────────┘ type-checking                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to supply the following argument:                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which normalized to:                                                        \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a union type literal                                           \n"-      where-        txt0 = build expr0-        txt1 = build expr1- -prettyTypeMessage (NotARecord k expr0 expr1) = ErrorMessages {..}-  where-    short = "Not a record"--    long =-        "Explanation: You can only access fields on records, like this:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot access fields on non-record expressions                      \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────┐                                                                   \n\-        \    │ 1.foo │                                                                   \n\-        \    └───────┘                                                                   \n\-        \      ⇧                                                                         \n\-        \      Invalid: Not a record                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You accidentally try to access a field of a union instead of a record, like   \n\-        \  this:                                                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ < foo : a >.foo │                                                         \n\-        \    └─────────────────┘                                                         \n\-        \      ⇧                                                                         \n\-        \      This is a union, not a record                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to access a field named:                                              \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... on the following expression which is not a record:                          \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... but is actually an expression of type:                                      \n\-        \                                                                                \n\-        \↳ " <> txt2 <> "                                                                \n"-      where-        txt0 = build k-        txt1 = build expr0-        txt2 = build expr1--prettyTypeMessage (MissingField k expr0) = ErrorMessages {..}-  where-    short = "Missing record field"--    long =-        "Explanation: You can only access fields on records, like this:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you can only access fields if they are present                          \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = True, bar = \"ABC\" }.qux │                                       \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                  ⇧                                             \n\-        \                                  Invalid: the record has no ❰qux❱ field        \n\-        \                                                                                \n\-        \You tried to access a field named:                                              \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... but the field is missing because the record only defines the following fields:\n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build k-        txt1 = build expr0--prettyTypeMessage (CantAnd expr0 expr1) =-        buildBooleanOperator "&&" expr0 expr1--prettyTypeMessage (CantOr expr0 expr1) =-        buildBooleanOperator "||" expr0 expr1--prettyTypeMessage (CantEQ expr0 expr1) =-        buildBooleanOperator "==" expr0 expr1--prettyTypeMessage (CantNE expr0 expr1) =-        buildBooleanOperator "/=" expr0 expr1--prettyTypeMessage (CantInterpolate expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only interpolate ❰Text❱"--    long =-        "Explanation: Text interpolation only works on expressions of type ❰Text❱        \n\-        \                                                                                \n\-        \For example, these are all valid uses of string interpolation:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ \"ABC${\"DEF\"}GHI\" │                                                    \n\-        \    └──────────────────┘                                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ λ(x : Text) → \"ABC${x}GHI\" │                                            \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────────────┐       \n\-        \    │ λ(age : Natural) → \"Age: ${Integer/show (Natural/toInteger age)}\" │     \n\-        \    └───────────────────────────────────────────────────────────────────┘       \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You might have thought that string interpolation automatically converts the   \n\-        \  interpolated value to a ❰Text❱ representation of that value:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ λ(age : Natural) → \"Age: ${age}\" │                                      \n\-        \    └──────────────────────────────────┘                                        \n\-        \                                  ⇧                                             \n\-        \                                  Invalid: ❰age❱ has type ❰Natural❱             \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You might have forgotten to escape a string interpolation that you wanted     \n\-        \  Dhall to ignore and pass through:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ \"echo ${HOME}\" │                                                        \n\-        \    └────────────────┘                                                          \n\-        \             ⇧                                                                  \n\-        \             ❰HOME❱ is not in scope and this might have meant to use ❰\\${HOME}❱\n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You interpolated this expression:                                               \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which does not have type ❰Text❱ but instead has type:                       \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1-- --prettyTypeMessage (CantTextAppend expr0 expr1) = ErrorMessages {..}-  where-    short = "❰++❱ only works on ❰Text❱"--    long =-        "Explanation: The ❰++❱ operator expects two arguments that have type ❰Text❱      \n\-        \                                                                                \n\-        \For example, this is a valid use of ❰++❱:                                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ \"ABC\" ++ \"DEF\" │                                                      \n\-        \    └────────────────┘                                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You might have thought that ❰++❱ was the operator to combine two lists:       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [1, 2, 3] ++ [4, 5, 6] │  Not valid                                       \n\-        \    └────────────────────────┘                                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \  ... but the list concatenation operator is actually ❰#❱:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────┐                                                   \n\-        \    │ [1, 2, 3] # [4, 5, 6] │  Valid                                            \n\-        \    └───────────────────────┘                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided this argument:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which does not have type ❰Text❱ but instead has type:                       \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (CantListAppend expr0 expr1) = ErrorMessages {..}-  where-    short = "❰#❱ only works on ❰List❱s"--    long =-        "Explanation: The ❰#❱ operator expects two arguments that are both ❰List❱s       \n\-        \                                                                                \n\-        \For example, this is a valid use of ❰#❱:                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────┐                                                   \n\-        \    │ [1, 2, 3] # [4, 5, 6] │                                                   \n\-        \    └───────────────────────┘                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided this argument:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which is not a ❰List❱ but instead has type:                                 \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--prettyTypeMessage (CantAdd expr0 expr1) =-        buildNaturalOperator "+" expr0 expr1--prettyTypeMessage (CantMultiply expr0 expr1) =-        buildNaturalOperator "*" expr0 expr1--prettyTypeMessage (NoDependentTypes expr0 expr1) = ErrorMessages {..}-  where-    short = "No dependent types"--    long =-        "Explanation: The Dhall programming language does not allow functions from terms \n\-        \to types.  These function types are also known as \"dependent function types\"  \n\-        \because you have a type whose value \"depends\" on the value of a term.         \n\-        \                                                                                \n\-        \For example, this is " <> _NOT <> " a legal function type:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ Bool → Type │                                                             \n\-        \    └─────────────┘                                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \Similarly, this is " <> _NOT <> " legal code:                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────────────────┐                      \n\-        \    │ λ(Vector : Natural → Type → Type) → Vector +0 Text │                      \n\-        \    └────────────────────────────────────────────────────┘                      \n\-        \                 ⇧                                                              \n\-        \                 Invalid dependent type                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your function type is invalid because the input has type:                       \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... and the output has kind:                                                    \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n\-        \                                                                                \n\-        \... which makes this a forbidden dependent function type                        \n"-      where-        txt0 = build expr0-        txt1 = build expr1--buildBooleanOperator :: Buildable a => Text -> Expr s a -> Expr s a -> ErrorMessages-buildBooleanOperator operator expr0 expr1 = ErrorMessages {..}-  where-    short = "❰" <> txt2 <> "❱ only works on ❰Bool❱s"--    long =-        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Bool❱\n\-        \                                                                                \n\-        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────┐                                                           \n\-        \    │ True " <> txt2 <> " False │                                               \n\-        \    └───────────────┘                                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided this argument:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which does not have type ❰Bool❱ but instead has type:                       \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--    txt2 = build operator--buildNaturalOperator :: Buildable a => Text -> Expr s a -> Expr s a -> ErrorMessages-buildNaturalOperator operator expr0 expr1 = ErrorMessages {..}-  where-    short = "❰" <> txt2 <> "❱ only works on ❰Natural❱s"--    long =-        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Natural❱\n\-        \                                                                                \n\-        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────┐                                                                 \n\-        \    │ +3 " <> txt2 <> " +5 │                                                    \n\-        \    └─────────┘                                                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You might have tried to use an ❰Integer❱, which is " <> _NOT <> " allowed:    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ λ(x : Integer) → λ(y : Integer) → x " <> txt2 <> " y │  Not valid         \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \  You can only use ❰Natural❱ numbers                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \● You might have mistakenly used an ❰Integer❱ literal, which is " <> _NOT <> " allowed:\n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────┐                                                                   \n\-        \    │ 2 " <> txt2 <> " 2 │  Not valid                                           \n\-        \    └───────┘                                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \  You need to prefix each literal with a ❰+❱ to transform them into ❰Natural❱   \n\-        \  literals, like this:                                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────┐                                                                 \n\-        \    │ +2 " <> txt2 <> " +2 │  Valid                                             \n\-        \    └─────────┘                                                                 \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided this argument:                                                     \n\-        \                                                                                \n\-        \↳ " <> txt0 <> "                                                                \n\-        \                                                                                \n\-        \... which does not have type ❰Natural❱ but instead has type:                    \n\-        \                                                                                \n\-        \↳ " <> txt1 <> "                                                                \n"-      where-        txt0 = build expr0-        txt1 = build expr1--    txt2 = build operator---- | A structured type error that includes context-data TypeError s a = TypeError-    { context     :: Context (Expr s a)-    , current     :: Expr s a-    , typeMessage :: TypeMessage s a-    } deriving (Typeable)--instance (Buildable a, Buildable s) => Show (TypeError s a) where-    show = Text.unpack . Builder.toLazyText . build--instance (Buildable a, Buildable s, Typeable a, Typeable s) => Exception (TypeError s a)--instance (Buildable a, Buildable s) => Buildable (TypeError s a) where-    build (TypeError ctx expr msg)-        =   "\n"-        <>  (   if  Text.null (Builder.toLazyText (buildContext ctx))-                then ""-                else buildContext ctx <> "\n"-            )-        <>  shortTypeMessage msg <> "\n"-        <>  source-      where-        buildKV (key, val) = build key <> " : " <> build val--        buildContext =-                build-            .   Text.unlines-            .   map (Builder.toLazyText . buildKV)-            .   reverse-            .   Dhall.Context.toList--        source = case expr of-            Note s _ -> build s-            _        -> mempty--{-| Newtype used to wrap error messages so that they render with a more-    detailed explanation of what went wrong--}-newtype DetailedTypeError s a = DetailedTypeError (TypeError s a)-    deriving (Typeable)--instance (Buildable a, Buildable s) => Show (DetailedTypeError s a) where-    show = Text.unpack . Builder.toLazyText . build--instance (Buildable a, Buildable s, Typeable a, Typeable s) => Exception (DetailedTypeError s a)--instance (Buildable a, Buildable s) => Buildable (DetailedTypeError s a) where-    build (DetailedTypeError (TypeError ctx expr msg))-        =   "\n"-        <>  (   if  Text.null (Builder.toLazyText (buildContext ctx))-                then ""-                else buildContext ctx <> "\n"-            )-        <>  longTypeMessage msg <> "\n"-        <>  "────────────────────────────────────────────────────────────────────────────────\n"-        <>  "\n"-        <>  source-      where-        buildKV (key, val) = build key <> " : " <> build val--        buildContext =-                build-            .   Text.unlines-            .   map (Builder.toLazyText . buildKV)-            .   reverse-            .   Dhall.Context.toList--        source = case expr of-            Note s _ -> build s-            _        -> mempty--{-| This function verifies that a custom context is well-formed so that-    type-checking will not loop--    Note that `typeWith` already calls `checkContext` for you on the `Context`-    that you supply--}-checkContext :: Context (Expr s X) -> Either (TypeError s X) ()-checkContext context =-    case Dhall.Context.match context of-        Nothing -> do-            return ()-        Just (x, v, context') -> do-            let shiftedV       =       Dhall.Core.shift (-1) (V x 0)  v-            let shiftedContext = fmap (Dhall.Core.shift (-1) (V x 0)) context'-            _ <- typeWith shiftedContext shiftedV-            return ()+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns        #-}++{-# OPTIONS_GHC -Wall #-}++-- | This module contains the logic for type checking Dhall code++module Dhall.TypeCheck (+    -- * Type-checking+      typeWith+    , typeOf+    , typeWithA+    , checkContext+    , messageExpressions++    -- * Types+    , Typer+    , X+    , absurd+    , TypeError(..)+    , DetailedTypeError(..)+    , Censored(..)+    , TypeMessage(..)+    , prettyTypeMessage+    , ErrorMessages(..)+    ) where++import Control.Exception                 (Exception)+import Control.Monad.Trans.Class         (lift)+import Control.Monad.Trans.Writer.Strict (execWriterT, tell)+import Data.List.NonEmpty                (NonEmpty (..))+import Data.Monoid                       (Endo (..))+import Data.Semigroup                    (Max (..))+import Data.Sequence                     (ViewL (..))+import Data.Set                          (Set)+import Data.Text                         (Text)+import Data.Typeable                     (Typeable)+import Data.Void                         (Void, absurd)+import Dhall.Context                     (Context)+import Dhall.Eval+    ( Environment (..)+    , Names (..)+    , Val (..)+    , (~>)+    )+import Dhall.Pretty                      (Ann, UnescapedLabel (..))+import Dhall.Src                         (Src)+import Lens.Micro                        (anyOf, over)+import Prettyprinter                     (Doc, Pretty (..), vsep)++import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , Expr (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Foldable               as Foldable+import qualified Data.Foldable.WithIndex     as Foldable.WithIndex+import qualified Data.List.NonEmpty          as NonEmpty+import qualified Data.Map+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text                   as Text+import qualified Data.Traversable+import qualified Dhall.Context+import qualified Dhall.Core+import qualified Dhall.Diff+import qualified Dhall.Eval                  as Eval+import qualified Dhall.Map+import qualified Dhall.Pretty+import qualified Dhall.Pretty.Internal+import qualified Dhall.Syntax                as Syntax+import qualified Dhall.Util+import qualified Prettyprinter               as Pretty+import qualified Prettyprinter.Render.String as Pretty++{-| A type synonym for `Void`++    This is provided for backwards compatibility, since Dhall used to use its+    own `X` type instead of @"Data.Void".`Void`@.  You should use `Void` instead+    of `X` now+-}+type X = Void+{-# DEPRECATED X "Use Data.Void.Void instead" #-}++axiom :: Const -> Either (TypeError s a) Const+axiom Type = return Kind+axiom Kind = return Sort+axiom Sort = Left (TypeError Dhall.Context.empty (Const Sort) Untyped)++rule :: Const -> Const -> Const+rule Type Type = Type+rule Kind Type = Type+rule Sort Type = Type+rule Type Kind = Kind+rule Kind Kind = Kind+rule Sort Kind = Sort+rule Type Sort = Sort+rule Kind Sort = Sort+rule Sort Sort = Sort++{-| Type-check an expression and return the expression's type if type-checking+    succeeds or an error if type-checking fails++    `typeWith` does not necessarily normalize the type since full normalization+    is not necessary for just type-checking.  If you actually care about the+    returned type then you may want to `Dhall.Core.normalize` it afterwards.++    The supplied `Context` records the types of the names in scope. If+    these are ill-typed, the return value may be ill-typed.+-}+typeWith :: Context (Expr s X) -> Expr s X -> Either (TypeError s X) (Expr s X)+typeWith ctx expr = do+    checkContext ctx+    typeWithA absurd ctx expr++{-| Function that converts the value inside an `Embed` constructor into a new+    expression+-}+type Typer a = forall s. a -> Expr s a++{-| Generalization of `typeWith` that allows type-checking the `Embed`+    constructor with custom logic+-}+typeWithA+    :: (Eq a, Pretty a)+    => Typer a+    -> Context (Expr s a)+    -> Expr s a+    -> Either (TypeError s a) (Expr s a)+typeWithA tpa context expression =+    fmap (Dhall.Core.renote . Eval.quote EmptyNames) (infer tpa ctx expression)+  where+    ctx = contextToCtx context++contextToCtx :: Eq a => Context (Expr s a) -> Ctx a+contextToCtx context = loop (Dhall.Context.toList context)+  where+    loop [] =+        Ctx Empty TypesEmpty++    loop ((x, t):rest) =+        Ctx (Skip vs x) (TypesBind ts x (Eval.eval vs (Dhall.Core.denote t)))+      where+        Ctx vs ts = loop rest++ctxToContext :: Eq a => Ctx a -> Context (Expr s a)+ctxToContext (Ctx {..}) = loop types+  where+    loop (TypesBind ts x t) = Dhall.Context.insert x t' (loop ts)+      where+        ns = typesToNames ts++        t' = Dhall.Core.renote (Eval.quote ns t)+    loop TypesEmpty = Dhall.Context.empty++typesToNames :: Types a -> Names+typesToNames (TypesBind ts x _) = Bind ns x+  where+    ns = typesToNames ts+typesToNames TypesEmpty = EmptyNames++data Types a = TypesEmpty | TypesBind !(Types a) {-# UNPACK #-} !Text (Val a)++data Ctx a = Ctx { values :: !(Environment a), types :: !(Types a) }++addType :: Text -> Val a -> Ctx a -> Ctx a+addType x t (Ctx vs ts) = Ctx (Skip vs x) (TypesBind ts x t)++addTypeValue :: Text -> Val a -> Val a -> Ctx a -> Ctx a+addTypeValue x t v (Ctx vs ts) = Ctx (Extend vs x v) (TypesBind ts x t)++fresh :: Ctx a -> Text -> Val a+fresh Ctx{..} x = VVar x (Eval.countNames x (Eval.envNames values))++{-| `typeWithA` is implemented internally in terms of @infer@ in order to speed+    up equivalence checking.++    Specifically, we extend the `Context` to become a @Ctx@, which can store+    the entire contents of a `let` expression (i.e. the type *and* the value+    of the bound variable).  By storing this extra information in the @Ctx@ we+    no longer need to substitute `let` expressions at all (which is very+    expensive!).++    However, this means that we need to use `Dhall.Eval.conv` to perform+    equivalence checking instead of `Dhall.Core.judgmentallyEqual` since+    only `Dhall.Core.judgmentallyEqual` is unable to use the information stored+    in the extended context for accurate equivalence checking.+-}+infer+    :: forall a s+    .  (Eq a, Pretty a)+    => Typer a+    -> Ctx a+    -> Expr s a+    -> Either (TypeError s a) (Val a)+infer typer = loop+  where+    {- The convention for primes (i.e. `'`s) is:++       * No primes  (`x`  ): An `Expr` that has not been `eval`ed yet+       * One prime  (`x'` ): A  `Val`+       * Two primes (`x''`): An `Expr` generated from `quote`ing a `Val`+    -}+    loop :: Ctx a -> Expr s a -> Either (TypeError s a) (Val a)+    loop ctx@Ctx{..} expression = case expression of+        Const c ->+            fmap VConst (axiom c)++        Var (V x0 n0) -> do+            let go TypesEmpty _ =+                    die (UnboundVariable x0)+                go (TypesBind ts x t) n+                    | x == x0   = if n == 0 then return t else go ts (n - 1)+                    | otherwise = go ts n++            go types n0++        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b -> do+            tA' <- loop ctx _A++            case tA' of+                VConst _ -> return ()+                _        -> die (InvalidInputType _A)++            let _A' = eval values _A++            let ctx' = addType x _A' ctx++            _B' <- loop ctx' b++            let _B'' = quote (Bind (Eval.envNames values) x) _B'++            tB' <- loop ctx' (Dhall.Core.renote _B'')++            case tB' of+                VConst _ -> return ()+                _        -> die (InvalidOutputType _B'')++            return (VHPi x _A' (\u -> Eval.eval (Extend values x u) _B''))++        Pi _ x _A _B -> do+            tA' <- loop ctx _A++            kA <- case tA' of+                VConst kA -> return kA+                _         -> die (InvalidInputType _A)++            let _A' = eval values _A++            let ctx' = addType x _A' ctx++            tB' <- loop ctx' _B++            kB <- case tB' of+                VConst kB -> return kB+                _         -> die (InvalidOutputType _B)++            return (VConst (rule kA kB))++        App f a -> do+            tf' <- loop ctx f++            case Eval.toVHPi tf' of+                Just (_x, _A₀', _B') -> do+                    _A₁' <- loop ctx a++                    if Eval.conv values _A₀' _A₁'+                        then do+                            let a' = eval values a++                            return (_B' a')++                        else do+                            let _A₀'' = quote names _A₀'+                            let _A₁'' = quote names _A₁'+                            die (TypeMismatch f _A₀'' a _A₁'')+                Nothing ->+                    die (NotAFunction f (quote names tf'))++        Let (Binding { value = a₀, variable = x, ..}) body -> do+            let a₀' = eval values a₀++            ctxNew <- case annotation of+                Nothing -> do+                    _A' <- loop ctx a₀++                    return (addTypeValue x _A' a₀' ctx)+                Just (_, _A₀) -> do+                    _ <- loop ctx _A₀++                    let _A₀' = eval values _A₀++                    _A₁' <- loop ctx a₀++                    if Eval.conv values _A₀' _A₁'+                        then+                            return ()++                        else do+                            let _A₀'' = quote names _A₀'+                            let _A₁'' = quote names _A₁'+                            Left (TypeError context a₀ (AnnotMismatch a₀ _A₀'' _A₁''))++                    return (addTypeValue x _A₀' a₀' ctx)++            loop ctxNew body++        Annot t _T₀ -> do+            case Dhall.Core.denote _T₀ of+                Const _ -> return ()+                _       -> do+                    _ <- loop ctx _T₀++                    return ()++            let _T₀' = eval values _T₀++            _T₁' <- loop ctx t++            if Eval.conv values _T₀' _T₁'+                then+                    return _T₁'++                else do+                    let _T₀'' = quote names _T₀'+                    let _T₁'' = quote names _T₁'+                    die (AnnotMismatch t _T₀'' _T₁'')++        Bool ->+            return (VConst Type)++        BoolLit _ ->+            return VBool++        BoolAnd l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantAnd l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantAnd r (quote names tr'))++            return VBool++        BoolOr l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantOr l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantOr r (quote names tr'))++            return VBool++        BoolEQ l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantEQ l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantEQ r (quote names tr'))++            return VBool++        BoolNE l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantNE l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantNE r (quote names tr'))++            return VBool++        BoolIf t l r -> do+            tt' <- loop ctx t++            case tt' of+                VBool -> return ()+                _     -> die (InvalidPredicate t (quote names tt'))++            _L' <- loop ctx l++            _R' <- loop ctx r++            _ <- loop ctx (quote names _L')++            let _L'' = quote names _L'++            _ <- loop ctx (quote names _R')++            let _R'' = quote names _R'++            if Eval.conv values _L' _R'+                then return ()+                else die (IfBranchMismatch l r _L'' _R'')++            return _L'++        Bytes ->+            return (VConst Type)++        BytesLit _ ->+            return VBytes++        Natural ->+            return (VConst Type)++        NaturalLit _ ->+            return VNatural++        NaturalFold ->+            return+                (   VNatural+                ~>  VHPi "natural" (VConst Type) (\natural ->+                        VHPi "succ" (natural ~> natural) (\_succ ->+                            VHPi "zero" natural (\_zero ->+                                natural+                            )+                        )+                    )+                )++        NaturalBuild ->+            return+                (   VHPi "natural" (VConst Type) (\natural ->+                        VHPi "succ" (natural ~> natural) (\_succ ->+                            VHPi "zero" natural (\_zero ->+                                natural+                            )+                        )+                    )+                ~>  VNatural+                )++        NaturalIsZero ->+            return (VNatural ~> VBool)++        NaturalEven ->+            return (VNatural ~> VBool)++        NaturalOdd ->+            return (VNatural ~> VBool)++        NaturalToInteger ->+            return (VNatural ~> VInteger)++        NaturalShow ->+            return (VNatural ~> VText)++        NaturalSubtract ->+            return (VNatural ~> VNatural ~> VNatural)++        NaturalPlus l r -> do+            tl' <- loop ctx l++            case tl' of+                VNatural -> return ()+                _        -> die (CantAdd l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VNatural -> return ()+                _        -> die (CantAdd r (quote names tr'))++            return VNatural++        NaturalTimes l r -> do+            tl' <- loop ctx l++            case tl' of+                VNatural -> return ()+                _        -> die (CantMultiply l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VNatural -> return ()+                _        -> die (CantMultiply r (quote names tr'))++            return VNatural++        Integer ->+            return (VConst Type)++        IntegerLit _ ->+            return VInteger++        IntegerClamp ->+            return (VInteger ~> VNatural)++        IntegerNegate ->+            return (VInteger ~> VInteger)++        IntegerShow ->+            return (VInteger ~> VText)++        IntegerToDouble ->+            return (VInteger ~> VDouble)++        Double ->+            return (VConst Type)++        DoubleLit _ ->+            return VDouble++        DoubleShow ->+            return (VDouble ~> VText)++        Text ->+            return (VConst Type)++        TextLit (Chunks xys _) -> do+            let process (_, y) = do+                    _Y' <- loop ctx y++                    case _Y' of+                        VText -> return ()+                        _     -> die (CantInterpolate y (quote names _Y'))++            mapM_ process xys++            return VText++        TextAppend l r -> do+            tl' <- loop ctx l++            case tl' of+                VText -> return ()+                _     -> die (CantTextAppend l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VText -> return ()+                _     -> die (CantTextAppend r (quote names tr'))++            return VText++        TextReplace ->+            return+                (   VHPi "needle" VText  (\_needle ->+                        VHPi "replacement" VText (\_replacement ->+                            VHPi "haystack" VText (\_haystack ->+                                VText+                            )+                        )+                    )+                )+        TextShow ->+            return (VText ~> VText)++        Date ->+            return (VConst Type)++        DateLiteral _ ->+            return VDate++        DateShow ->+            return (VDate ~> VText)++        Time ->+            return (VConst Type)++        TimeLiteral _ _ ->+            return VTime++        TimeShow ->+            return (VTime ~> VText)++        TimeZone ->+            return (VConst Type)++        TimeZoneLiteral _ ->+            return VTimeZone++        TimeZoneShow ->+            return (VTimeZone ~> VText)++        List ->+            return (VConst Type ~> VConst Type)++        ListLit Nothing ts₀ ->+            case Data.Sequence.viewl ts₀ of+                t₀ :< ts₁ -> do+                    _T₀' <- loop ctx t₀++                    let _T₀'' = quote names _T₀'++                    tT₀' <- loop ctx _T₀''++                    case tT₀' of+                        VConst Type -> return ()+                        _           -> die (InvalidListType (App List _T₀''))++                    let process i t₁ = do+                            _T₁' <- loop ctx t₁++                            if Eval.conv values _T₀' _T₁'+                                then+                                    return ()++                                else do+                                    let _T₀'' = quote names _T₀'+                                    let _T₁'' = quote names _T₁'++                                    -- Carefully note that we don't use `die`+                                    -- here so that the source span is narrowed+                                    -- to just the offending element+                                    let err = MismatchedListElements (i+1) _T₀'' t₁ _T₁''++                                    Left (TypeError context t₁ err)++                    Foldable.WithIndex.itraverse_ process ts₁++                    return (VList _T₀')++                _ ->+                    die MissingListType++        ListLit (Just _T₀) ts ->+            if Data.Sequence.null ts+                then do+                    _ <- loop ctx _T₀++                    let _T₀' = eval values _T₀++                    let _T₀'' = quote names _T₀'++                    case _T₀' of+                        VList _ -> return _T₀'+                        _       -> die (InvalidListType _T₀'')++                -- See https://github.com/dhall-lang/dhall-haskell/issues/1359.+                else die ListLitInvariant++        ListAppend x y -> do+            tx' <- loop ctx x++            _A₀' <- case tx' of+                VList _A₀' -> return _A₀'+                _          -> die (CantListAppend x (quote names tx'))++            ty' <- loop ctx y++            _A₁' <- case ty' of+                VList _A₁' -> return _A₁'+                _          -> die (CantListAppend y (quote names ty'))++            if Eval.conv values _A₀' _A₁'+                then return ()+                else do+                    let _A₀'' = quote names _A₀'+                    let _A₁'' = quote names _A₁'+                    die (ListAppendMismatch _A₀'' _A₁'')++            return (VList _A₀')++        ListBuild ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VHPi "list" (VConst Type) (\list ->+                                VHPi "cons" (a ~> list ~> list) (\_cons ->+                                    (VHPi "nil" list (\_nil -> list))+                                )+                            )+                        ~>  VList a+                    )+                )++        ListFold ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VList a+                        ~>  VHPi "list" (VConst Type) (\list ->+                                VHPi "cons" (a ~> list ~> list) (\_cons ->+                                    (VHPi "nil" list (\_nil -> list))+                                )+                            )+                    )+                )++        ListLength ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VNatural))++        ListHead ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))++        ListLast ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))++        ListIndexed ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VList a+                        ~>  VList+                                (VRecord+                                    (Dhall.Map.unorderedFromList+                                        [ ("index", VNatural)+                                        , ("value", a       )+                                        ]+                                    )+                                )+                    )+                )+        ListReverse ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VList a))++        Optional ->+            return (VConst Type ~> VConst Type)++        None ->+            return (VHPi "A" (VConst Type) (\_A -> VOptional _A))++        Some a -> do+            _A' <- loop ctx a++            tA' <- loop ctx (quote names _A')++            case tA' of+                VConst Type -> return ()+                _           -> do+                   let _A'' = quote names _A'+                   let tA'' = quote names tA'++                   die (InvalidSome a _A'' tA'')++            return (VOptional _A')++        Record xTs -> do+            let process x (RecordField {recordFieldValue = _T}) = do+                    tT' <- lift (loop ctx _T)++                    case tT' of+                        VConst c -> tell (Max c)+                        _        -> lift (die (InvalidFieldType x _T))++            Max c <- execWriterT (Dhall.Map.unorderedTraverseWithKey_ process xTs)++            return (VConst c)++        RecordLit xts -> do+            let process t = do+                    _T' <- loop ctx $ recordFieldValue t++                    let _T'' = quote names _T'++                    _ <- loop ctx _T''++                    return _T'++            xTs <- traverse process (Dhall.Map.sort xts)++            return (VRecord xTs)++        Union xTs -> do+            let process _ Nothing =+                    return mempty++                process x₁ (Just _T₁) = do+                    tT₁' <- loop ctx _T₁++                    case tT₁' of+                        VConst c -> return (Max c)+                        _        -> die (InvalidAlternativeType x₁ _T₁)++            Max c <- fmap Foldable.fold (Dhall.Map.unorderedTraverseWithKey process xTs)+            return (VConst c)+        Combine _ mk l r -> do+            _L' <- loop ctx l++            let l'' = quote names (eval values l)++            _R' <- loop ctx r++            let r'' = quote names (eval values r)++            xLs' <- case _L' of+                VRecord xLs' ->+                    return xLs'++                _ -> do+                    let _L'' = quote names _L'++                    case mk of+                        Nothing -> die (MustCombineARecord '∧' l'' _L'')+                        Just t  -> die (InvalidDuplicateField t l _L'')++            xRs' <- case _R' of+                VRecord xRs' ->+                    return xRs'++                _ -> do+                    let _R'' = quote names _R'++                    case mk of+                        Nothing -> die (MustCombineARecord '∧' r'' _R'')+                        Just t  -> die (InvalidDuplicateField t r _R'')++            let combineTypes xs xLs₀' xRs₀' = do+                    let combine x (VRecord xLs₁') (VRecord xRs₁') =+                            combineTypes (x : xs) xLs₁' xRs₁'++                        combine x _ _ =+                            case mk of+                                Nothing -> die (FieldCollision (NonEmpty.reverse (x :| xs)))+                                Just t  -> die (DuplicateFieldCannotBeMerged (t :| reverse (x : xs)))++                    let xEs =+                            Dhall.Map.outerJoin Right Right combine xLs₀' xRs₀'++                    xTs <- Dhall.Map.unorderedTraverseWithKey (\_x _E -> _E) xEs++                    return (VRecord xTs)++            combineTypes [] xLs' xRs'++        CombineTypes _ l r -> do+            _L' <- loop ctx l++            let l' = eval values l++            let l'' = quote names l'++            cL <- case _L' of+                VConst cL -> return cL+                _         -> die (CombineTypesRequiresRecordType l l'')++            _R' <- loop ctx r++            let r' = eval values r++            let r'' = quote names r'++            cR <- case _R' of+                VConst cR -> return cR+                _         -> die (CombineTypesRequiresRecordType r r'')++            let c = max cL cR++            xLs' <- case l' of+                VRecord xLs' -> return xLs'+                _            -> die (CombineTypesRequiresRecordType l l'')++            xRs' <- case r' of+                VRecord xRs' -> return xRs'+                _            -> die (CombineTypesRequiresRecordType r r'')++            let combineTypes xs xLs₀' xRs₀' = do+                    let combine x (VRecord xLs₁') (VRecord xRs₁') =+                            combineTypes (x : xs) xLs₁' xRs₁'++                        combine x _ _ =+                            die (FieldTypeCollision (NonEmpty.reverse (x :| xs)))++                    let mL = Dhall.Map.toMap xLs₀'+                    let mR = Dhall.Map.toMap xRs₀'++                    Foldable.sequence_ (Data.Map.intersectionWithKey combine mL mR)++            combineTypes [] xLs' xRs'++            return (VConst c)++        Prefer _ _ l r -> do+            _L' <- loop ctx l++            _R' <- loop ctx r++            xLs' <- case _L' of+                VRecord xLs' -> return xLs'++                _            -> do+                    let _L'' = quote names _L'++                    let l'' = quote names (eval values l)++                    die (MustCombineARecord '⫽' l'' _L'')++            xRs' <- case _R' of+                VRecord xRs' -> return xRs'++                _            -> do+                    let _R'' = quote names _R'++                    let r'' = quote names (eval values r)++                    die (MustCombineARecord '⫽' r'' _R'')++            return (VRecord (Dhall.Map.union xRs' xLs'))++        RecordCompletion l r -> do+            _L' <- loop ctx l++            case _L' of+                VRecord xLs'+                  | not (Dhall.Map.member "default" xLs')+                     -> die (InvalidRecordCompletion "default" l)+                  | not (Dhall.Map.member "Type" xLs')+                     -> die (InvalidRecordCompletion "Type" l)+                  | otherwise+                     -> loop ctx (Annot (Prefer mempty PreferFromCompletion (Field l def) r) (Field l typ))+                _ -> die (CompletionSchemaMustBeARecord l (quote names _L'))++              where+                def = Syntax.makeFieldSelection "default"+                typ = Syntax.makeFieldSelection "Type"+        Merge t u mT₁ -> do+            _T' <- loop ctx t++            yTs' <- case _T' of+                VRecord yTs' ->+                    return yTs'++                _ -> do+                    let _T'' = quote names _T'++                    die (MustMergeARecord t _T'')++            _U' <- loop ctx u++            yUs' <- case _U' of+                VUnion yUs' ->+                    return yUs'++                VOptional _O' ->+                    -- This is a bit of hack, but it allows us to reuse the+                    -- rather complex type-matching logic for Optionals.+                    return (Dhall.Map.unorderedFromList [("None", Nothing), ("Some", Just _O')])++                _ -> do+                    let _U'' = quote names _U'++                    die (MustMergeUnionOrOptional u _U'')++            let ysT = Dhall.Map.keysSet yTs'+            let ysU = Dhall.Map.keysSet yUs'++            let diffT = Data.Set.difference ysT ysU+            let diffU = Data.Set.difference ysU ysT++            if Data.Set.null diffT+                then return ()+                else die (UnusedHandler diffT)++            if Data.Set.null diffU+                then return ()+                else let (exemplar,rest) = Data.Set.deleteFindMin diffU+                     in die (MissingHandler exemplar rest)++            let match _y _T₀' Nothing =+                    return _T₀'++                match y handler' (Just _A₁') =+                    case Eval.toVHPi handler' of+                        Just (x, _A₀', _T₀') ->+                            if Eval.conv values _A₀' _A₁'+                                then do+                                    let _T₁' = _T₀' (fresh ctx x)++                                    let _T₁'' = quote names _T₁'++                                    -- x appearing in _T₁'' would indicate a disallowed+                                    -- handler type (see+                                    -- https://github.com/dhall-lang/dhall-lang/issues/749).+                                    --+                                    -- If x appears in _T₁'', quote will have given it index+                                    -- -1. Any well-typed variable has a non-negative index,+                                    -- so we can simply look for negative indices to detect x.+                                    let containsBadVar (Var (V _ n)) =+                                            n < 0++                                        containsBadVar e =+                                            anyOf+                                                Dhall.Core.subExpressions+                                                containsBadVar+                                                e++                                    if containsBadVar _T₁''+                                        then do+                                            let handler'' = quote names handler'++                                            let outputType = Dhall.Core.shift 1 (V x (-1)) _T₁''++                                            die (DisallowedHandlerType y handler'' outputType x)++                                        else return _T₁'++                                else do+                                    let _A₀'' = quote names _A₀'+                                    let _A₁'' = quote names _A₁'++                                    die (HandlerInputTypeMismatch y _A₁'' _A₀'')++                        Nothing -> do+                            let handler'' = quote names handler'++                            die (HandlerNotAFunction y handler'')++            matched <-+                sequence+                    (Data.Map.intersectionWithKey match (Dhall.Map.toMap yTs') (Dhall.Map.toMap yUs'))++            let checkMatched :: Data.Map.Map Text (Val a) -> Either (TypeError s a) (Maybe (Val a))+                checkMatched = fmap (fmap snd) . Foldable.foldlM go Nothing . Data.Map.toList+                  where+                    go Nothing (y₁, _T₁') =+                        return (Just (y₁, _T₁'))++                    go yT₀'@(Just (y₀, _T₀')) (y₁, _T₁') =+                        if Eval.conv values _T₀' _T₁'+                            then return yT₀'++                            else do+                                let _T₀'' = quote names _T₀'+                                let _T₁'' = quote names _T₁'+                                die (HandlerOutputTypeMismatch y₀ _T₀'' y₁ _T₁'')++            mT₀' <- checkMatched matched++            mT₁' <- Data.Traversable.for mT₁ $ \_T₁ -> do+                _ <- loop ctx _T₁++                return (eval values _T₁)++            case (mT₀', mT₁') of+                (Nothing, Nothing) ->+                    die MissingMergeType+                (Nothing, Just _T₁') ->+                    return _T₁'+                (Just _T₀', Nothing) ->+                    return _T₀'+                (Just _T₀', Just _T₁') ->+                    if Eval.conv values _T₀' _T₁'+                        then return _T₀'++                        else do+                            let _T₀'' = quote names _T₀'+                            let _T₁'' = quote names _T₁'+                            die (AnnotMismatch (Merge t u Nothing) _T₁'' _T₀'')++        ToMap e mT₁ -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            xTs' <- case _E' of+                VRecord xTs' -> return xTs'+                _            -> die (MustMapARecord e _E'')++            tE' <- loop ctx _E''++            let tE'' = quote names tE'++            case tE' of+                VConst Type -> return ()+                _           -> die (InvalidToMapRecordKind _E'' tE'')++            Foldable.traverse_ (loop ctx) mT₁++            let compareFieldTypes _T₀' Nothing =+                    Just (Right _T₀')++                compareFieldTypes _T₀' r@(Just (Right _T₁'))+                    | Eval.conv values _T₀' _T₁' = r+                    | otherwise = do+                        let _T₀'' = quote names _T₀'+                        let _T₁'' = quote names _T₁'++                        Just (die (HeterogenousRecordToMap _E'' _T₀'' _T₁''))++                compareFieldTypes _T₀' r@(Just (Left _)) =+                    r++            let r = appEndo (foldMap (Endo . compareFieldTypes) xTs') Nothing++            let mT₁' = fmap (eval values) mT₁++            let mapType _T' =+                    VList+                        (VRecord+                            (Dhall.Map.unorderedFromList+                                [("mapKey", VText), ("mapValue", _T')]+                            )+                        )++            case (r, mT₁') of+                (Nothing, Nothing) ->+                    die MissingToMapType+                (Just err@(Left _), _) ->+                    err+                (Just (Right _T'), Nothing) ->+                    pure (mapType _T')+                (Nothing, Just _T₁'@(VList (VRecord itemTypes)))+                   | Just _T' <- Dhall.Map.lookup "mapValue" itemTypes+                   , Eval.conv values (mapType _T') _T₁' ->+                       pure _T₁'+                (Nothing, Just _T₁') -> do+                    let _T₁'' = quote names _T₁'++                    die (InvalidToMapType _T₁'')+                (Just (Right _T'), Just _T₁')+                   | Eval.conv values (mapType _T') _T₁' ->+                       pure (mapType _T')+                   | otherwise -> do+                       let _T₁'' = quote names _T₁'++                       die (MapTypeMismatch (quote names (mapType _T')) _T₁'')++        ShowConstructor e -> do+            _E' <- loop ctx e+            case _E' of+              VUnion _ -> pure VText+              VOptional _ -> pure VText++              _ -> die ShowConstructorNotOnUnion++        Field e (Syntax.fieldSelectionLabel -> x) -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xTs' ->+                    case Dhall.Map.lookup x xTs' of+                        Just _T' -> return _T'+                        Nothing  -> die (MissingField x _E'')+                _ -> do+                    let e' = eval values e++                    let e'' = quote names e'++                    case e' of+                        VUnion xTs' ->+                            case Dhall.Map.lookup x xTs' of+                                Just (Just _T') -> return (VHPi x _T' (\_ -> e'))+                                Just  Nothing   -> return e'+                                Nothing         -> die (MissingConstructor x e)++                        _ -> do+                            let text = Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabel x)++                            die (CantAccess text e'' _E'')+        Project e (Left xs) -> do+            case duplicateElement xs of+                Just x -> do+                    die (DuplicateProjectionLabel x)+                Nothing -> do+                    return ()++            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xTs' -> do+                    let process x =+                            case Dhall.Map.lookup x xTs' of+                                Just _T' -> return (x, _T')+                                Nothing  -> die (MissingField x _E'')++                    let adapt = VRecord . Dhall.Map.unorderedFromList++                    fmap adapt (traverse process xs)++                _ -> do+                    let text =+                            Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabels xs)++                    die (CantProject text e _E'')++        Project e (Right s) -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xEs' -> do+                    _ <- loop ctx s++                    let s' = eval values s++                    case s' of+                        VRecord xSs' -> do+                            let actualSubset =+                                    quote names (VRecord (Dhall.Map.intersection xEs' xSs'))++                            let expectedSubset = s++                            let process x _S' = do+                                    let _S'' = quote names _S'++                                    case Dhall.Map.lookup x xEs' of+                                        Nothing ->+                                            die (MissingField x _E'')++                                        Just _E' ->+                                            if Eval.conv values _E' _S'+                                                then return ()+                                                else die (ProjectionTypeMismatch x _E'' _S'' expectedSubset actualSubset)++                            Dhall.Map.unorderedTraverseWithKey_ process xSs'++                            return s'++                        _ ->+                            die (CantProjectByExpression s)++                _ -> do+                    let text = Dhall.Core.pretty s++                    die (CantProject text e s)++        Assert _T -> do+            _ <- loop ctx _T++            let _T' = eval values _T++            case _T' of+                VEquivalent x' y' -> do+                    let x'' = quote names x'+                    let y'' = quote names y'++                    if Eval.conv values x' y'+                        then return _T'+                        else die (AssertionFailed x'' y'')++                _ ->+                    die (NotAnEquivalence _T)++        Equivalent _ x y -> do+            _A₀' <- loop ctx x++            let _A₀'' = quote names _A₀'++            tA₀' <- loop ctx _A₀''++            case tA₀' of+                VConst Type -> return ()+                _          -> die (IncomparableExpression x)++            _A₁' <- loop ctx y++            let _A₁'' = quote names _A₁'++            tA₁' <- loop ctx _A₁''++            case tA₁' of+                VConst Type -> return ()+                _           -> die (IncomparableExpression y)++            if Eval.conv values _A₀' _A₁'+                then return ()+                else die (EquivalenceTypeMismatch x _A₀'' y _A₁'')++            return (VConst Type)++        With e₀ ks₀ v₀ -> do+            tE₀' <- loop ctx e₀++            -- The purpose of this inner loop is to ensure that we only need to+            -- typecheck the record once++            let with tE' ks v = case tE' of+                  VRecord kTs' ->+                    case ks of+                      WithLabel k :| [] -> do+                          tV' <- loop ctx v++                          return (VRecord (Dhall.Map.insert k tV' kTs'))+                      WithLabel k₀ :| k₁ : ks' -> do+                          let _T =+                                  case Dhall.Map.lookup k₀ kTs' of+                                      Just _T' -> _T'+                                      Nothing  -> VRecord mempty++                          tV' <- with _T (k₁ :| ks') v++                          return (VRecord (Dhall.Map.insert k₀ tV' kTs'))+                      WithQuestion :| _ -> do+                          die NotALabelPath++                  VOptional _O' -> do+                    case ks of++                        -- (Some x) with ? = v is valid iff the type of x is the same as the type of v.+                      WithQuestion :| [] -> do+                        tV' <- loop ctx v+                        if Eval.conv values _O' tV'+                          then return (VOptional _O')+                          else die OptionalWithTypeMismatch++                        -- (Some x) with ?.a.b = v is valid iff the type of x.a.b is the same as the type of v.+                      WithQuestion :| k₁ : ks' -> do+                        tV' <- with _O' (k₁ :| ks') v+                        if Eval.conv values _O' tV'+                          then return (VOptional _O')+                          else die OptionalWithTypeMismatch++                      WithLabel k :| _ -> die (NotAQuestionPath k)++                  _ -> die (NotWithARecord e₀ (quote names tE')) -- TODO: NotWithARecordOrOptional++            with tE₀' ks₀ v₀++        Note s e ->+            case loop ctx e of+                Left (TypeError ctx' (Note s' e') m) ->+                    Left (TypeError ctx' (Note s' e') m)+                Left (TypeError ctx'          e'  m) ->+                    Left (TypeError ctx' (Note s  e') m)+                Right r ->+                    Right r++        ImportAlt l _r ->+            loop ctx l++        Embed p ->+            return (eval values (typer p))+      where+        die err = Left (TypeError context expression err)++        context = ctxToContext ctx++        names = typesToNames types++        eval vs e = Eval.eval vs (Dhall.Core.denote e)++        quote ns value = Dhall.Core.renote (Eval.quote ns value)++{-| `typeOf` is the same as `typeWith` with an empty context, meaning that the+    expression must be closed (i.e. no free variables), otherwise type-checking+    will fail.+-}+typeOf :: Expr s X -> Either (TypeError s X) (Expr s X)+typeOf = typeWith Dhall.Context.empty++-- | The specific type error+data TypeMessage s a+    = UnboundVariable Text+    | InvalidInputType (Expr s a)+    | InvalidOutputType (Expr s a)+    | NotAFunction (Expr s a) (Expr s a)+    | TypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | AnnotMismatch (Expr s a) (Expr s a) (Expr s a)+    | Untyped+    | MissingListType+    | MismatchedListElements Int (Expr s a) (Expr s a) (Expr s a)+    | InvalidListType (Expr s a)+    | ListLitInvariant+    | InvalidSome (Expr s a) (Expr s a) (Expr s a)+    | InvalidPredicate (Expr s a) (Expr s a)+    | IfBranchMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | InvalidFieldType Text (Expr s a)+    | InvalidAlternativeType Text (Expr s a)+    | ListAppendMismatch (Expr s a) (Expr s a)+    | MustCombineARecord Char (Expr s a) (Expr s a)+    | InvalidDuplicateField Text (Expr s a) (Expr s a)+    | InvalidRecordCompletion Text (Expr s a)+    | CompletionSchemaMustBeARecord (Expr s a) (Expr s a)+    | CombineTypesRequiresRecordType (Expr s a) (Expr s a)+    | DuplicateFieldCannotBeMerged (NonEmpty Text)+    | FieldCollision (NonEmpty Text)+    | FieldTypeCollision (NonEmpty Text)+    | MustMergeARecord (Expr s a) (Expr s a)+    | MustMergeUnionOrOptional (Expr s a) (Expr s a)+    | MustMapARecord (Expr s a) (Expr s a)+    | InvalidToMapRecordKind (Expr s a) (Expr s a)+    | HeterogenousRecordToMap (Expr s a) (Expr s a) (Expr s a)+    | InvalidToMapType (Expr s a)+    | MapTypeMismatch (Expr s a) (Expr s a)+    | MissingToMapType+    | UnusedHandler (Set Text)+    | MissingHandler Text (Set Text)+    | HandlerInputTypeMismatch Text (Expr s a) (Expr s a)+    | DisallowedHandlerType Text (Expr s a) (Expr s a) Text+    | HandlerOutputTypeMismatch Text (Expr s a) Text (Expr s a)+    | MissingMergeType+    | HandlerNotAFunction Text (Expr s a)+    | CantAccess Text (Expr s a) (Expr s a)+    | CantProject Text (Expr s a) (Expr s a)+    | CantProjectByExpression (Expr s a)+    | DuplicateProjectionLabel Text+    | MissingField Text (Expr s a)+    | MissingConstructor Text (Expr s a)+    | ProjectionTypeMismatch Text (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | AssertionFailed (Expr s a) (Expr s a)+    | NotAnEquivalence (Expr s a)+    | IncomparableExpression (Expr s a)+    | EquivalenceTypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | NotWithARecord (Expr s a) (Expr s a)+    | CantAnd (Expr s a) (Expr s a)+    | CantOr (Expr s a) (Expr s a)+    | CantEQ (Expr s a) (Expr s a)+    | CantNE (Expr s a) (Expr s a)+    | CantInterpolate (Expr s a) (Expr s a)+    | CantTextAppend (Expr s a) (Expr s a)+    | CantListAppend (Expr s a) (Expr s a)+    | CantAdd (Expr s a) (Expr s a)+    | CantMultiply (Expr s a) (Expr s a)+    | OptionalWithTypeMismatch+    | NotALabelPath+    | NotAQuestionPath Text+    | ShowConstructorNotOnUnion+    deriving (Show)++formatHints :: [Doc Ann] -> Doc Ann+formatHints hints = vsep (map format hints)+  where+    format hint = "\n\n\ESC[1;33mHint\ESC[0m: " <> hint++shortTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann+shortTypeMessage msg =+    "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n"+  where+    ErrorMessages {..} = prettyTypeMessage msg++longTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann+longTypeMessage msg =+        "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n"+    <>  "\n"+    <>  long+  where+    ErrorMessages {..} = prettyTypeMessage msg++{-| Output of `prettyTypeMessage`, containing short- and long-form error+    messages+-}+data ErrorMessages = ErrorMessages+    { short :: Doc Ann+    -- ^ Default succinct 1-line explanation of what went wrong+    , hints :: [Doc Ann]+    -- ^ Possibly-empty hints based on specific types involved in the error+    , long  :: Doc Ann+    -- ^ Longer and more detailed explanation of the error+    }++_NOT :: Doc ann+_NOT = "\ESC[1mnot\ESC[0m"++insert :: Pretty a => a -> Doc Ann+insert = Dhall.Util.insert++emptyRecordTypeHint :: (Eq a, Pretty a) => Expr s a -> [Doc Ann]+emptyRecordTypeHint expr =+    if Eval.judgmentallyEqual expr (Record mempty) then+        ["{} is the empty record type, use {=} for the empty record value"]+    else []++-- | Convert a `TypeMessage` to short- and long-form `ErrorMessages`+prettyTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> ErrorMessages+prettyTypeMessage (UnboundVariable x) = ErrorMessages {..}+  -- We do not need to print variable name here. For the discussion see:+  -- https://github.com/dhall-lang/dhall-haskell/pull/116+  where+    short = "Unbound variable: " <> Pretty.pretty x++    hints = []++    long =+        "Explanation: Expressions can only reference previously introduced (i.e. “bound”)\n\+        \variables that are still “in scope”                                             \n\+        \                                                                                \n\+        \For example, the following valid expressions introduce a “bound” variable named \n\+        \❰x❱:                                                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ λ(x : Bool) → x │  Anonymous functions introduce “bound” variables        \n\+        \    └─────────────────┘                                                         \n\+        \        ⇧                                                                       \n\+        \        This is the bound variable                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ let x = 1 in x  │  ❰let❱ expressions introduce “bound” variables          \n\+        \    └─────────────────┘                                                         \n\+        \          ⇧                                                                     \n\+        \          This is the bound variable                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following expressions are not valid because they all reference a   \n\+        \variable that has not been introduced yet (i.e. an “unbound” variable):         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ λ(x : Bool) → y │  The variable ❰y❱ hasn't been introduced yet            \n\+        \    └─────────────────┘                                                         \n\+        \                    ⇧                                                           \n\+        \                    This is the unbound variable                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ (let x = True in x) && x │  ❰x❱ is undefined outside the parentheses      \n\+        \    └──────────────────────────┘                                                \n\+        \                             ⇧                                                  \n\+        \                             This is the unbound variable                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ let x = x in x │  The definition for ❰x❱ cannot reference itself          \n\+        \    └────────────────┘                                                          \n\+        \              ⇧                                                                 \n\+        \              This is the unbound variable                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You misspell a variable name, like this:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────────┐                      \n\+        \    │ λ(empty : Bool) → if emty then \"Empty\" else \"Full\" │                      \n\+        \    └────────────────────────────────────────────────────┘                      \n\+        \                           ⇧                                                    \n\+        \                           Typo                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You misspell a reserved identifier, like this:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ foral (a : Type) → a → a │                                                \n\+        \    └──────────────────────────┘                                                \n\+        \      ⇧                                                                         \n\+        \      Typo                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You tried to define a recursive value, like this:                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ let x = x + 1 in x │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \              ⇧                                                                 \n\+        \              Recursive definitions are not allowed                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You accidentally forgot a ❰λ❱ or ❰∀❱/❰forall❱                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \        Unbound variable                                                        \n\+        \        ⇩                                                                       \n\+        \    ┌─────────────────┐                                                         \n\+        \    │  (x : Bool) → x │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \      ⇧                                                                         \n\+        \      A ❰λ❱ here would transform this into a valid anonymous function           \n\+        \                                                                                \n\+        \                                                                                \n\+        \        Unbound variable                                                        \n\+        \        ⇩                                                                       \n\+        \    ┌────────────────────┐                                                      \n\+        \    │  (x : Bool) → Bool │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \      ⇧                                                                         \n\+        \      A ❰∀❱ or ❰forall❱ here would transform this into a valid function type    \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You forgot to prefix a file path with ❰./❱:                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ path/to/file.dhall │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \      ⇧                                                                         \n\+        \      This should be ❰./path/to/file.dhall❱                                     \n"++prettyTypeMessage (InvalidInputType expr) = ErrorMessages {..}+  where+    short = "Invalid function input"++    hints = []++    long =+        "Explanation: A function can accept an input “term” that has a given “type”, like\n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \        This is the input term that the function accepts                        \n\+        \        ⇩                                                                       \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ ∀(x : Natural) → Bool │  This is the type of a function that accepts an   \n\+        \    └───────────────────────┘  input term named ❰x❱ that has type ❰Natural❱     \n\+        \            ⇧                                                                   \n\+        \            This is the type of the input term                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Bool → Natural │  This is the type of a function that accepts an anonymous\n\+        \    └────────────────┘  input term that has type ❰Bool❱                         \n\+        \      ⇧                                                                         \n\+        \      This is the type of the input term                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or a function can accept an input “type” that has a given “kind”, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \        This is the input type that the function accepts                        \n\+        \        ⇩                                                                       \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(a : Type) → Type │  This is the type of a function that accepts an input\n\+        \    └────────────────────┘  type named ❰a❱ that has kind ❰Type❱                 \n\+        \            ⇧                                                                   \n\+        \            This is the kind of the input type                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ (Type → Type) → Type │  This is the type of a function that accepts an    \n\+        \    └──────────────────────┘  anonymous input type that has kind ❰Type → Type❱  \n\+        \       ⇧                                                                        \n\+        \       This is the kind of the input type                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \Other function inputs are " <> _NOT <> " valid, like this:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────┐                                                            \n\+        \    │ ∀(x : 1) → x │  ❰1❱ is a “term” and not a “type” nor a “kind” so ❰x❱      \n\+        \    └──────────────┘  cannot have “type” ❰1❱ or “kind” ❰1❱                      \n\+        \            ⇧                                                                   \n\+        \            This is not a type or kind                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ True → x │  ❰True❱ is a “term” and not a “type” nor a “kind” so the       \n\+        \    └──────────┘  anonymous input cannot have “type” ❰True❱ or “kind” ❰True❱    \n\+        \      ⇧                                                                         \n\+        \      This is not a type or kind                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You annotated a function input with the following expression:                   \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is neither a type nor a kind                                          \n"+      where+        txt = insert expr++prettyTypeMessage (InvalidOutputType expr) = ErrorMessages {..}+  where+    short = "Invalid function output"++    hints = []++    long =+        "Explanation: A function can return an output “term” that has a given “type”,    \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(x : Text) → Bool │  This is the type of a function that returns an      \n\+        \    └────────────────────┘  output term that has type ❰Bool❱                    \n\+        \                    ⇧                                                           \n\+        \                    This is the type of the output term                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Bool → Natural │  This is the type of a function that returns an output   \n\+        \    └────────────────┘  term that has type ❰Natural❱                            \n\+        \             ⇧                                                                  \n\+        \             This is the type of the output term                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or a function can return an output “type” that has a given “kind”, like     \n\+        \this:                                                                           \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(a : Type) → Type │  This is the type of a function that returns an      \n\+        \    └────────────────────┘  output type that has kind ❰Type❱                    \n\+        \                    ⇧                                                           \n\+        \                    This is the kind of the output type                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ (Type → Type) → Type │  This is the type of a function that returns an    \n\+        \    └──────────────────────┘  output type that has kind ❰Type❱                  \n\+        \                      ⇧                                                         \n\+        \                      This is the kind of the output type                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \Other outputs are " <> _NOT <> " valid, like this:                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ ∀(x : Bool) → x │  ❰x❱ is a “term” and not a “type” nor a “kind” so the   \n\+        \    └─────────────────┘  output cannot have “type” ❰x❱ or “kind” ❰x❱            \n\+        \                    ⇧                                                           \n\+        \                    This is not a type or kind                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ Text → True │  ❰True❱ is a “term” and not a “type” nor a “kind” so the    \n\+        \    └─────────────┘  output cannot have “type” ❰True❱ or “kind” ❰True❱          \n\+        \             ⇧                                                                  \n\+        \             This is not a type or kind                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You use ❰∀❱ instead of ❰λ❱ by mistake, like this:                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ ∀(x: Bool) → x │                                                          \n\+        \    └────────────────┘                                                          \n\+        \      ⇧                                                                         \n\+        \      Using ❰λ❱ here instead of ❰∀❱ would transform this into a valid function  \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified that your function outputs a:                                     \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is neither a type nor a kind:                                         \n"+      where+        txt = insert expr++prettyTypeMessage (NotAFunction expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a function"++    hints = []++    long =+        "Explanation: Expressions separated by whitespace denote function application,   \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────┐                                                                     \n\+        \    │ f x │  This denotes the function ❰f❱ applied to an argument named ❰x❱     \n\+        \    └─────┘                                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \A function is a term that has type ❰a → b❱ for some ❰a❱ or ❰b❱.  For example,   \n\+        \the following expressions are all functions because they have a function type:  \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        The function's input type is ❰Bool❱                     \n\+        \                        ⇩                                                       \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(x : Bool) → x : Bool → Bool │  User-defined anonymous function          \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output type is ❰Bool❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \                     The function's input type is ❰Natural❱                     \n\+        \                     ⇩                                                          \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ Natural/even : Natural → Bool │  Built-in function                        \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output type is ❰Bool❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        The function's input kind is ❰Type❱                     \n\+        \                        ⇩                                                       \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(a : Type) → a : Type → Type │  Type-level functions are still functions \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output kind is ❰Type❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \             The function's input kind is ❰Type❱                                \n\+        \             ⇩                                                                  \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  Built-in type-level function                        \n\+        \    └────────────────────┘                                                      \n\+        \                    ⇧                                                           \n\+        \                    The function's output kind is ❰Type❱                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        Function's input has kind ❰Type❱                        \n\+        \                        ⇩                                                       \n\+        \    ┌─────────────────────────────────────────────────┐                         \n\+        \    │ List/head : ∀(a : Type) → (List a → Optional a) │  A function can return  \n\+        \    └─────────────────────────────────────────────────┘  another function       \n\+        \                                ⇧                                               \n\+        \                                Function's output has type ❰List a → Optional a❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \                       The function's input type is ❰List Text❱                 \n\+        \                       ⇩                                                        \n\+        \    ┌────────────────────────────────────────────┐                              \n\+        \    │ List/head Text : List Text → Optional Text │  A function applied to an    \n\+        \    └────────────────────────────────────────────┘  argument can be a function  \n\+        \                                   ⇧                                            \n\+        \                                   The function's output type is ❰Optional Text❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \An expression is not a function if the expression's type is not of the form     \n\+        \❰a → b❱.  For example, these are " <> _NOT <> " functions:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ 1 : Natural │  ❰1❱ is not a function because ❰Natural❱ is not the type of \n\+        \    └─────────────┘  a function                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ Natural/even 2 : Bool │  ❰Natural/even 2❱ is not a function because       \n\+        \    └───────────────────────┘  ❰Bool❱ is not the type of a function             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ List Text : Type │  ❰List Text❱ is not a function because ❰Type❱ is not   \n\+        \    └──────────────────┘  the type of a function                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to add two ❰Natural❱s without a space around the ❰+❱, like this:    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────┐                                                                     \n\+        \    │ 2+2 │                                                                     \n\+        \    └─────┘                                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \  The above code is parsed as:                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ 2 (+2) │                                                                  \n\+        \    └────────┘                                                                  \n\+        \      ⇧                                                                         \n\+        \      The compiler thinks that this ❰2❱ is a function whose argument is ❰+2❱    \n\+        \                                                                                \n\+        \                                                                                \n\+        \  This is because the ❰+❱ symbol has two meanings: you use ❰+❱ to add two       \n\+        \  numbers, but you also can prefix ❰Natural❱ literals with a ❰+❱ to turn them   \n\+        \  into ❰Integer❱ literals (like ❰+2❱)                                           \n\+        \                                                                                \n\+        \  To fix the code, you need to put spaces around the ❰+❱, like this:            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 2 + 2 │                                                                   \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to use the following expression as a function:                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but this expression's type is:                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a function type                                                \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (TypeMismatch expr0 expr1 expr2 expr3) = ErrorMessages {..}+  where+    short = "Wrong type of function argument\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3)++    hints = emptyRecordTypeHint expr2++    long =+        "Explanation: Every function declares what type or kind of argument to accept    \n\+        \                                                                                \n\+        \For example:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(x : Bool) → x : Bool → Bool │  This anonymous function only accepts     \n\+        \    └───────────────────────────────┘  arguments that have type ❰Bool❱          \n\+        \                        ⇧                                                       \n\+        \                        The function's input type                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ Natural/even : Natural → Bool │  This built-in function only accepts      \n\+        \    └───────────────────────────────┘  arguments that have type ❰Natural❱       \n\+        \                     ⇧                                                          \n\+        \                     The function's input type                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(a : Type) → a : Type → Type │  This anonymous function only accepts     \n\+        \    └───────────────────────────────┘  arguments that have kind ❰Type❱          \n\+        \                        ⇧                                                       \n\+        \                        The function's input kind                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  This built-in function only accepts arguments that  \n\+        \    └────────────────────┘  have kind ❰Type❱                                    \n\+        \             ⇧                                                                  \n\+        \             The function's input kind                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expressions are valid:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(x : Bool) → x) True │  ❰True❱ has type ❰Bool❱, which matches the type  \n\+        \    └────────────────────────┘  of argument that the anonymous function accepts \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Natural/even 2 │  ❰2❱ has type ❰Natural❱, which matches the type of       \n\+        \    └────────────────┘  argument that the ❰Natural/even❱ function accepts,      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(a : Type) → a) Bool │  ❰Bool❱ has kind ❰Type❱, which matches the kind  \n\+        \    └────────────────────────┘  of argument that the anonymous function accepts \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ List Text │  ❰Text❱ has kind ❰Type❱, which matches the kind of argument   \n\+        \    └───────────┘  that that the ❰List❱ function accepts                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you can " <> _NOT <> " apply a function to the wrong type or kind of argument\n\+        \                                                                                \n\+        \For example, the following expressions are not valid:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ (λ(x : Bool) → x) \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the anonymous function\n\+        \    └───────────────────────┘  expects an argument that has type ❰Bool❱         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ Natural/even \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the ❰Natural/even❱ function\n\+        \    └──────────────────┘  expects an argument that has type ❰Natural❱           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(a : Type) → a) True │  ❰True❱ has type ❰Bool❱, but the anonymous       \n\+        \    └────────────────────────┘  function expects an argument of kind ❰Type❱     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ List 1 │  ❰1❱ has type ❰Natural❱, but the ❰List❱ function expects an      \n\+        \    └────────┘  argument that has kind ❰Type❱                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You omit a function argument by mistake:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ List/head   [1, 2, 3] │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                ⇧                                                               \n\+        \                ❰List/head❱ is missing the first argument,                      \n\+        \                which should be: ❰Natural❱                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You supply an ❰Integer❱ literal to a function that expects a ❰Natural❱        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ Natural/even +2 │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                   ⇧                                                            \n\+        \                   This should be ❰2❱                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to invoke the following function:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which expects an argument of type or kind:                                  \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... on the following argument:                                                  \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which has a different type or kind:                                         \n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2+        txt3 = insert expr3++prettyTypeMessage (AnnotMismatch expr0 expr1 expr2) = ErrorMessages {..}+  where+    short = "Expression doesn't match annotation\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)++    hints = []++    long =+        "Explanation: You can annotate an expression with its type or kind using the     \n\+        \❰:❱ symbol, like this:                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱\n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \The type checker verifies that the expression's type or kind matches the        \n\+        \provided annotation                                                             \n\+        \                                                                                \n\+        \For example, all of the following are valid annotations that the type checker   \n\+        \accepts:                                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ 1 : Natural │  ❰1❱ is an expression that has type ❰Natural❱, so the type  \n\+        \    └─────────────┘  checker accepts the annotation                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ Natural/even 2 : Bool │  ❰Natural/even 2❱ has type ❰Bool❱, so the type    \n\+        \    └───────────────────────┘  checker accepts the annotation                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  ❰List❱ is an expression that has kind ❰Type → Type❱,\n\+        \    └────────────────────┘  so the type checker accepts the annotation          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ List Text : Type │  ❰List Text❱ is an expression that has kind ❰Type❱, so \n\+        \    └──────────────────┘  the type checker accepts the annotation               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following annotations are " <> _NOT <> " valid and the type checker will\n\+        \reject them:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 : Text │  The type checker rejects this because ❰1❱ does not have type  \n\+        \    └──────────┘  ❰Text❱                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ List : Type │  ❰List❱ does not have kind ❰Type❱                           \n\+        \    └─────────────┘                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● The Haskell Dhall interpreter implicitly inserts a top-level annotation       \n\+        \  matching the expected type                                                    \n\+        \                                                                                \n\+        \  For example, if you run the following Haskell code:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ >>> input auto \"1\" :: IO Text │                                         \n\+        \    └───────────────────────────────┘                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... then the interpreter will actually type check the following annotated     \n\+        \  expression:                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 : Text │                                                                \n\+        \    └──────────┘                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... and then type-checking will fail                                          \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You or the interpreter annotated this expression:                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... with this type or kind:                                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the inferred type or kind of the expression is actually:                \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage Untyped = ErrorMessages {..}+  where+    short = "❰Sort❱ has no type, kind, or sort"++    hints = []++    long =+        "Explanation: There are five levels of expressions that form a hierarchy:        \n\+        \                                                                                \n\+        \● terms                                                                         \n\+        \● types                                                                         \n\+        \● kinds                                                                         \n\+        \● sorts                                                                         \n\+        \● orders                                                                        \n\+        \                                                                                \n\+        \The following example illustrates this hierarchy:                               \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────┐                                       \n\+        \    │ \"ABC\" : Text : Type : Kind : Sort │                                     \n\+        \    └───────────────────────────────────┘                                       \n\+        \       ⇧      ⇧      ⇧      ⇧      ⇧                                            \n\+        \       term   type   kind   sort   order                                        \n\+        \                                                                                \n\+        \There is nothing above ❰Sort❱ in this hierarchy, so if you try to type check any\n\+        \expression containing ❰Sort❱ anywhere in the expression then type checking fails\n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You supplied a sort where a kind was expected                                 \n\+        \                                                                                \n\+        \  For example, the following expression will fail to type check:                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ f : Type -> Kind │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                  ⇧                                                             \n\+        \                  ❰Kind❱ is a sort, not a kind                                  \n"++prettyTypeMessage (InvalidPredicate expr0 expr1) = ErrorMessages {..}+  where+    short = "Invalid predicate for ❰if❱: "+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized Bool expr1)++    hints = []++    long =+        "Explanation: Every ❰if❱ expression begins with a predicate which must have type \n\+        \❰Bool❱                                                                          \n\+        \                                                                                \n\+        \For example, these are valid ❰if❱ expressions:                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────┐                                            \n\+        \    │ if True then \"Yes\" else \"No\" │                                        \n\+        \    └──────────────────────────────┘                                            \n\+        \         ⇧                                                                      \n\+        \         Predicate                                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ λ(x : Bool) → if x then False else True │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                       ⇧                                                        \n\+        \                       Predicate                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but these are " <> _NOT <> " valid ❰if❱ expressions:                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ if 0 then \"Yes\" else \"No\" │  ❰0❱ does not have type ❰Bool❱            \n\+        \    └───────────────────────────┘                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ if \"\" then False else True │  ❰\"\"❱ does not have type ❰Bool❱          \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might be used to other programming languages that accept predicates other \n\+        \  than ❰Bool❱                                                                   \n\+        \                                                                                \n\+        \  For example, some languages permit ❰0❱ or ❰\"\"❱ as valid predicates and treat\n\+        \  them as equivalent to ❰False❱.  However, the Dhall language does not permit   \n\+        \  this                                                                          \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \Your ❰if❱ expression begins with the following predicate:                       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... that has type:                                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the predicate must instead have type ❰Bool❱                             \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (IfBranchMismatch expr0 expr1 expr2 expr3) =+    ErrorMessages {..}+  where+    short = "❰if❱ branches must have matching types\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3)++    hints = []++    long =+        "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\+        \is an expression:                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \                   Expression for ❰then❱ branch                                 \n\+        \                   ⇩                                                            \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ if True then \"Hello, world!\"   │                                        \n\+        \    │         else \"Goodbye, world!\" │                                        \n\+        \    └────────────────────────────────┘                                          \n\+        \                   ⇧                                                            \n\+        \                   Expression for ❰else❱ branch                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \These two expressions must have the same type.  For example, the following ❰if❱ \n\+        \expressions are all valid:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ λ(b : Bool) → if b then 0 else 1 │ Both branches have type ❰Natural❱      \n\+        \    └──────────────────────────────────┘                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ λ(b : Bool) →              │                                              \n\+        \    │     if b then Natural/even │ Both branches have type ❰Natural → Bool❱     \n\+        \    │          else Natural/odd  │                                              \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following expression is " <> _NOT <> " valid:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \                   This branch has type ❰Natural❱                               \n\+        \                   ⇩                                                            \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ if True then 0         │                                                  \n\+        \    │         else \"ABC\"     │                                                \n\+        \    └────────────────────────┘                                                  \n\+        \                   ⇧                                                            \n\+        \                   This branch has type ❰Text❱                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \The ❰then❱ and ❰else❱ branches must have matching types, even if the predicate  \n\+        \is always ❰True❱ or ❰False❱                                                     \n\+        \                                                                                \n\+        \Your ❰if❱ expression has the following ❰then❱ branch:                           \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which has type:                                                             \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... and the following ❰else❱ branch:                                            \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which has a different type:                                                 \n\+        \                                                                                \n\+        \" <> txt3 <> "\n\+        \                                                                                \n\+        \Fix your ❰then❱ and ❰else❱ branches to have matching types                      \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2+        txt3 = insert expr3++prettyTypeMessage (ListLitInvariant) = ErrorMessages {..}+  where+    short = "Internal error: A non-empty list literal violated an internal invariant"++    hints = []++    long =+        "Explanation: Internal error: A non-empty list literal violated an internal      \n\+        \invariant.                                                                      \n\+        \                                                                                \n\+        \A non-empty list literal must always be represented as                          \n\+        \                                                                                \n\+        \    ListLit Nothing [x, y, ...]                                                 \n\+        \                                                                                \n\+        \Please file a bug report at https://github.com/dhall-lang/dhall-haskell/issues, \n\+        \ideally including the offending source code.                                    \n"++prettyTypeMessage (InvalidListType expr0) = ErrorMessages {..}+  where+    short = "Invalid type for ❰List❱"++    hints = []++    long =+        "Explanation: ❰List❱s can optionally document their type with a type annotation, \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ [1, 2, 3] : List Natural │  A ❰List❱ of three ❰Natural❱ numbers           \n\+        \    └──────────────────────────┘                                                \n\+        \                       ⇧                                                        \n\+        \                       The type of the ❰List❱'s elements, which are ❰Natural❱   \n\+        \                       numbers                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ [] : List Natural │  An empty ❰List❱                                      \n\+        \    └───────────────────┘                                                       \n\+        \           ⇧                                                                    \n\+        \           You must specify the type when the ❰List❱ is empty                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \The type must be of the form ❰List ...❱ and not something else.  For example,   \n\+        \the following type annotation is " <> _NOT <> " valid:                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────┐                                                              \n\+        \    │ ... : Bool │                                                              \n\+        \    └────────────┘                                                              \n\+        \            ⇧                                                                   \n\+        \            This type does not have the form ❰List ...❱                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \The element type must be a type and not something else.  For example, the       \n\+        \following element types are " <> _NOT <> " valid:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────┐                                                            \n\+        \    │ ... : List 1 │                                                            \n\+        \    └──────────────┘                                                            \n\+        \                 ⇧                                                              \n\+        \                 This is a ❰Natural❱ number and not a ❰Type❱                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ ... : List Type │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                 ⇧                                                              \n\+        \                 This is a ❰Kind❱ and not a ❰Type❱                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \You declared that the ❰List❱ should have type:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a valid list type                                              \n"+      where+        txt0 = insert expr0++prettyTypeMessage MissingListType =+    ErrorMessages {..}+  where+    short = "An empty list requires a type annotation"++    hints = []++    long =+        "Explanation: Lists do not require a type annotation if they have at least one   \n\+        \element:                                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ [1, 2, 3] │  The compiler can infer that this list has type ❰List Natural❱\n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, empty lists still require a type annotation:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ [] : List Natural │  This type annotation is mandatory                    \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \You cannot supply an empty list without a type annotation                       \n"++prettyTypeMessage (MismatchedListElements i expr0 _expr1 expr2) =+    ErrorMessages {..}+  where+    short = "List elements should all have the same type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr2)++    hints = []++    long =+        "Explanation: Every element in a list must have the same type                    \n\+        \                                                                                \n\+        \For example, this is a valid ❰List❱:                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ [1, 2, 3] │  Every element in this ❰List❱ is a ❰Natural❱ number           \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \.. but this is " <> _NOT <> " a valid ❰List❱:                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ [1, \"ABC\", 3] │  The first and second element have different types      \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your first ❰List❱ element has this type:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the element at index #" <> txt1 <> " has this type instead:             \n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = insert expr0+        txt1 = pretty i+        txt3 = insert expr2++prettyTypeMessage (InvalidSome expr0 expr1 expr2) = ErrorMessages {..}+  where+    short = "❰Some❱ argument has the wrong type"++    hints = []++    long =+        "Explanation: The ❰Some❱ constructor expects an argument that is a term, where   \n\+        \the type of the type of a term must be ❰Type❱                                   \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰Some❱:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ Some 1 │  ❰1❱ is a valid term because ❰1 : Natural : Type❱                \n\+        \    └────────┘                                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but this is " <> _NOT <> " a valid ❰Optional❱ value:                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ Some Text │  ❰Text❱ is not a valid term because ❰Text : Type : Kind ❱     \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \The ❰Some❱ argument you provided:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... has this type:                                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the type of that type is:                                               \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which is not ❰Type❱                                                         \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage (InvalidFieldType k expr0) = ErrorMessages {..}+  where+    short = "Invalid field type"++    hints = []++    long =+        "Explanation: Every record type annotates each field with a ❰Type❱, a ❰Kind❱, or \n\+        \a ❰Sort❱ like this:                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────┐                            \n\+        \    │ { foo : Natural, bar : Integer, baz : Text } │  Every field is annotated  \n\+        \    └──────────────────────────────────────────────┘  with a ❰Type❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ { foo : Type, bar : Type } │  Every field is annotated                    \n\+        \    └────────────────────────────┘  with a ❰Kind❱                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the types of fields may " <> _NOT <> " be term-level values:           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ { foo : Natural, bar : 1 } │  Invalid record type                         \n\+        \    └────────────────────────────┘                                              \n\+        \                             ⇧                                                  \n\+        \                             ❰1❱ is a ❰Natural❱ number and not a ❰Type❱,        \n\+        \                             ❰Kind❱, or ❰Sort❱                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided a record type with a field named:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... annotated with the following expression:                                    \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is neither a ❰Type❱, a ❰Kind❱, nor a ❰Sort❱                           \n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (InvalidAlternativeType k expr0) = ErrorMessages {..}+  where+    short = "Invalid alternative type"++    hints = []++    long =+        "Explanation: Every union type specifies the type of each alternative, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \               The type of the first alternative is ❰Bool❱                      \n\+        \               ⇩                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ < Left : Bool, Right : Natural > │  A union type with two alternatives    \n\+        \    └──────────────────────────────────┘                                        \n\+        \                             ⇧                                                  \n\+        \                             The type of the second alternative is ❰Natural❱    \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, these alternatives can only be annotated with ❰Type❱s, ❰Kind❱s, or     \n\+        \❰Sort❱s.  For example, the following union types are " <> _NOT <> " valid:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ < Left : Bool, Right : 1 > │  Invalid union type                          \n\+        \    └────────────────────────────┘                                              \n\+        \                             ⇧                                                  \n\+        \                             This is a ❰Natural❱ and not a ❰Type❱, ❰Kind❱, or   \n\+        \                             ❰Sort❱                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally typed ❰:❱ instead of ❰=❱ for a union literal with one        \n\+        \  alternative:                                                                  \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ < Example : 1 > │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                ⇧                                                               \n\+        \                This could be ❰=❱ instead                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided a union type with an alternative named:                            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... annotated with the following expression which is not a ❰Type❱, ❰Kind❱, or   \n\+        \❰Sort❱:                                                                         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (ListAppendMismatch expr0 expr1) = ErrorMessages {..}+  where+    short = "You can only append ❰List❱s with matching element types\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can append two ❰List❱s using the ❰#❱ operator, like this:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ [1, 2, 3] # [4, 5] │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot append two ❰List❱s if they have different element types.     \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \       These elements have type ❰Natural❱                                       \n\+        \       ⇩                                                                        \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ [1, 2, 3] # [True, False] │  Invalid: the element types don't match       \n\+        \    └───────────────────────────┘                                               \n\+        \                  ⇧                                                             \n\+        \                  These elements have type ❰Bool❱                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to append a ❰List❱ thas has elements of type:                         \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... with another ❰List❱ that has elements of type:                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... and those two types do not match                                            \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CompletionSchemaMustBeARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "The completion schema must be a record"++    hints = []++    long =+        "Explanation: You can complete records using the ❰::❱ operator:                  \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────────┐ \n\+        \    │ {Type = {foo : Bool, bar : Natural}, default = {bar = 2}::{foo = True}} │ \n\+        \    └─────────────────────────────────────────────────────────────────────────┘ \n\+        \                                                                                \n\+        \... The left-hand side of :: must be a record with 'Type' and 'default' keys    \n\+        \                                                                                \n\+        \You tried to record complete the following value:                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a record. It is:                                               \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (InvalidRecordCompletion fieldName expr0) = ErrorMessages {..}+  where+    short = "Completion schema is missing a field: " <> pretty fieldName++    hints = []++    long =+        "Explanation: You can complete records using the ❰::❱ operator like this:\n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────────┐ \n\+        \    │ {Type = {foo : Bool, bar : Natural}, default = {bar = 2}::{foo = True}} │ \n\+        \    └─────────────────────────────────────────────────────────────────────────┘ \n\+        \                                                                                \n\+        \... but you need to have both Type and default fields in the completion schema  \n\+        \    (the record on the left of the the ::).                                     \n\+        \                                                                                \n\+        \You tried to do record completion using the schema:                             \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is missing the key:                                                   \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = pretty fieldName++prettyTypeMessage (MustCombineARecord c expression typeExpression) =+    ErrorMessages {..}+  where+    action = case c of+        '∧' -> "combine"+        _   -> "override"++    short = "You can only " <> action <> " records"++    hints = emptyRecordTypeHint expression++    long =+        "Explanation: You can " <> action <> " records using the ❰" <> op <> "❱ operator, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz = True } │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ λ(r : { foo : Bool }) → r " <> op <> " { bar = \"ABC\" } │                \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot " <> action <> " values that are not records.                \n\+        \                                                                                \n\+        \For example, the following expressions are " <> _NOT <> " valid:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────┐                                            \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " 1 │                               \n\+        \    └──────────────────────────────┘                                            \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: Not a record                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz : Bool } │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: This is a record type and not a record\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " < baz : Bool > │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: This is a union type and not a record \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You supplied this expression as one of the arguments:                           \n\+        \                                                                                \n\+        \" <> insert expression <> "\n\+        \                                                                                \n\+        \... which is not a record, but is actually a:                                   \n\+        \                                                                                \n\+        \" <> insert typeExpression <> "\n"+      where+        op = pretty c++prettyTypeMessage (InvalidDuplicateField k expr0 expr1) =+    ErrorMessages {..}+  where+    short = "Invalid duplicate field: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can specify a field twice if both fields are themselves        \n\+        \records, like this:                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────────┐                \n\+        \    │ { ssh = { enable = True }, ssh = { forwardX11 = True } } │                \n\+        \    └──────────────────────────────────────────────────────────┘                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... because the language automatically merges two occurrences of a field using  \n\+        \the ❰∧❱ operator, and the above example is equivalent to:                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────┐                     \n\+        \    │ { ssh = { enable = True } ∧ { forwardX11 = True } } │                     \n\+        \    └─────────────────────────────────────────────────────┘                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... which is in turn equivalent to:                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐                          \n\+        \    │ { ssh = { enable = True, forwardX11 = True } } │                          \n\+        \    └────────────────────────────────────────────────┘                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, this implies that both fields must be records since the ❰∧❱ operator   \n\+        \cannot merge non-record values.  For example, these expressions are not valid:  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ { x = 0, x = 0 } │  Invalid: Neither field is a record                    \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ { x = 0, x = { y = 0 } } │  Invalid: The first ❰x❱ field is not a record  \n\+        \    └──────────────────────────┘                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified more than one field named:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but one of the fields had this value:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... with this type:                                                             \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which is not a record type                                                  \n"+      where+        txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome k)+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CombineTypesRequiresRecordType expr0 expr1) =+    ErrorMessages {..}+  where+    short = "❰⩓❱ requires arguments that are record types"++    hints = []++    long =+        "Explanation: You can only use the ❰⩓❱ operator on arguments that are record type\n\+        \literals, like this:                                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────┐                                     \n\+        \    │ { age : Natural } ⩓ { name : Text } │                                     \n\+        \    └─────────────────────────────────────┘                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot use the ❰⩓❱ operator on any other type of arguments.  For    \n\+        \example, you cannot use variable arguments:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────┐                                       \n\+        \    │ λ(t : Type) → t ⩓ { name : Text } │  Invalid: ❰t❱ might not be a record   \n\+        \    └───────────────────────────────────┘  type                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to supply the following argument:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which normalized to:                                                        \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a record type literal                                          \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (DuplicateFieldCannotBeMerged ks) = ErrorMessages {..}+  where+    short = "Duplicate field cannot be merged: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: Duplicate fields are only allowed if they are both records and if  \n\+        \the two records can be recursively merged without collisions.                   \n\+        \                                                                                \n\+        \Specifically, an expression like:                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ { x = a, x = b } │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... is syntactic sugar for:                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ { x = a ∧ b } │                                                           \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \... which is rejected if ❰a ∧ b❱ does not type-check.  One way this can happen  \n\+        \is if ❰a❱ and ❰b❱ share a field in common that is not a record, which is known  \n\+        \as a \"collision\".                                                               \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = { y = 0 }, x = { y = 1 } } │ Invalid: The two ❰x.y❱ fields \"collide\"\n\+        \    └──────────────────────────────────┘                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... whereas the following expression is valid:                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = { y = 0 }, x = { z = 1 } } │ Valid: the two ❰x❱ fields don't collide\n\+        \    └──────────────────────────────────┘ because they can be recursively merged \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You specified the same field twice by mistake                                 \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified the following field twice:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which collided on the following path:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome (NonEmpty.head ks))++        txt1 = insert (toPath ks)++prettyTypeMessage (FieldCollision ks) = ErrorMessages {..}+  where+    short = "Field collision on: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: You can recursively merge records using the ❰∧❱ operator:          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { x = a } ∧ { y = b } │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \... but two records cannot be merged in this way if they share a field that is  \n\+        \not a record.                                                                   \n\+        \                                                                                \n\+        \For example, the following expressions are " <> _NOT <> " valid:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ { x = 1 } ∧ { x = True } │  Invalid: The ❰x❱ fields \"collide\" because they\n\+        \    └──────────────────────────┘  are not records that can be merged            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = 1 } ∧ { x = { y = True } } │  Invalid: One of the two ❰x❱ fields is \n\+        \    └──────────────────────────────────┘  still not a record                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following expression is valid:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐  Valid: The two ❰x❱ fields     \n\+        \    │ { x = { y = True } } ∧ { x = { z = 1 } } │  don't collide because they can\n\+        \    └──────────────────────────────────────────┘  be recursively merged         \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to use ❰∧❱ to update a field's value, like this:                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────┐                                  \n\+        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = 2 } │                                  \n\+        \    └────────────────────────────────────────┘                                  \n\+        \                                   ⇧                                            \n\+        \                                  Invalid attempt to update ❰foo❱'s value to ❰2❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \  You probably meant to use ❰⫽❱ / ❰//❱  instead:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────┐                                  \n\+        \    │ { foo = 1, bar = \"ABC\" } ⫽ { foo = 2 } │                                  \n\+        \    └────────────────────────────────────────┘                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to merge two records which collided on the following path:            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (toPath ks)++prettyTypeMessage (FieldTypeCollision ks) = ErrorMessages {..}+  where+    short = "Field type collision on: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: You can recursively merge record types using the ❰⩓❱ operator, like\n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { x : A } ⩓ { y : B } │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot merge record types if two field types collide that are not   \n\+        \both record types.                                                              \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ { x : Natural } ⩓ { x : Bool } │  Invalid: The ❰x❱ fields \"collide\"       \n\+        \    └────────────────────────────────┘  because they cannot be merged           \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following expression is valid:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐  Valid: The ❰x❱ field    \n\+        \    │ { x : { y : Bool } } ⩓ { x : { z : Natural } } │  types don't collide and \n\+        \    └────────────────────────────────────────────────┘  can be merged           \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to merge two record types which collided on the following path:       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (toPath ks)++prettyTypeMessage (MustMergeARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "❰merge❱ expects a record of handlers"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │     let union    = < Left : Natural | Right : Bool >.Left 2         │     \n\+        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\+        \    │ in  merge handlers union                                            │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the first argument to ❰merge❱ must be a record and not some other type. \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ let handler = λ(x : Bool) → x               │                             \n\+        \    │ in  merge handler (< Foo : Bool >.Foo True) │                             \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                ⇧                                                               \n\+        \                Invalid: ❰handler❱ isn't a record                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally provide an empty record type instead of an empty record when \n\+        \  you ❰merge❱ an empty union:                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ λ(x : <>) → λ(a : Type) → merge {} x : a │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                      ⇧                                         \n\+        \                                      This should be ❰{=}❱ instead              \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided the following handler:                                             \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a record, but is actually a value of type:                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (MustMergeUnionOrOptional expr0 expr1) = ErrorMessages {..}+  where+    short = "❰merge❱ expects a union or an ❰Optional❱"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────┐                 \n\+        \    │ let optional = None Bool                                │                 \n\+        \    │ let handlers = { None = False, Some = λ(x : Bool) → x } │                 \n\+        \    │ in  merge handlers optional                             │                 \n\+        \    └─────────────────────────────────────────────────────────┘                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the second argument to ❰merge❱ must not be some other type.             \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ let handlers = { Foo = λ(x : Bool) → x } │                                \n\+        \    │ in  merge handlers True                  │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                         ⇧                                                      \n\+        \                         Invalid: ❰True❱ isn't a union or an ❰Optional❱         \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to ❰merge❱ this expression:                                           \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a union or an ❰Optional❱, but is actually a value of type:     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (UnusedHandler ks) = ErrorMessages {..}+  where+    short = "Unused handler"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you must provide exactly one handler per alternative in the union.  You \n\+        \cannot supply extra handlers                                                    \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ let union    = < Left : Natural >.Left 2 │  The ❰Right❱ alternative is    \n\+        \    │ let handlers =                           │  missing                       \n\+        \    │             { Left  = Natural/even       │                                \n\+        \    │             , Right = λ(x : Bool) → x    │  Invalid: ❰Right❱ handler isn't\n\+        \    │             }                            │           used                 \n\+        \    │ in  merge handlers union                 │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided the following handlers:                                            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which had no matching alternatives in the union you tried to ❰merge❱        \n"+      where+        txt0 = insert (Text.intercalate ", " (Data.Set.toList ks))++prettyTypeMessage (MissingHandler exemplar ks) = ErrorMessages {..}+  where+    short = case Data.Set.toList ks of+         []       -> "Missing handler: " <> Dhall.Pretty.Internal.prettyLabel exemplar+         xs@(_:_) -> "Missing handlers: " <> (Pretty.hsep . Pretty.punctuate Pretty.comma+                                             . map Dhall.Pretty.Internal.prettyLabel $ exemplar:xs)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you must provide exactly one handler per alternative in the union.  You \n\+        \cannot omit any handlers                                                        \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \                                          Invalid: Missing ❰Right❱ handler      \n\+        \                                          ⇩                                     \n\+        \    ┌──────────────────────────────────────────────────────────────┐            \n\+        \    │ let handlers = { Left = Natural/even }                       │            \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2      │            \n\+        \    │ in  merge handlers union                                     │            \n\+        \    └──────────────────────────────────────────────────────────────┘            \n\+        \                                                                                \n\+        \                                                                                \n\+        \Note that you need to provide handlers for other alternatives even if those     \n\+        \alternatives are never used                                                     \n\+        \                                                                                \n\+        \You need to supply the following handlers:                                      \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (Text.intercalate ", " (exemplar : Data.Set.toList ks))++prettyTypeMessage MissingMergeType =+    ErrorMessages {..}+  where+    short = "An empty ❰merge❱ requires a type annotation"++    hints = []++    long =+        "Explanation: A ❰merge❱ does not require a type annotation if the union has at   \n\+        \least one alternative, like this                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you must provide a type annotation when merging an empty union:        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ λ(a : <>) → merge {=} a : Bool │                                          \n\+        \    └────────────────────────────────┘                                          \n\+        \                                ⇧                                               \n\+        \                                This can be any type                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \You can provide any type at all as the annotation, since merging an empty       \n\+        \union can produce any type of output                                            \n"++prettyTypeMessage (HandlerInputTypeMismatch expr0 expr1 expr2) =+    ErrorMessages {..}+  where+    short = "Wrong handler input type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as the input type of each handler function matches the type of the  \n\+        \corresponding alternative:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ union    : < Left : Natural       | Right : Bool        > │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                          ⇧                       ⇧                             \n\+        \                   These must match        These must match                     \n\+        \                          ⇩                       ⇩                             \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \      Invalid: Doesn't match the type of the ❰Right❱ alternative                \n\+        \                                                               ⇩                \n\+        \    ┌──────────────────────────────────────────────────────────────────┐        \n\+        \    │ let handlers = { Left = Natural/even | Right = λ(x : Text) → x } │        \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2          │        \n\+        \    │ in  merge handlers union                                         │        \n\+        \    └──────────────────────────────────────────────────────────────────┘        \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for the following alternative:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... needs to accept an input value of type:                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but actually accepts an input value of a different type:                    \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage (DisallowedHandlerType label handlerType handlerOutputType variable) =+    ErrorMessages {..}+  where+    short = "Disallowed handler type"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the output type of a handler may not depend on the input value.         \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \      Invalid: The output type is ❰Optional A❱, which references the input      \n\+        \      value ❰A❱.                                                                \n\+        \                  ⇩                                                             \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ merge { x = None } (< x : Type >.x Bool) │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for the following alternative:                                     \n\+        \                                                                                \n\+        \" <> insert label <> "\n\+        \                                                                                \n\+        \... has type:                                                                   \n\+        \                                                                                \n\+        \" <> insert handlerType <> "\n\+        \                                                                                \n\+        \... where the output type:                                                      \n\+        \                                                                                \n\+        \" <> insert handlerOutputType <> "\n\+        \                                                                                \n\+        \... references the handler's input value:                                       \n\+        \                                                                                \n\+        \" <> insert variable <> "\n"++prettyTypeMessage (HandlerOutputTypeMismatch key0 expr0 key1 expr1) =+    ErrorMessages {..}+  where+    short = "Handlers should have the same output type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as the output type of each handler function is the same:            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                                    ⇧                    ⇧                      \n\+        \                                These output types both match                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────┐                         \n\+        \    │ let Union = < Left : Natural | Right : Bool >   │                         \n\+        \    │ let handlers =                                  │                         \n\+        \    │              { Left  = λ(x : Natural) → x       │  This outputs ❰Natural❱ \n\+        \    │              , Right = λ(x : Bool   ) → x       │  This outputs ❰Bool❱    \n\+        \    │              }                                  │                         \n\+        \    │ in  merge handlers (Union.Left 2)               │                         \n\+        \    └─────────────────────────────────────────────────┘                         \n\+        \                ⇧                                                               \n\+        \                Invalid: The handlers in this record don't have matching outputs\n\+        \                                                                                \n\+        \                                                                                \n\+        \The handler for the ❰" <> txt0 <> "❱ alternative has this output type:          \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the handler for the ❰" <> txt2 <> "❱ alternative has this output type instead:\n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = pretty key0+        txt1 = insert expr0+        txt2 = pretty key1+        txt3 = insert expr1++prettyTypeMessage (HandlerNotAFunction k expr0) = ErrorMessages {..}+  where+    short = "Handler for "<> Dhall.Pretty.Internal.prettyLabel k <> " is not a function"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as each handler is a function -- FIXME                              \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐                          \n\+        \    │ merge { Foo = True } (< Foo : Natural >.Foo 1) │                          \n\+        \    └────────────────────────────────────────────────┘                          \n\+        \                    ⇧                                                           \n\+        \                    Invalid: Not a function                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for this alternative:                                              \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... has the following type:                                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not the type of a function                                         \n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (MustMapARecord provided _providedType) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a record value"++    hints = emptyRecordTypeHint provided++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record, like this:         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the argument to ❰toMap❱ must be a record and not some other type.       \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally provide an empty record type instead of an empty record when \n\+        \  using ❰toMap❱:                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────┐                   \n\+        \    │ toMap {} : List { mapKey : Text, mapValue : Natural } │                   \n\+        \    └───────────────────────────────────────────────────────┘                   \n\+        \            ⇧                                                                   \n\+        \            This should be ❰{=}❱ instead                                        \n"++prettyTypeMessage (InvalidToMapRecordKind type_ kind) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a record of kind ❰Type❱"++    hints = []++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record of kind ❰Type❱, like\n\+        \ this:                                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but records of kind ❰Kind❱ or ❰Sort❱ cannot be turned into ❰List❱s.         \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You applied ❰toMap❱ to a record of the following type:                          \n\+        \                                                                                \n\+        \" <> insert type_ <> "\n\+        \                                                                                \n\+        \... which has kind                                                              \n\+        \                                                                                \n\+        \" <> insert kind <> "\n"++prettyTypeMessage (HeterogenousRecordToMap _expr0 _expr1 _expr2) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a homogenous record"++    hints = []++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record, like this:         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but every field of the record must have the same type.                      \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ toMap { Foo = True, Bar = 0 }           │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                    ⇧           ⇧                                               \n\+        \                    Bool        Natural                                         \n"++prettyTypeMessage (MapTypeMismatch expr0 expr1) = ErrorMessages {..}+  where+    short = "❰toMap❱ result type doesn't match annotation"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: a ❰toMap❱ application has been annotated with a type that doesn't  \n\+        \match its inferred type.                                                        \n"++prettyTypeMessage (InvalidToMapType expr) =+    ErrorMessages {..}+  where+    short = "An empty ❰toMap❱ was annotated with an invalid type"+        <>  "\n"+        <>  insert expr++    hints = []++    long =+        "Explanation: A ❰toMap❱ applied to an empty record must have a type annotation:  \n\+        \that matches a list of key-value pairs, like this                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ toMap {=} : List { mapKey : Text, mapValue : Natural}               │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \The type you have provided doesn't match the expected form.                     \n\+        \                                                                                \n"++prettyTypeMessage MissingToMapType =+    ErrorMessages {..}+  where+    short = "An empty ❰toMap❱ requires a type annotation"++    hints = []++    long =+        "Explanation: A ❰toMap❱ does not require a type annotation if the record has at  \n\+        \least one field, like this                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record                                                    │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you must provide a type annotation with an empty record:               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ toMap {=} : List { mapKey : Text, mapValue : Natural}               │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n"++prettyTypeMessage (CantAccess lazyText0 expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a record or a union"++    hints = []++    long =+        "Explanation: You can only access fields on records or unions, like this:        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ < foo : Bool | bar : Text >.foo │  ... and so is this                     \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────┐                              \n\+        \    │ λ(r : < foo : Bool | bar : Text >) → r.foo │  ... and so is this          \n\+        \    └────────────────────────────────────────────┘                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot access fields on non-record expressions                      \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 1.foo │                                                                   \n\+        \    └───────┘                                                                   \n\+        \      ⇧                                                                         \n\+        \      Invalid: Not a record                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to access the field:                                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... on the following expression which is not a record nor a union type:         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but is actually an expression of type:                                      \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert lazyText0+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CantProject lazyText0 expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a record"++    hints = []++    long =+        "Explanation: You can only project fields on records, like this:                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────┐                     \n\+        \    │ { foo = True, bar = \"ABC\", baz = 1 }.{ foo, bar } │  This is valid ...  \n\+        \    └─────────────────────────────────────────────────────┘                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────────────────────────┐      \n\+        \    │ λ(r : { foo : Bool, bar : Text , baz : Natural }) → r.{ foo, bar } │  ... and so is this           \n\+        \    └────────────────────────────────────────────────────────────────────┘      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot project fields on non-record expressions                     \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ 1.{ foo, bar } │                                                          \n\+        \    └────────────────┘                                                          \n\+        \      ⇧                                                                         \n\+        \      Invalid: Not a record                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally try to project fields of a union instead of a record, like   \n\+        \  this:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────┐                                      \n\+        \    │ < foo : a | bar : b >.{ foo, bar } │                                      \n\+        \    └────────────────────────────────────┘                                      \n\+        \      ⇧                                                                         \n\+        \      This is a union, not a record                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to access the fields:                                                 \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... on the following expression which is not a record:                          \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but is actually an expression of type:                                      \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert lazyText0+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CantProjectByExpression expr) = ErrorMessages {..}+  where+    short = "Selector is not a record type"++    hints = []++    long =+        "Explanation: You can project by an expression if that expression is a record    \n\+        \type:                                                                           \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True }.({ foo : Bool }) │  This is valid ...                      \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ λ(r : { foo : Bool }) → r.{ foo : Bool } │  ... and so is this            \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot project by any other type of expression:                     \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { foo = True }.(True) │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                      ⇧                                                         \n\+        \                      Invalid: Not a record type                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally try to project by a record value instead of a record type,   \n\+        \  like this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ let T = { foo : Bool }          │                                         \n\+        \    │                                 │                                         \n\+        \    │ let x = { foo = True , bar = 1} │                                         \n\+        \    │                                 │                                         \n\+        \    │ let y = { foo = False, bar = 2} │                                         \n\+        \    │                                 │                                         \n\+        \    │ in  x.(y)                       │                                         \n\+        \    └─────────────────────────────────┘                                         \n\+        \             ⇧                                                                  \n\+        \             The user might have meant ❰T❱ here                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to project out the following type:                                    \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is not a record type                                                  \n"+      where+        txt = insert expr++prettyTypeMessage (DuplicateProjectionLabel k) = ErrorMessages {..}+  where+    short = "Duplicate projection label: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can only specify a label once when projecting a record's fields\n\+        \by label.  For example, this is valid:                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ { x = 1.1, y = 2.4, z = -0.3 }.{ x, y } │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but this is not valid:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ { x = 1.1, y = 2.4, z = -0.3 }.{ y, y } │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                          ⇧                                     \n\+        \                                          Invalid: the label ❰y❱ appears twice  \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to project the following field twice:                                 \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert k++prettyTypeMessage (MissingField k expr0) = ErrorMessages {..}+  where+    short = "Missing record field: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can only access fields on records, like this:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you can only access fields if they are present                          \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.qux │                                       \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                  ⇧                                             \n\+        \                                  Invalid: the record has no ❰qux❱ field        \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to access a field named:                                              \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the field is missing because the record only defines the following      \n\+        \fields:                                                                         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (MissingConstructor k expr0) = ErrorMessages {..}+  where+    short = "Missing constructor: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can access constructors from unions, like this:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ < Foo | Bar >.Foo │  This is valid ...                                    \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you can only access constructors if they match an union alternative of  \n\+        \the same name.                                                                  \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ < Foo | Bar >.Baz │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                    ⇧                                                           \n\+        \                    Invalid: the union has no ❰Baz❱ alternative                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to access a constructor named:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the constructor is missing because the union only defines the following \n\+        \alternatives:                                                                   \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (ProjectionTypeMismatch k expr0 expr1 expr2 expr3) = ErrorMessages {..}+  where+    short = "Projection type mismatch\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr2 expr3)++    hints = []++    long =+        "Explanation: You can project a subset of fields from a record by specifying the \n\+        \desired type of the final record, like this:                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ { foo = 1, bar = True }.({ foo : Natural }) │  This is valid              \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the expected type for each desired field must match the actual type of  \n\+        \the corresponding field in the original record.                                 \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \              Invalid: The ❰foo❱ field contains ❰1❱, which has type ❰Natural❱...\n\+        \              ⇩                                                                 \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ { foo = 1, bar = True }.({ foo : Text }) │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                       ⇧                                        \n\+        \                                       ... but we requested that the ❰foo❱ field\n\+        \                                       must contain a value of type ❰Text❱      \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to project out a field named:                                         \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... that should have type:                                                      \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but that field instead had a value of type:                                 \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (AssertionFailed expr0 expr1) = ErrorMessages {..}+  where+    short = "Assertion failed\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can assert at type-checking time that two terms are equal if   \n\+        \they have the same normal form, like this:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid                                       \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... and an assertion still succeeds if the normal forms only differ by renaming \n\+        \bound variables, like this:                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────┐                    \n\+        \    │ assert : λ(n : Natural) → n + 0 ≡ λ(m : Natural) → m │  This is also valid\n\+        \    └──────────────────────────────────────────────────────┘                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, an assertion fails if the normal forms differ in any other way.  For   \n\+        \example, the following assertion is " <> _NOT <> " valid:                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ assert : 0 ≡ 1 │  Invalid: ❰0❱ does not equal ❰1❱                         \n\+        \    └────────────────┘                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have tried to ❰assert❱ a precondition on a function's input, like   \n\+        \  this:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────────────────┐        \n\+        \    │ λ(n : Natural) → let _ = assert : Natural/isZero n ≡ False in n  │        \n\+        \    └──────────────────────────────────────────────────────────────────┘        \n\+        \                                        ⇧                                       \n\+        \                                        Invalid: This assertion will always fail\n\+        \                                                                                \n\+        \                                                                                \n\+        \  This will not work.  Such an assertion is checking all possible inputs to the \n\+        \  function, before you've even used the function at all.                        \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to assert that this expression:                                       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... is the same as this other expression:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but they differ\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (NotAnEquivalence expr) = ErrorMessages {..}+  where+    short = "Not an equivalence\n"++    hints = []++    long =+        "Explanation: The type annotation for an ❰assert❱ must evaluate to an equivalence\n\+        \of the form ❰x ≡ y❱, like this:                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid                                       \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but any other type is not a valid annotation.  For example, the following   \n\+        \assertion is " <> _NOT <> " valid:                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ assert : True │  Invalid: ❰True❱ is not an equivalence                    \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to supply an expression of type ❰Bool❱ to the assertion, rather than\n\+        \  two separate expressions to compare, like this:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ assert : Natural/isZero 0 │  Invalid: A boolean expression is not the     \n\+        \    └───────────────────────────┘  same thing as a type-level equivalence       \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You have to explicitly compare two expressions, even if that just means       \n\+        \  comparing the expression to ❰True❱, like this:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ assert : Natural/isZero 0 ≡ True │  Valid: You can assert that two boolean\n\+        \    └──────────────────────────────────┘  expressions are equivalent            \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided the following type annotation for an ❰assert❱:                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not an equivalence\n"+      where+        txt0 = insert expr++prettyTypeMessage (IncomparableExpression expr) = ErrorMessages {..}+  where+    short = "Incomparable expression\n"++    hints = []++    long =+        "Explanation: You can use an ❰assert❱ to compare two terms for equivalence, like \n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid because ❰2 + 2❱ and ❰4❱ are both terms\n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot compare expressions, that are not terms, such as types.  For \n\+        \example, the following equivalence is " <> _NOT <> " valid:                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ assert : Natural ≡ Natural │  Invalid: ❰Natural❱ is a type, not a term    \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to compare the following expression:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a term\n"+      where+        txt0 = insert expr++prettyTypeMessage (EquivalenceTypeMismatch l _L r _R) = ErrorMessages {..}+  where+    short = "The two sides of the equivalence have different types"++    hints = []++    long =+        "Explanation: You can use ❰≡❱ to compare two terms of the same type for          \n\+        \equivalence, like this:                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ 2 + 2 ≡ 4 │  This is valid because ❰2 + 2❱ and ❰4❱ have the same type     \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot compare expressions, that have different types.  For example,\n\+        \the following assertion is " <> _NOT <> " valid:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 ≡ True │  Invalid: ❰1❱ has type ❰Natural❱, ❰True❱ has type ❰Bool❱       \n\+        \    └──────────┘                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to compare the following expressions:                                 \n\+        \                                                                                \n\+        \" <> insert l <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> insert _L <> "\n\+        \                                                                                \n\+        \... and\n\+        \                                                                                \n\+        \" <> insert r <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> insert _R <> "\n"++prettyTypeMessage (NotWithARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "❰with❱ only works on records"++    hints = []++    long =+        "Explanation: You can use ❰with❱ to update a record, like this:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────┐                                                 \n\+        \    │  { a = 5 } with b = 10  │  This is valid because ❰{ a = 5}❱ is a record   \n\+        \    └────────────────────────┘                                                  \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │  λ(r : { a : Natural }) → r with b = 10  │  This is also valid because    \n\+        \    └──────────────────────────────────────────┘  ❰r❱ is a record               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot use ❰with❱ to update an expression that is not a record.  For\n\+        \example, the following expression is " <> _NOT <> " valid:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ 1 with b = 10 │  Invalid: ❰1❱ is not a record                             \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to update the following expressions:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a record type\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantAnd expr0 expr1) =+        buildBooleanOperator "&&" expr0 expr1++prettyTypeMessage (CantOr expr0 expr1) =+        buildBooleanOperator "||" expr0 expr1++prettyTypeMessage (CantEQ expr0 expr1) =+        buildBooleanOperator "==" expr0 expr1++prettyTypeMessage (CantNE expr0 expr1) =+        buildBooleanOperator "!=" expr0 expr1++prettyTypeMessage (CantInterpolate expr0 expr1) = ErrorMessages {..}+  where+    short = "You can only interpolate ❰Text❱"++    hints = []++    long =+        "Explanation: Text interpolation only works on expressions of type ❰Text❱        \n\+        \                                                                                \n\+        \For example, these are all valid uses of string interpolation:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ \"ABC${\"DEF\"}GHI\" │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ λ(x : Text) → \"ABC${x}GHI\" │                                              \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────┐                           \n\+        \    │ λ(age : Natural) → \"Age: ${Natural/show age}\" │                           \n\+        \    └───────────────────────────────────────────────┘                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have thought that string interpolation automatically converts the   \n\+        \  interpolated value to a ❰Text❱ representation of that value:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ λ(age : Natural) → \"Age: ${age}\" │                                        \n\+        \    └──────────────────────────────────┘                                        \n\+        \                                  ⇧                                             \n\+        \                                  Invalid: ❰age❱ has type ❰Natural❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You might have forgotten to escape a string interpolation that you wanted     \n\+        \  Dhall to ignore and pass through:                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ \"echo ${HOME}\" │                                                          \n\+        \    └────────────────┘                                                          \n\+        \             ⇧                                                                  \n\+        \             ❰HOME❱ is not in scope and this might have meant to use ❰\\${HOME}❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You interpolated this expression:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Text❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantTextAppend expr0 expr1) = ErrorMessages {..}+  where+    short = "❰++❱ only works on ❰Text❱"++    hints = []++    long =+        "Explanation: The ❰++❱ operator expects two arguments that have type ❰Text❱      \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰++❱:                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ \"ABC\" ++ \"DEF\" │                                                          \n\+        \    └────────────────┘                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have thought that ❰++❱ was the operator to combine two lists:       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ [1, 2, 3] ++ [4, 5, 6] │  Not valid                                       \n\+        \    └────────────────────────┘                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... but the list concatenation operator is actually ❰#❱:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ [1, 2, 3] # [4, 5, 6] │  Valid                                            \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Text❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantListAppend expr0 expr1) = ErrorMessages {..}+  where+    short = "❰#❱ only works on ❰List❱s"++    hints = []++    long =+        "Explanation: The ❰#❱ operator expects two arguments that are both ❰List❱s       \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰#❱:                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ [1, 2, 3] # [4, 5, 6] │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a ❰List❱ but instead has type:                                 \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantAdd expr0 expr1) =+        buildNaturalOperator "+" expr0 expr1++prettyTypeMessage (CantMultiply expr0 expr1) =+        buildNaturalOperator "*" expr0 expr1++prettyTypeMessage OptionalWithTypeMismatch = ErrorMessages {..}+  where+    short = "❰with❱ cannot change the type of an ❰Optional❱ value"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword cannot change the type of a value stored inside \n\+        \of a ❰Some❱ constructor                                                         \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰with❱:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \           The old value has type ❰Natural❱                                     \n\+        \           ⇩                                                                    \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ Some 1 with ? = 2 │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                      ⇧                                                         \n\+        \                      ... which matches the type of the new value, which is also\n\+        \                      ❰Natural❱                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \           The old value has type ❰Natural❱                                     \n\+        \           ⇩                                                                    \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ Some 1 with ? = True │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                      ⇧                                                         \n\+        \                      ... but the new value has type ❰Bool❱, which does not     \n\+        \                      match                                                     \n"++prettyTypeMessage NotALabelPath = ErrorMessages {..}+  where+    short = "Use a label to update a record"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword supports updating records by naming the field(s)\n\+        \to update, but you provided a path component of ❰?❱, which only works on        \n\+        \❰Optional❱ values and not records.                                              \n\+        \                                                                                \n\+        \For example, these are valid uses of ❰with❱ to update a record:                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ { x = 1 } with x = 2 │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ { x = { y = 1 } } with x.y = 2 │                                          \n\+        \    └────────────────────────────────┘                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ { x = 1 } with ? = 2 │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                     ⇧                                                          \n\+        \                     This path component is reserved for updating ❰Optional❱    \n\+        \                     values and not records                                     \n\+        \                                                                                \n\+        \Note that you can update a field named ❰?❱ if you escape the path component,    \n\+        \though:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ { ? = 1 } with `?` = 2 │                                                  \n\+        \    └────────────────────────┘                                                  \n"++prettyTypeMessage (NotAQuestionPath k) = ErrorMessages {..}+  where+    short = "Use ❰?❱ to update an ❰Optional❱ value"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword supports updating ❰Optional❱ values using a path\n\+        \component of ❰?❱, but you provided a path component other than ❰?❱.             \n\+        \                                                                                \n\+        \For example, these are valid uses of ❰with❱ to update an ❰Optional❱ value:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ Some 1 with ? = 2 │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────┐                                             \n\+        \    │ { x = Some 1 } with x.? = 2 │                                             \n\+        \    └─────────────────────────────┘                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ Some 1 with x = True │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                  ⇧                                                             \n\+        \                  This path component should have been ❰?❱                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this path component:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which perhaps should have been ❰?❱.                                         \n"+      where+        txt0 = insert k++prettyTypeMessage ShowConstructorNotOnUnion = ErrorMessages {..}+  where+      short = "ShowConstructorNotOnUnion"+      hints = []+      long = ""++buildBooleanOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages+buildBooleanOperator operator expr0 expr1 = ErrorMessages {..}+  where+    short = "❰" <> txt2 <> "❱ only works on ❰Bool❱s"++    hints = []++    long =+        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Bool❱\n\+        \                                                                                \n\+        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ True " <> txt2 <> " False │                                               \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Bool❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++    txt2 = pretty operator++buildNaturalOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages+buildNaturalOperator operator expr0 expr1 = ErrorMessages {..}+  where+    short = "❰" <> txt2 <> "❱ only works on ❰Natural❱s"++    hints = []++    long =+        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Natural❱\n\+        \                                                                                \n\+        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 3 " <> txt2 <> " 5 │                                                      \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have tried to use an ❰Integer❱, which is " <> _NOT <> " allowed:    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ λ(x : Integer) → λ(y : Integer) → x " <> txt2 <> " y │  Not valid         \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You can only use ❰Natural❱ numbers                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You might have mistakenly used an ❰Integer❱ literal, which is " <> _NOT <> " allowed:\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────┐                                                                 \n\+        \    │ +2 " <> txt2 <> " +2 │  Not valid                                         \n\+        \    └─────────┘                                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You need to remove the leading ❰+❱ to transform them into ❰Natural❱ literals, \n\+        \  like this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 2 " <> txt2 <> " 2 │  Valid                                               \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Natural❱ but instead has type:                    \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++    txt2 = pretty operator++-- | A structured type error that includes context+data TypeError s a = TypeError+    { context     :: Context (Expr s a)+    , current     :: Expr s a+    , typeMessage :: TypeMessage s a+    }++instance (Eq a, Pretty s, Pretty a) => Show (TypeError s a) where+    show = Pretty.renderString . Dhall.Pretty.layout . prettyTypeError++instance (Eq a, Pretty s, Pretty a, Typeable s, Typeable a) => Exception (TypeError s a)++instance (Eq a, Pretty s, Pretty a) => Pretty (TypeError s a) where+    pretty = Pretty.unAnnotate . prettyTypeError++prettyTypeError :: (Eq a, Pretty s, Pretty a) => TypeError s a -> Doc Ann+prettyTypeError (TypeError _ expr msg) =+    (   "\n"+    <>  shortTypeMessage msg <> "\n"+    <>  source+    )+  where+    source = case expr of+        Note s _ -> pretty s+        _        -> mempty++{-| Wrap a type error in this exception type to censor source code and+    `Dhall.Syntax.Text` literals from the error message+-}+data Censored+    = CensoredDetailed (DetailedTypeError Src X)+    | Censored (TypeError Src X)++instance Show Censored where+    show = Pretty.renderString . Dhall.Pretty.layout . Pretty.pretty++instance Exception Censored++instance Pretty Censored where+    pretty (CensoredDetailed (DetailedTypeError e)) =+        pretty (DetailedTypeError (censorTypeError e))+    pretty (Censored e) = pretty (censorTypeError e)++censorTypeError :: TypeError Src a -> TypeError Src a+censorTypeError (TypeError c e m) = TypeError c' e' m'+  where+    c' = fmap Dhall.Core.censorExpression c++    e' = Dhall.Core.censorExpression e++    m' = over messageExpressions Dhall.Core.censorExpression m++-- | @Traversal@ that traverses every `Expr` in a `TypeMessage`+messageExpressions+    :: Applicative f+    => (Expr s a -> f (Expr t b)) -> TypeMessage s a -> f (TypeMessage t b)+messageExpressions f m = case m of+    UnboundVariable a ->+        UnboundVariable <$> pure a+    InvalidInputType a ->+        InvalidInputType <$> f a+    InvalidOutputType a ->+        InvalidOutputType <$> f a+    NotAFunction a b ->+        NotAFunction <$> f a <*> f b+    TypeMismatch a b c d ->+        TypeMismatch <$> f a <*> f b <*> f c <*> f d+    AnnotMismatch a b c ->+        AnnotMismatch <$> f a <*> f b <*> f c+    Untyped ->+        pure Untyped+    MissingListType ->+        pure MissingListType+    MismatchedListElements a b c d ->+        MismatchedListElements <$> pure a <*> f b <*> f c <*> f d+    InvalidListType a ->+        InvalidListType <$> f a+    ListLitInvariant ->+        pure ListLitInvariant+    InvalidSome a b c ->+        InvalidSome <$> f a <*> f b <*> f c+    InvalidPredicate a b ->+        InvalidPredicate <$> f a <*> f b+    IfBranchMismatch a b c d ->+        IfBranchMismatch <$> f a <*> f b <*> f c <*> f d+    InvalidFieldType a b ->+        InvalidFieldType <$> pure a <*> f b+    InvalidAlternativeType a b ->+        InvalidAlternativeType <$> pure a <*> f b+    ListAppendMismatch a b ->+        ListAppendMismatch <$> f a <*> f b+    InvalidDuplicateField a b c ->+        InvalidDuplicateField a <$> f b <*> f c+    MustCombineARecord a b c ->+        MustCombineARecord <$> pure a <*> f b <*> f c+    InvalidRecordCompletion a l ->+        InvalidRecordCompletion a <$> f l+    CompletionSchemaMustBeARecord l r ->+        CompletionSchemaMustBeARecord <$> f l <*> f r+    CombineTypesRequiresRecordType a b ->+        CombineTypesRequiresRecordType <$> f a <*> f b+    DuplicateFieldCannotBeMerged a ->+        pure (DuplicateFieldCannotBeMerged a)+    FieldCollision a ->+        pure (FieldCollision a)+    FieldTypeCollision a ->+        pure (FieldTypeCollision a)+    MustMergeARecord a b ->+        MustMergeARecord <$> f a <*> f b+    MustMergeUnionOrOptional a b ->+        MustMergeUnionOrOptional <$> f a <*> f b+    MustMapARecord a b ->+        MustMapARecord <$> f a <*> f b+    InvalidToMapRecordKind a b ->+        InvalidToMapRecordKind <$> f a <*> f b+    HeterogenousRecordToMap a b c ->+        HeterogenousRecordToMap <$> f a <*> f b <*> f c+    InvalidToMapType a ->+        InvalidToMapType <$> f a+    MapTypeMismatch a b ->+        MapTypeMismatch <$> f a <*> f b+    MissingToMapType ->+        pure MissingToMapType+    UnusedHandler a ->+        UnusedHandler <$> pure a+    MissingHandler e a ->+        MissingHandler <$> pure e <*> pure a+    HandlerInputTypeMismatch a b c ->+        HandlerInputTypeMismatch <$> pure a <*> f b <*> f c+    DisallowedHandlerType a b c d ->+        DisallowedHandlerType <$> pure a <*> f b <*> f c <*> pure d+    HandlerOutputTypeMismatch a b c d ->+        HandlerOutputTypeMismatch <$> pure a <*> f b <*> pure c <*> f d+    MissingMergeType ->+        pure MissingMergeType+    HandlerNotAFunction a b ->+        HandlerNotAFunction <$> pure a <*> f b+    CantAccess a b c ->+        CantAccess <$> pure a <*> f b <*> f c+    CantProject a b c ->+        CantProject <$> pure a <*> f b <*> f c+    CantProjectByExpression a ->+        CantProjectByExpression <$> f a+    DuplicateProjectionLabel a ->+        pure (DuplicateProjectionLabel a)+    MissingField a b ->+        MissingField <$> pure a <*> f b+    MissingConstructor a b ->+        MissingConstructor <$> pure a <*> f b+    ProjectionTypeMismatch a b c d e ->+        ProjectionTypeMismatch <$> pure a <*> f b <*> f c <*> f d <*> f e+    AssertionFailed a b ->+        AssertionFailed <$> f a <*> f b+    NotAnEquivalence a ->+        NotAnEquivalence <$> f a+    IncomparableExpression a ->+        IncomparableExpression <$> f a+    EquivalenceTypeMismatch a b c d ->+        EquivalenceTypeMismatch <$> f a <*> f b <*> f c <*> f d+    NotWithARecord a b ->+        NotWithARecord <$> f a <*> f b+    CantAnd a b ->+        CantAnd <$> f a <*> f b+    CantOr a b ->+        CantOr <$> f a <*> f b+    CantEQ a b ->+        CantEQ <$> f a <*> f b+    CantNE a b ->+        CantNE <$> f a <*> f b+    CantInterpolate a b ->+        CantInterpolate <$> f a <*> f b+    CantTextAppend a b ->+        CantTextAppend <$> f a <*> f b+    CantListAppend a b ->+        CantListAppend <$> f a <*> f b+    CantAdd a b ->+        CantAdd <$> f a <*> f b+    CantMultiply a b ->+        CantMultiply <$> f a <*> f b+    OptionalWithTypeMismatch ->+        pure OptionalWithTypeMismatch+    NotALabelPath ->+        pure NotALabelPath+    NotAQuestionPath k ->+        pure (NotAQuestionPath k)+    ShowConstructorNotOnUnion ->+        pure ShowConstructorNotOnUnion++{-| Newtype used to wrap error messages so that they render with a more+    detailed explanation of what went wrong+-}+newtype DetailedTypeError s a = DetailedTypeError (TypeError s a)+    deriving (Typeable)++instance (Eq a, Pretty s, Pretty a) => Show (DetailedTypeError s a) where+    show = Pretty.renderString . Dhall.Pretty.layout . prettyDetailedTypeError++instance (Eq a, Pretty s, Pretty a, Typeable s, Typeable a) => Exception (DetailedTypeError s a)++instance (Eq a, Pretty s, Pretty a) => Pretty (DetailedTypeError s a) where+    pretty = Pretty.unAnnotate . prettyDetailedTypeError++prettyDetailedTypeError :: (Eq a, Pretty s, Pretty a) => DetailedTypeError s a -> Doc Ann+prettyDetailedTypeError (DetailedTypeError (TypeError ctx expr msg)) =+    (   "\n"+    <>  (   if null (Dhall.Context.toList ctx)+            then ""+            else prettyContext ctx <> "\n\n"+        )+    <>  longTypeMessage msg <> "\n"+    <>  "────────────────────────────────────────────────────────────────────────────────\n"+    <>  "\n"+    <>  source+    )+  where+    prettyKV (key, val) =+        Dhall.Util.snipDoc+            (Dhall.Pretty.Internal.prettyLabel key <> " : " <> Dhall.Pretty.prettyExpr val)++    prettyContext =+            Pretty.vsep+        .   map prettyKV+        .   reverse+        .   Dhall.Context.toList++    source = case expr of+        Note s _ -> pretty s+        _        -> mempty++{-| This function verifies that a custom context is well-formed so that+    type-checking will not loop++    Note that `typeWith` already calls `checkContext` for you on the `Context`+    that you supply+-}+checkContext :: Context (Expr s X) -> Either (TypeError s X) ()+checkContext context =+    case Dhall.Context.match context of+        Nothing ->+            return ()+        Just (x, v, context') -> do+            let shiftedV       =       Dhall.Core.shift (-1) (V x 0)  v+            let shiftedContext = fmap (Dhall.Core.shift (-1) (V x 0)) context'+            _ <- typeWith shiftedContext shiftedV+            return ()++toPath :: (Functor list, Foldable list) => list Text -> Text+toPath ks =+    Text.intercalate "."+        (Foldable.toList (fmap (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome) ks))++duplicateElement :: Ord a => [a] -> Maybe a+duplicateElement = go Data.Set.empty+  where+    go _ [] = Nothing+    go found (x : xs)+        | Data.Set.member x found = Just x+        | otherwise               = go (Data.Set.insert x found) xs
+ src/Dhall/URL.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++module Dhall.URL where++import Data.Text (Text)++import Dhall.Syntax (Directory (..), File (..), Scheme (..), URL (..))++renderComponent :: Text -> Text+renderComponent component = "/" <> component++renderQuery :: Text -> Text+renderQuery query = "?" <> query++renderURL :: URL -> Text+renderURL url =+        schemeText+    <>  authority+    <>  pathText+    <>  queryText+  where+    URL {..} = url++    File {..} = path++    Directory {..} = directory++    schemeText = case scheme of+        HTTP  -> "http://"+        HTTPS -> "https://"++    pathText =+            foldMap renderComponent (reverse components)+        <>  renderComponent file++    queryText = foldMap renderQuery query
+ src/Dhall/Util.hs view
@@ -0,0 +1,291 @@+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++-- | Shared utility functions++module Dhall.Util+    ( snip+    , snipDoc+    , insert+    , _ERROR+    , _WARNING+    , printWarning+    , Censor(..)+    , Input(..)+    , Transitivity(..)+    , OutputMode(..)+    , Output(..)+    , getExpression+    , getExpressionAndHeader+    , getExpressionAndHeaderFromStdinText+    , Header(..)+    , CheckFailed(..)+    , MultipleCheckFailed(..)+    , handleMultipleChecksFailed+    , renderExpression+    ) where++import Control.Exception      (Exception (..))+import Control.Monad.IO.Class (MonadIO (..))+import Data.Bifunctor         (first)+import Data.Either            (lefts)+import Data.Foldable          (toList)+import Data.List.NonEmpty     (NonEmpty (..))+import Data.String            (IsString)+import Data.Text              (Text)+import Dhall.Parser           (Header (..), ParseError)+import Dhall.Pretty           (Ann, CharacterSet)+import Dhall.Src              (Src)+import Dhall.Syntax           (Expr, Import)+import Prettyprinter          (Doc, Pretty)++import qualified Control.Exception+import qualified Data.Text+import qualified Data.Text.IO+import qualified Dhall.Parser+import qualified Dhall.Pretty+import qualified Prettyprinter                 as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty.Terminal+import qualified Prettyprinter.Render.Text     as Pretty.Text+import qualified System.Console.ANSI           as ANSI+import qualified System.IO                     as IO++-- | Utility function to cut out the interior of a large text block+snip :: Text -> Text+snip text+    | length ls <= numberOfLinesOfContext * 2 + 1 = text+    | otherwise =+         if Data.Text.last text == '\n' then preview else Data.Text.init preview+  where+    numberOfLinesOfContext = 20++    ls = Data.Text.lines text++    header = take numberOfLinesOfContext ls++    footer = takeEnd numberOfLinesOfContext ls++    excerpt = filter (Data.Text.any (/= ' ')) (header <> footer)++    leadingSpaces =+        Data.Text.length . Data.Text.takeWhile (== ' ')++    minSpaces = minimum (map leadingSpaces excerpt)++    maxLength = maximum (map Data.Text.length excerpt)++    separator =+            Data.Text.replicate minSpaces " "+        <>  Data.Text.replicate (maxLength - minSpaces) "="++    preview =+            Data.Text.unlines header+        <>  Data.Text.take 80 separator <> "\n"+        <>  Data.Text.unlines footer++{-| Like `snip`, but for `Doc`s++    Note that this has to be opinionated and render ANSI color codes, but that+    should be fine because we don't use this in a non-interactive context+-}+snipDoc :: Doc Ann -> Doc a+snipDoc doc = Pretty.align (Pretty.pretty (snip text))+  where+    stream = Dhall.Pretty.layout doc++    ansiStream = fmap Dhall.Pretty.annToAnsiStyle stream++    text = Pretty.Terminal.renderStrict ansiStream++takeEnd :: Int -> [a] -> [a]+takeEnd n l = go (drop n l) l+  where+    go (_:xs) (_:ys) = go xs ys+    go _ r = r++-- | Function to insert an aligned pretty expression+insert :: Pretty a => a -> Doc Ann+insert expression =+    "↳ " <> Pretty.align (snipDoc (Pretty.pretty expression))++-- | Prefix used for error messages+_ERROR :: IsString string => string+_ERROR = "\ESC[1;31mError\ESC[0m"++-- | Prefix used for error messages+_WARNING :: IsString string => string+_WARNING = "\ESC[1;33mWarning\ESC[0m"++-- | Output a warning message on stderr.+printWarning :: (MonadIO m) => String -> m ()+printWarning message = do+    let warning =+                "\n"+            <> _WARNING+            <> ": "+            <> message++    liftIO $ IO.hPutStrLn IO.stderr warning++get+    :: (String -> Text -> Either ParseError a)+    -> Censor+    -> InputOrTextFromStdin+    -> IO a+get parser censor input = do+    inText <-+        case input of+            Input_ (InputFile file) -> Data.Text.IO.readFile file+            Input_ StandardInput    -> Data.Text.IO.getContents+            StdinText _ text        -> pure text++    let name =+            case input of+                Input_ (InputFile file) -> file+                Input_ StandardInput    -> "(input)"+                StdinText inputName _   -> inputName++    let result = parser name inText++    let censoredResult =+            case censor of+                NoCensor -> result+                Censor   -> first Dhall.Parser.censor result++    throws censoredResult++{-| Convenience utility for converting `Either`-based exceptions to `IO`-based+    exceptions+-}+throws :: (Exception e, MonadIO io) => Either e a -> io a+throws (Left  e) = liftIO (Control.Exception.throwIO e)+throws (Right r) = return r++-- | Set to `Censor` if you want to censor error text that might include secrets+data Censor = NoCensor | Censor++-- | Path to input+data Input = StandardInput | InputFile FilePath deriving (Eq)++-- | Path to input or raw input text, necessary since we can't read STDIN twice+data InputOrTextFromStdin+    = Input_ Input+    | StdinText String Text+    -- ^ @StdinText name text@ where name is a user-friendly name describing the+    -- input expression, used in parsing error messages++{-| Specifies whether or not an input's transitive dependencies should also be+    processed.  Transitive dependencies are restricted to relative file imports.+-}+data Transitivity+    = NonTransitive+    -- ^ Do not process transitive dependencies+    | Transitive+    -- ^ Process transitive dependencies in the same way++-- | Path to output+data Output = StandardOutput | OutputFile FilePath++{-| Some command-line subcommands can either `Write` their input or `Check`+    that the input has already been modified.  This type is shared between them+    to record that choice.+-}+data OutputMode = Write | Check++-- | A check failure corresponding to a single input.+-- This type is intended to be used with 'MultipleCheckFailed' for error+-- reporting.+newtype CheckFailed = CheckFailed { input :: Input }++-- | Exception thrown when the @--check@ flag to a command-line subcommand fails+data MultipleCheckFailed = MultipleCheckFailed+  { command :: Text+  , modified :: Text+  , inputs :: NonEmpty Input+  }++instance Exception MultipleCheckFailed++instance Show MultipleCheckFailed where+    show MultipleCheckFailed{..} =+         _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed on:\n\+        \\n" <> files <>+        "\n\+        \You ran ❰dhall " <> command_ <> " --check❱, but the input appears to have not\n\+        \been " <> modified_ <> " before, or was changed since the last time the input\n\+        \was " <> modified_ <> ".\n"+      where+        modified_ = Data.Text.unpack modified++        command_ = Data.Text.unpack command++        files = unlines . map format $ toList inputs++        format input = case input of+            StandardInput -> "↳ (stdin)"+            InputFile file -> "↳ " <> file++-- | Run IO for multiple inputs, then collate all the check failures before+-- throwing if there was any failure+handleMultipleChecksFailed+    :: (Foldable t, Traversable t)+    => Text+    -> Text+    -> (a -> IO (Either CheckFailed ()))+    -> t a+    -> IO ()+handleMultipleChecksFailed command modified f xs = post =<< mapM f xs+  where+    post results =+        case lefts (toList results) of+            [] -> pure ()+            cf:cfs -> Control.Exception.throwIO $ MultipleCheckFailed+                { command+                , modified+                , inputs = fmap input (cf:|cfs)+                }++-- | Convenient utility for retrieving an expression+getExpression :: Censor -> Input -> IO (Expr Src Import)+getExpression censor = get Dhall.Parser.exprFromText censor . Input_++-- | Convenient utility for retrieving an expression along with its header+getExpressionAndHeader :: Censor -> Input -> IO (Header, Expr Src Import)+getExpressionAndHeader censor =+    get Dhall.Parser.exprAndHeaderFromText censor . Input_++-- | Convenient utility for retrieving an expression along with its header from+-- | text already read from STDIN (so it's not re-read)+getExpressionAndHeaderFromStdinText+    :: Censor -> String -> Text -> IO (Header, Expr Src Import)+getExpressionAndHeaderFromStdinText censor inputName =+    get Dhall.Parser.exprAndHeaderFromText censor . StdinText inputName++{-| Convenient utility to output an expression either to a file+    or to stdout.+-}+renderExpression :: Pretty a => CharacterSet -> Bool -> Maybe FilePath -> Expr Src a -> IO ()+renderExpression characterSet plain output expression = do+    let document = Dhall.Pretty.prettyCharacterSet characterSet expression++    let stream = Dhall.Pretty.layout document++    case output of+        Nothing -> do+            supportsANSI <- ANSI.hSupportsANSI IO.stdout++            let ansiStream =+                    if supportsANSI && not plain+                    then fmap Dhall.Pretty.annToAnsiStyle stream+                    else Pretty.unAnnotateS stream++            Pretty.Terminal.renderIO IO.stdout ansiStream++            Data.Text.IO.putStrLn ""++        Just file_ ->+            IO.withFile file_ IO.WriteMode $ \h -> do+                Pretty.Text.renderIO h stream++                Data.Text.IO.hPutStrLn h ""
+ src/Dhall/Util.hs-boot view
@@ -0,0 +1,5 @@+module Dhall.Util where++import Data.Text (Text)++snip :: Text -> Text
+ src/Dhall/Version.hs view
@@ -0,0 +1,17 @@+{-| Utilities for getting the current version of the Haskell implementation of+    Dhall+-}+module Dhall.Version ( dhallVersion+                     , dhallVersionString+                     ) where++import qualified Data.Version as V+import qualified Paths_dhall  as P++-- | The current `V.Version` of the Haskell implementation+dhallVersion :: V.Version+dhallVersion = P.version++-- | The current version `String` for the Haskell implementation+dhallVersionString :: String+dhallVersionString = V.showVersion dhallVersion
+ tests/Dhall/Test/Dhall.hs view
@@ -0,0 +1,498 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE DeriveAnyClass      #-}+{-# LANGUAGE DeriveFunctor       #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedLists     #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Dhall.Test.Dhall where++import Control.Exception      (SomeException, throwIO, try)+import Data.Either.Validation (validationToEither)+import Data.Fix               (Fix (..))+import Data.Functor.Classes   (Eq1 (..), Show1 (..))+import Data.List.NonEmpty     (NonEmpty (..))+import Data.Maybe             (isJust)+import Data.Scientific        (Scientific)+import Data.Sequence          (Seq)+import Data.Text              (Text)+import Data.Vector            (Vector)+import Data.Void              (Void)+import Dhall                  (FromDhall, ToDhall)+import Dhall.Core             (Expr (..))+import GHC.Generics           (Generic, Rep)+import Numeric.Natural        (Natural)+import System.Timeout         (timeout)+import Test.Tasty+import Test.Tasty.HUnit++import qualified Data.Functor.Classes as Classes+import qualified Data.Text.Lazy+import qualified Dhall+import qualified Dhall.Core+import qualified Dhall.Import+import qualified Dhall.Map+import qualified Dhall.Parser++data ExprF expr+   = LitF Natural+   | AddF expr expr+   | MulF expr expr+   deriving (Eq, Functor, Generic, FromDhall, ToDhall, Show)++instance Eq1 ExprF where+    liftEq _  (LitF aL) (LitF aR) = aL == aR+    liftEq eq (AddF aL bL) (AddF aR bR) = (aL `eq` aR) && (bL `eq` bR)+    liftEq eq (MulF aL bL) (MulF aR bR) = (aL `eq` aR) && (bL `eq` bR)+    liftEq _ _ _ = False++instance Show1 ExprF where+    liftShowsPrec _  _ d (LitF a) = showsPrec d a+    liftShowsPrec sp _ d (AddF a b) = Classes.showsBinaryWith sp sp "AddF" d a b+    liftShowsPrec sp _ d (MulF a b) = Classes.showsBinaryWith sp sp "MulF" d a b++tests :: TestTree+tests =+    testGroup "Input"+     [ shouldShowDetailedTypeError+     , shouldHandleUnionLiteral+     , shouldHaveWorkingRecursiveFromDhall+     , shouldHaveWorkingGenericAuto+     , shouldHandleUnionsCorrectly+     , shouldTreatAConstructorStoringUnitAsEmptyAlternative+     , shouldConvertDhallToHaskellCorrectly+     , shouldConvertHaskellToDhallCorrectly+     , shouldShowCorrectErrorForInvalidDecoderInUnion+     ]++data MyType = MyType { foo :: String , bar :: Natural }++wrongDhallType :: Dhall.Decoder MyType+wrongDhallType = Dhall.Decoder {..}+  where expected = pure $+          Dhall.Core.Record+            ( Dhall.Map.fromList+              [ ( "bar", Dhall.Core.makeRecordField Dhall.Core.Natural)+              , ( "foo", Dhall.Core.makeRecordField Dhall.Core.Text )+              ]+            )+        extract expr = Dhall.typeError expected expr++shouldShowDetailedTypeError :: TestTree+shouldShowDetailedTypeError = testCase "detailed TypeError" $ do+  inputEx :: Either SomeException MyType <-+        try ( Dhall.input wrongDhallType "{  bar = 0, foo = \"foo\" }")++  let expectedMsg =+        "\ESC[1;31mError\ESC[0m: Invalid Dhall.Decoder                                               \n\+        \                                                                                \n\+        \Every Decoder must provide an extract function that does not fail with a type   \n\+        \error if an expression matches the expected type.  You provided a Decoder that  \n\+        \disobeys this contract                                                          \n\+        \                                                                                \n\+        \The Decoder provided has the expected dhall type:                               \n\+        \                                                                                \n\+        \↳ { bar : Natural, foo : Text }\n\+        \                                                                                \n\+        \and it threw a type error during extraction from the well-typed expression:     \n\+        \                                                                                \n\+        \↳ { bar = 0, foo = \"foo\" }\n\+        \                                                                                \n"++  let assertMsg = "The exception message did not match the expected output"++  case inputEx of+    Left ex -> assertEqual assertMsg expectedMsg (show ex)+    Right _ -> fail "The extraction using a wrong type succeeded"++-- https://github.com/dhall-lang/dhall-haskell/issues/915+shouldHandleUnionLiteral :: TestTree+shouldHandleUnionLiteral = testCase "Marshal union literals" $ do+    let example :: Dhall.Decoder Bool+        example = Dhall.union (Dhall.constructor "Test" Dhall.bool)++    _ <- Dhall.input example "< Test : Bool >.Test True"++    return ()++shouldTreatAConstructorStoringUnitAsEmptyAlternative :: TestTree+shouldTreatAConstructorStoringUnitAsEmptyAlternative = testCase "Handle unit constructors" $ do+    let exampleType :: Dhall.Decoder ()+        exampleType = Dhall.union (Dhall.constructor "A" Dhall.unit)++    () <- Dhall.input exampleType "< A >.A"++    let exampleEncoder :: Dhall.Encoder ()+        exampleEncoder = Dhall.unionEncoder (Dhall.encodeConstructor "A")++    let a = Dhall.Core.makeFieldSelection "A"+    Dhall.embed exampleEncoder () @=? Field (Union (Dhall.Map.singleton "A" Nothing)) a++newtype RecursiveType a = RecursiveType (RecursiveType a)+    deriving Generic++instance FromDhall (RecursiveType a)++shouldHaveWorkingRecursiveFromDhall :: TestTree+shouldHaveWorkingRecursiveFromDhall = testGroup "recursive FromDhall instance"+    [ testCase "works for a recursive expression" $ do+        actual <- Dhall.input Dhall.auto "./tests/recursive/expr0.dhall"++        expected @=? actual+    , testCase "roundtrips (one-way)" $ do+        let expr = Dhall.embed Dhall.inject expected+        actual <- either throwIO pure . validationToEither . Dhall.extract Dhall.auto $ expr++        expected @=? actual+    , testCase "passes a shadowing sanity check" $ do+        actual <- Dhall.input Dhall.auto "./tests/recursive/expr1.dhall"++        expected @=? actual+    , testCase "terminate if type is recursive (monomorphic)" $ do+        actual <- timeout (1 * 1000000) $ do+            !typ <- return $ Dhall.expected (Dhall.auto :: Dhall.Decoder (RecursiveType Void))+            return typ+        assertBool "Does not terminate!" $ isJust actual+    , testCase "terminate if type is recursive (polymorphic)" $ do+        actual <- timeout (1 * 1000000) $ do+            !typ <- return $ Dhall.expected (Dhall.auto :: Dhall.Decoder (RecursiveType a))+            return typ+        assertBool "Does not terminate!" $ isJust actual+    ]+  where+    expected =+        Fix+            (AddF+                (Fix (MulF (Fix (LitF 3)) (Fix (LitF 7))))+                (Fix (AddF (Fix (LitF 1)) (Fix (LitF 2))))+            )++data CompilerFlavor3 =+  GHC3 | GHCJS3 | Helium3+  deriving (Generic, Show, Eq)++data CompilerFlavor2 =+  GHC2 | GHCJS2+  deriving (Generic, Show, Eq)++-- https://github.com/dhall-lang/dhall-haskell/issues/926+shouldHaveWorkingGenericAuto :: TestTree+shouldHaveWorkingGenericAuto = testGroup "genericAuto"+  [ testCase "works for a three-constructor enum" $ do+      compiler <- Dhall.input Dhall.genericAuto "< GHC3 | GHCJS3 | Helium3 >.GHC3"+      assertEqual "genericAuto didn't give us what we wanted" GHC3 compiler++  , testCase "works for a two-constructor enum" $ do+      compiler <- Dhall.input Dhall.genericAuto "< GHC2 | GHCJS2 >.GHC2"+      assertEqual "genericAuto didn't give us what we wanted" GHC2 compiler+  ]++data NonEmptyUnion = N0 Bool | N1 Natural | N2 Text+    deriving (Eq, Generic, ToDhall, FromDhall, Show)++data Enum = E0 | E1 | E2+    deriving (Eq, Generic, ToDhall, FromDhall, Show)++data Records+    = R0 {}+    | R1 { a :: () }+    | R2 { x :: Double }+    | R3 { a :: (), b :: () }+    | R4 { x :: Double, y :: Double }+    deriving (Eq, Generic, ToDhall, FromDhall, Show)++data Products = P0 | P1 () | P2 Double | P3 () () | P4 Double Double+    deriving (Eq, Generic, ToDhall, FromDhall, Show)++shouldHandleUnionsCorrectly :: TestTree+shouldHandleUnionsCorrectly =+  testGroup "Handle union literals"+    [ "λ(x : < N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >) → x"+        `shouldPassThroughWrapped` [ N0 True, N1 5, N2 "ABC" ]+    , "λ(x : < E0 | E1 | E2 >) → x"+        `shouldPassThroughWrapped` [ E0, E1, E2 ]+    , "λ(x : < R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >) → x"+        `shouldPassThroughWrapped` [ R0 {}, R1 { a = () }, R2 { x = 1.0 }, R3 { a = (), b = () }, R4 { x = 1.0, y = 2.0 } ]+    , "λ(x : < P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >) → x"+        `shouldPassThroughWrapped` [ P0 , P1 (), P2 1.0, P3 () (), P4 1.0 2.0 ]++    , "λ(x : < N0 : Bool | N1 : Natural | N2 : Text >) → x"+        `shouldPassThroughSmart` [ N0 True, N1 5, N2 "ABC" ]+    , "λ(x : < R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >) → x"+        `shouldPassThroughSmart` [ R0 {}, R1 { a = () }, R2 { x = 1.0 }, R3 { a = (), b = () }, R4 { x = 1.0, y = 2.0 } ]+    , "λ(x : < P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >) → x"+        `shouldPassThroughSmart` [ P0 , P1 (), P2 1.0, P3 () (), P4 1.0 2.0 ]++    , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N0 { _1 = True }"+        `shouldMarshalIntoWrapped` N0 True+    , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N1 { _1 = 5 }"+        `shouldMarshalIntoWrapped` N1 5+    , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N2 { _1 = \"ABC\" }"++        `shouldMarshalIntoWrapped` N2 "ABC"++    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N0 True"+        `shouldMarshalIntoSmart` N0 True+    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N1 5"+        `shouldMarshalIntoSmart` N1 5+    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N2 \"ABC\""+        `shouldMarshalIntoSmart` N2 "ABC"++    , "(< E0 | E1 | E2>).E0" `shouldMarshalIntoWrapped` E0+    , "(< E0 | E1 | E2>).E1" `shouldMarshalIntoWrapped` E1+    , "(< E0 | E1 | E2>).E2" `shouldMarshalIntoWrapped` E2++    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+        `shouldMarshalIntoWrapped` R0+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+        `shouldMarshalIntoWrapped` R1 { a = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0 }"+        `shouldMarshalIntoWrapped` R2 { x = 1.0 }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+        `shouldMarshalIntoWrapped` R3 { a = (), b = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"+        `shouldMarshalIntoWrapped` R4 { x = 1.0, y = 2.0 }++    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+        `shouldMarshalIntoSmart` R0+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+        `shouldMarshalIntoSmart` R1 { a = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0 }"+        `shouldMarshalIntoSmart` R2 { x = 1.0 }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+        `shouldMarshalIntoSmart` R3 { a = (), b = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"+        `shouldMarshalIntoSmart` R4 { x = 1.0, y = 2.0 }++    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+        `shouldMarshalIntoWrapped` P0+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1 { _1 = {=} }"+        `shouldMarshalIntoWrapped` P1 ()+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 { _1 = 1.0 }"+        `shouldMarshalIntoWrapped` P2 1.0+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+        `shouldMarshalIntoWrapped` P3 () ()+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"+        `shouldMarshalIntoWrapped` P4 1.0 2.0++    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+        `shouldMarshalIntoSmart` P0+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1"+        `shouldMarshalIntoSmart` P1 ()+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 1.0"+        `shouldMarshalIntoSmart` P2 1.0+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+        `shouldMarshalIntoSmart` P3 () ()+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"+        `shouldMarshalIntoSmart` P4 1.0 2.0++    , N0 True+        `shouldEmbedAsWrapped`+        "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N0 { _1 = True }"+    , N1 5+        `shouldEmbedAsWrapped`+        "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N1 { _1 = 5 }"+    , N2 "ABC"+        `shouldEmbedAsWrapped`+        "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N2 { _1 = \"ABC\" }"++    , N0 True+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N0 True"+    , N1 5+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N1 5"+    , N2 "ABC"+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N2 \"ABC\""++    , E0 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E0"+    , E1 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E1"+    , E2 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E2"++    , R0 `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+    , R1 { a = () } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+    , R2 { x = 1.0 } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0}"+    , R3 { a = (), b = () } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+    , R4 { x = 1.0, y = 2.0 } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"++    , R0 `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+    , R1 { a = () } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+    , R2 { x = 1.0 } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0}"+    , R3 { a = (), b = () } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+    , R4 { x = 1.0, y = 2.0 } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"++    , P0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+    , P1 () `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1 { _1 = {=} }"+    , P2 1.0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 { _1 = 1.0 }"+    , P3 () () `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+    , P4 1.0 2.0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"++    , P0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+    , P1 () `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1"+    , P2 1.0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 1.0"+    , P3 () () `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+    , P4 1.0 2.0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"+    ]+  where+    smartOptions =+        Dhall.defaultInterpretOptions+            { Dhall.singletonConstructors = Dhall.Smart }++    wrappedOptions =+        Dhall.defaultInterpretOptions+            { Dhall.singletonConstructors = Dhall.Wrapped }++    functionWithOptions+      :: ( Generic a+         , Dhall.GenericToDhall (Rep a)+         , Generic b+         , Dhall.GenericFromDhall b (Rep b)+         )+      => Dhall.InterpretOptions -> Dhall.Decoder (a -> b)+    functionWithOptions options =+      Dhall.function (Dhall.genericToDhallWith options) (Dhall.genericAutoWith options)++    code `shouldPassThroughWrapped` values = testCase "Pass through" $ do+        f <- Dhall.input (functionWithOptions wrappedOptions) code++        values @=? map f values++    code `shouldPassThroughSmart` values = testCase "Pass through" $ do+        f <- Dhall.input (functionWithOptions smartOptions) code++        values @=? map f values++    code `shouldMarshalIntoWrapped` expectedValue = testCase "Marshal" $ do+        actualValue <- Dhall.input (Dhall.genericAutoWith wrappedOptions) code++        expectedValue @=? actualValue++    code `shouldMarshalIntoSmart` expectedValue = testCase "Marshal" $ do+        actualValue <- Dhall.input (Dhall.genericAutoWith smartOptions) code++        expectedValue @=? actualValue++    value `shouldEmbedAsWrapped` expectedCode = testCase "ToDhall" $ do+        parsedExpression <- Dhall.Core.throws (Dhall.Parser.exprFromText "(test)" expectedCode)++        resolvedExpression <- Dhall.Import.assertNoImports parsedExpression++        Dhall.Core.denote resolvedExpression @=? Dhall.embed (Dhall.genericToDhallWith wrappedOptions) value++    value `shouldEmbedAsSmart` expectedCode = testCase "ToDhall" $ do+        parsedExpression <- Dhall.Core.throws (Dhall.Parser.exprFromText "(test)" expectedCode)++        resolvedExpression <- Dhall.Import.assertNoImports parsedExpression++        Dhall.Core.denote resolvedExpression @=? Dhall.embed (Dhall.genericToDhallWith smartOptions) value++shouldConvertDhallToHaskellCorrectly :: TestTree+shouldConvertDhallToHaskellCorrectly =+    testGroup+        "Marshall Dhall code to Haskell"+        [ "True" `correspondsTo` True+        , "False" `correspondsTo` False+        , "2" `correspondsTo` (2 :: Natural)+        , "+2" `correspondsTo` (2 :: Integer)+        , "2.0" `correspondsTo` (2.0 :: Double)+        , "2.0" `correspondsTo` (2.0 :: Scientific)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Lazy.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: String)+        , "Some 2" `correspondsTo` (Just 2 :: Maybe Natural)+        , "None Natural" `correspondsTo` (Nothing :: Maybe Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Seq Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: [Natural])+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Vector Natural)+        , "[] : List Natural" `correspondsTo` ([] :: [Natural])+        , "{=}" `correspondsTo` ()+        , "{ _1 = True, _2 = {=} }" `correspondsTo` (True, ())+        ]+  where+    correspondsTo :: (Eq a, FromDhall a, Show a) => Text -> a -> TestTree+    dhallCode `correspondsTo` expectedHaskellValue =+      testCase "Marshall Dhall code to Haskell" $ do+          actualHaskellValue <- Dhall.input Dhall.auto dhallCode++          expectedHaskellValue @=? actualHaskellValue++shouldConvertHaskellToDhallCorrectly :: TestTree+shouldConvertHaskellToDhallCorrectly =+    testGroup+        "Marshall Haskell to Dhall code"+        [ "True" `correspondsTo` True+        , "False" `correspondsTo` False+        , "2" `correspondsTo` (2 :: Natural)+        , "+2" `correspondsTo` (2 :: Integer)+        , "2.0" `correspondsTo` (2.0 :: Double)+        , "2.0" `correspondsTo` (2.0 :: Scientific)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Lazy.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: String)+        , "Some 2" `correspondsTo` (Just 2 :: Maybe Natural)+        , "None Natural" `correspondsTo` (Nothing :: Maybe Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Seq Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: [Natural])+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Vector Natural)+        , "[] : List Natural" `correspondsTo` ([] :: [Natural])+        , "{=}" `correspondsTo` ()+        , "{ _1 = True, _2 = {=} }" `correspondsTo` (True, ())+        ]+  where+    correspondsTo :: ToDhall a => Text -> a -> TestTree+    expectedDhallCode `correspondsTo` haskellValue =+        testCase "Marshall Haskell to Dhall code" $ do+            let actualDhallCode =+                    Dhall.Core.pretty (Dhall.embed Dhall.inject haskellValue)++            expectedDhallCode @=? actualDhallCode++-- https://github.com/dhall-lang/dhall-haskell/issues/1711+data Issue1711+  = A Bad+  | B+  | C+  | D+  deriving (Generic, Show, FromDhall)++newtype Bad = Bad Text+  deriving (Show)++issue1711Msg :: Text+issue1711Msg = "Issue 1711"++instance FromDhall Bad where+  autoWith _ =+    Dhall.Decoder+      (const (Dhall.extractError issue1711Msg))+      (Dhall.expected Dhall.strictText)++type DhallExtractErrors = Dhall.ExtractErrors Dhall.Parser.Src Void++-- https://github.com/dhall-lang/dhall-haskell/issues/1711+shouldShowCorrectErrorForInvalidDecoderInUnion :: TestTree+shouldShowCorrectErrorForInvalidDecoderInUnion =+  testCase "Correct error is thrown for invalid decoder in union" $ do+    let value = "< B | D | C | A : Text >.A \"\""++    inputEx :: Either DhallExtractErrors Issue1711 <- try (Dhall.input Dhall.auto value)++    let expectedMsg = issue1711Msg++    let assertMsg = "The exception message did not match the expected output"++    case inputEx of+      Left (Dhall.DhallErrors errs) -> case errs of+        (err :| []) -> case err of+          Dhall.TypeMismatch {} -> fail "The extraction using an invalid decoder failed with a type mismatch"+          Dhall.ExpectedTypeError _ -> fail "An error occurred while determining the expected Dhall type"+          Dhall.ExtractError extractError -> assertEqual assertMsg expectedMsg extractError+        _ -> fail "The extraction using an invalid decoder failed with multiple errors"+      Right _ -> fail "The extraction using an invalid decoder succeeded"
+ tests/Dhall/Test/Diff.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Diff where++import Data.Text  (Text)+import Test.Tasty (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Diff                as Diff+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.HUnit          as Tasty.HUnit+import qualified Turtle++diffDirectory :: FilePath+diffDirectory = "./tests/diff"++getTests :: IO TestTree+getTests = do+    diffTests <- Test.Util.discover (Turtle.chars <* "A.dhall") diffTest (Turtle.lstree diffDirectory)++    let testTree = Tasty.testGroup "diff tests" [ diffTests ]++    return testTree++diffTest :: Text -> TestTree+diffTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let leftFile  = Text.unpack (prefix <> "A.dhall")+        let rightFile = Text.unpack (prefix <> "B.dhall")+        let diffFile  = Text.unpack (prefix <> ".txt")++        let toInput file = do+                text <- Text.IO.readFile file+                Core.throws (Parser.exprFromText mempty text)++        leftInput  <- toInput leftFile+        rightInput <- toInput rightFile++        expectedDiffText <- Text.IO.readFile diffFile++        let actualDiffDocument =+                Diff.doc (Diff.diffNormalized leftInput rightInput) <> "\n"++        let actualDiffText = Pretty.Text.renderStrict+                    (Dhall.Pretty.layout actualDiffDocument)++        let message = "The diffed expressions did not match the expected output"++        Tasty.HUnit.assertEqual message expectedDiffText actualDiffText
+ tests/Dhall/Test/DirectoryTree.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.DirectoryTree (tests) where++import Control.Monad+import Data.Either            (partitionEithers)+import Data.Either.Validation+import Dhall.DirectoryTree+import Lens.Micro             (set)+import System.FilePath        ((</>))+import Test.Tasty+import Test.Tasty.HUnit++import qualified Data.List+import qualified Data.Text.IO+import qualified Dhall+import qualified Dhall.Core+import qualified System.Directory         as Directory+import qualified System.FilePath          as FilePath+import qualified System.PosixCompat.Files as Files++tests :: TestTree+tests = testGroup "to-directory-tree"+    [ testGroup "fixpointed"+        [ fixpointedType+        , fixpointedEmpty+        , fixpointedSimple+        , fixpointedAllowPathSeparators+#ifndef mingw32_HOST_OS+        , fixpointedPermissions+        , fixpointedUserGroup+#endif+        ]+    ]++fixpointedType :: TestTree+fixpointedType = testCase "Type is as expected" $ do+    let file = "./tests/to-directory-tree/type.dhall"+    ref <- Dhall.inputExpr file+    expected' <- case directoryTreeType of+        Failure e -> assertFailure $ show e+        Success expr -> return expr+    assertBool "Type mismatch" $ expected' `Dhall.Core.judgmentallyEqual` ref++fixpointedEmpty :: TestTree+fixpointedEmpty = testCase "empty" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-empty.out"+        path = "./tests/to-directory-tree/fixpoint-empty.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?= [Directory outDir]++fixpointedSimple :: TestTree+fixpointedSimple = testCase "simple" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-simple.out"+        path = "./tests/to-directory-tree/fixpoint-simple.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?= Data.List.sort+        [ Directory outDir+        , File $ outDir </> "file"+        , Directory $ outDir </> "directory"+        ]++fixpointedAllowPathSeparators :: TestTree+fixpointedAllowPathSeparators = testCase "allow-path-separators" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-allow-path-separators.out"+        path = "./tests/to-directory-tree/fixpoint-allow-path-separators.dhall"+    entries <- runDirectoryTree True outDir path+    entries @?= Data.List.sort+        [ Directory outDir+        , Directory $ outDir </> "non-existent-1"+        , File $ outDir </> "non-existent-1" </> "file"+        , Directory $ outDir </> "non-existent-2"+        , Directory $ outDir </> "non-existent-2" </> "directory"+        ]++{-+This test is disabled on Windows as it fails due to limitations of the :+    expected: 448+    but got: 438+-}+fixpointedPermissions :: TestTree+fixpointedPermissions = testCase "permissions" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-permissions.out"+        path = "./tests/to-directory-tree/fixpoint-permissions.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?=+        [ Directory outDir+        , File $ outDir </> "file"+        ]+    s <- Files.getFileStatus $ outDir </> "file"+    let mode = Files.fileMode s `Files.intersectFileModes` Files.accessModes+    prettyFileMode mode @?= prettyFileMode Files.ownerModes++fixpointedUserGroup :: TestTree+fixpointedUserGroup = testCase "user and group" $ do+    let file = "./tests/to-directory-tree/fixpoint-usergroup.dhall"+    expr <- Dhall.inputExpr file+    entries <- decodeDirectoryTree expr+    entries @?=+        [ TextFileEntry $ Entry+            { entryName = "ids"+            , entryContent = ""+            , entryUser = Just (UserId 0)+            , entryGroup = Just (GroupId 0)+            , entryMode = Nothing+            }+        , TextFileEntry $ Entry+            { entryName = "names"+            , entryContent = ""+            , entryUser = Just (UserName "user")+            , entryGroup = Just (GroupName "group")+            , entryMode = Nothing+            }+        ]++runDirectoryTree :: Bool -> FilePath -> FilePath -> IO [WalkEntry]+runDirectoryTree allowSeparators outDir path = do+    doesOutDirExist <- Directory.doesDirectoryExist outDir+    when doesOutDirExist $+        Directory.removeDirectoryRecursive outDir+    Directory.createDirectoryIfMissing True outDir++    text <- Data.Text.IO.readFile path+    let inputSettings+            = set Dhall.rootDirectory (FilePath.takeDirectory path)+            . set Dhall.sourceName path+            $ Dhall.defaultInputSettings+    expr <- Dhall.inputExprWithSettings inputSettings text++    toDirectoryTree allowSeparators outDir $ Dhall.Core.denote expr++    Data.List.sort <$> walkFsTree outDir++data WalkEntry+    = Directory FilePath+    | File FilePath+    deriving (Eq, Ord, Show)++walkFsTree :: FilePath -> IO [WalkEntry]+walkFsTree dir = do+    entries <- Directory.listDirectory dir+    (ds, fs) <- fmap partitionEithers $ forM entries $ \path -> do+        let path' = dir </> path+        isDirectory <- Directory.doesDirectoryExist path'+        return $ if isDirectory then Left path' else Right (File path')+    entries' <- traverse walkFsTree ds+    return $ Directory dir : fs <> concat entries'
+ tests/Dhall/Test/Format.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Format where++import Data.Text    (Text)+import Dhall.Parser (Header (..))+import Dhall.Pretty (CharacterSet (..))+import Test.Tasty   (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty              as Pretty+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter             as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.Silver         as Tasty.Silver+import qualified Turtle++getTests :: IO TestTree+getTests = do+    let unicodeFiles = do+            path <- Turtle.lstree "./tests/format"++            let skip = [ "./tests/format/asciiA.dhall" ]++            path `Test.Util.pathNotIn` skip++            return path++    unicodeTests <- Test.Util.discover (Turtle.chars <* "A.dhall") (formatTest Unicode) unicodeFiles++    asciiTests <- Test.Util.discover (Turtle.chars <* "A.dhall") (formatTest ASCII) (pure "./tests/format/asciiA.dhall")++    let testTree =+            Tasty.testGroup "format tests"+                [ unicodeTests+                , asciiTests+                ]++    return testTree++format :: CharacterSet -> (Header, Core.Expr Parser.Src Core.Import) -> Text+format characterSet (Header header, expr) =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet characterSet expr+            <> "\n"++        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream++formatTest :: CharacterSet -> Text -> TestTree+formatTest characterSet prefix =+    let inputFile  = Text.unpack (prefix <> "A.dhall")+        outputFile = Text.unpack (prefix <> "B.dhall")++        action = do+            inputText <- Text.IO.readFile inputFile++            headerAndExpr <- Core.throws (Parser.exprAndHeaderFromText mempty inputText)++            return (format characterSet headerAndExpr)+    in+        Tasty.Silver.goldenVsAction (Text.unpack prefix) outputFile action id
+ tests/Dhall/Test/Freeze.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Freeze where++import Data.Text    (Text)+import Dhall.Freeze (Intent (..), Scope (..))+import Test.Tasty   (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Core       as Core+import qualified Dhall.Freeze     as Freeze+import qualified Dhall.Parser     as Parser+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++freezeDirectoryCached :: FilePath+freezeDirectoryCached = "./tests/freeze/cached"++freezeDirectorySecure :: FilePath+freezeDirectorySecure = "./tests/freeze/secure"++getTests :: IO TestTree+getTests = do+    freezeCachedTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+        (freezeTest freezeDirectoryCached Cache)+        (Turtle.lstree freezeDirectoryCached)+    freezeSecureTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+        (freezeTest freezeDirectorySecure Secure)+        (Turtle.lstree freezeDirectorySecure)++    let testTree = Tasty.testGroup "freeze tests"+            [ Tasty.testGroup "cached" [freezeCachedTests]+            , Tasty.testGroup "secure" [freezeSecureTests]+            ]++    return testTree++freezeTest :: FilePath -> Intent -> Text -> TestTree+freezeTest dir intent prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let inputFile  = Text.unpack (prefix <> "A.dhall")+        let outputFile = Text.unpack (prefix <> "B.dhall")++        inputText <- Text.IO.readFile inputFile++        parsedInput <- Core.throws (Parser.exprFromText mempty inputText)++        actualExpression <- Freeze.freezeExpression dir AllImports intent parsedInput++        let actualText = Core.pretty actualExpression <> "\n"++        expectedText <- Text.IO.readFile outputFile++        let message = "The linted expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedText actualText
+ tests/Dhall/Test/Import.hs view
@@ -0,0 +1,239 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}++module Dhall.Test.Import where++import Control.Exception (SomeException)+import Data.Text         (Text)+import Data.Void         (Void)+import System.FilePath   ((</>))+import Test.Tasty        (TestTree)++import qualified Control.Exception                as Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Text                        as Text+import qualified Data.Text.IO                     as Text.IO+import qualified Dhall.Core                       as Core+import qualified Dhall.Import                     as Import+import qualified Dhall.Parser                     as Parser+import qualified Dhall.Test.Util                  as Test.Util+import qualified System.FilePath                  as FilePath+import qualified System.IO.Temp                   as Temp+import qualified Test.Tasty                       as Tasty+import qualified Test.Tasty.HUnit                 as Tasty.HUnit+import qualified Turtle++#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Network.HTTP.Client     as HTTP+import qualified Network.HTTP.Client.TLS as HTTP+#endif+++importDirectory :: FilePath+importDirectory = "./dhall-lang/tests/import"++getTests :: IO TestTree+getTests = do+    let flakyTests =+            [ -- This test is flaky, occasionally failing with:+              --+              --     Error: Remote host not found+              --+              --     URL: https://test.dhall-lang.org/Bool/package.dhall+              importDirectory </> "success/headerForwardingA.dhall"+            , importDirectory </> "success/unit/RemoteAsTextA.dhall"+            , importDirectory </> "success/unit/SimpleRemoteA.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain1A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain2A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain3A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChainMissingA.dhall"++              -- Skip all tests that reference httpbin.org to avoid clobbering+              -- their servers.  These should eventually be replaced by tests+              -- that depend on an equivalent endpoint on test.dhall-lang.org+              -- instead of httpbin.org.+            , importDirectory </> "failure/customHeadersUsingBoundVariable.dhall"+            , importDirectory </> "failure/originHeadersFromRemote.dhall"+            , importDirectory </> "failure/originHeadersFromRemoteENV.dhall"+            , importDirectory </> "success/customHeadersA.dhall"+            , importDirectory </> "success/noHeaderForwardingA.dhall"+            , importDirectory </> "success/success/originHeadersA.dhall"+            , importDirectory </> "success/originHeadersENV.dhall"+            , importDirectory </> "success/originHeadersImportA.dhall"+            , importDirectory </> "success/originHeadersImportENV.dhall"+            , importDirectory </> "success/originHeadersImportFromEnvA.dhall"+            , importDirectory </> "success/originHeadersImportFromEnvENV.dhall"+            , importDirectory </> "success/originHeadersOverrideA.dhall"+            , importDirectory </> "success/originHeadersOverrideENV.dhall"+            ]++    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest (do+        path <- Turtle.lstree (importDirectory </> "success")++        path `Test.Util.pathNotIn` flakyTests++        return path )++    failureTests <- Test.Util.discover (Turtle.chars <* ".dhall") failureTest (do+        path <- Turtle.lstree (importDirectory </> "failure")++        let expectedSuccesses =+                [ importDirectory </> "failure/unit/DontRecoverCycle.dhall"+                , importDirectory </> "failure/unit/DontRecoverTypeError.dhall"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+                -- We attempt to simulate test.dhall-lang.org, but even so+                -- some tests unexpectedly succeed due to the inadequacy of+                -- the simulation+                , importDirectory </> "failure/unit/cors/OnlySelf.dhall"+                , importDirectory </> "failure/unit/cors/OnlyOther.dhall"+                , importDirectory </> "failure/unit/cors/Null.dhall"+                , importDirectory </> "failure/unit/cors/TwoHops.dhall"+                , importDirectory </> "failure/unit/cors/Empty.dhall"+                , importDirectory </> "failure/unit/cors/NoCORS.dhall"+                , importDirectory </> "failure/originHeadersFromRemote.dhall"+#endif+                ]++        path `Test.Util.pathNotIn` expectedSuccesses+        "ENV.dhall" `Test.Util.pathNotSuffixOf` path++        return path )++    let testTree =+            Tasty.testGroup "import tests"+                [ successTests+                , failureTests+                ]++    return testTree++successTest :: Text -> TestTree+successTest prefix = do+    let inputPath = Text.unpack (prefix <> "A.dhall")++    let expectedPath = Text.unpack (prefix <> "B.dhall")++    let directoryString = FilePath.takeDirectory inputPath++    let expectedFailures =+            [+              -- Importing relative to the home directory works, but I'm too+              -- lazy to mock the home directory for testing purposes+              importDirectory </> "success/unit/ImportRelativeToHome"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+            , importDirectory </> "success/originHeadersImportFromEnv"+            , importDirectory </> "success/originHeadersImport"+            , importDirectory </> "success/originHeadersOverride"+            , importDirectory </> "success/unit/asLocation/RemoteChainEnv"+#endif+            ]++    Test.Util.testCase prefix expectedFailures (do++        text <- Text.IO.readFile inputPath++        expectedText <- Text.IO.readFile expectedPath++        actualExpr <- Core.throws (Parser.exprFromText mempty text)++        expectedExpr <- Core.throws (Parser.exprFromText mempty expectedText)++        let originalCache = "dhall-lang/tests/import/cache"++#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+        let httpManager =+                HTTP.newManager+                    HTTP.tlsManagerSettings+                        { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (120 * 1000 * 1000) }++        let status =+                Import.makeEmptyStatus+                    httpManager+                    (pure Import.envOriginHeaders)+                    directoryString+#else+        let status = Import.emptyStatus directoryString+#endif++        let load =+                State.evalStateT+                    (Test.Util.loadWith actualExpr)+                    status++        let usesCache = [ "hashFromCache"+                        , "unit/asLocation/Hash"+                        , "unit/IgnorePoisonedCache"+                        , "unit/DontCacheIfHash"+                        ]++        let endsIn path' =+                not (null (Turtle.match (Turtle.ends path') (Test.Util.toDhallPath prefix)))++        let buildNewCache = do+                tempdir <- Turtle.managed (Temp.withSystemTempDirectory "dhall-cache")+                Turtle.liftIO (Turtle.cptree originalCache tempdir)+                return tempdir++        let cacheSetup =+                if any endsIn usesCache+                    then do+                        cacheDir <- buildNewCache++                        let set = do+                                m <- Turtle.need "XDG_CACHE_HOME"++                                Turtle.export "XDG_CACHE_HOME" (Turtle.format Turtle.fp cacheDir)++                                return m++                        let reset Nothing = do+                                Turtle.unset "XDG_CACHE_HOME"+                            reset (Just x) = do+                                Turtle.export "XDG_CACHE_HOME" x++                        _ <- Turtle.managed (Exception.bracket set reset)+                        return ()+                else pure ()++        let setup = cacheSetup >> Test.Util.managedTestEnvironment prefix++        let resolve = Turtle.with setup (const load)++        let handler :: SomeException -> IO (Core.Expr Parser.Src Void)+            handler exception = Tasty.HUnit.assertFailure (show exception)++        actualResolved <- Exception.handle handler resolve++        expectedResolved <- Import.assertNoImports expectedExpr++        let actual = Core.normalize actualResolved :: Core.Expr Void Void++        let expected = Core.normalize expectedResolved :: Core.Expr Void Void++        let message =+                "The imported expression did not match the expected output"++        Tasty.HUnit.assertEqual message expected actual)++failureTest :: Text -> TestTree+failureTest prefix = do+    let path = prefix <> ".dhall"++    let pathString = Text.unpack path++    Tasty.HUnit.testCase pathString (do+        actualExpr <- do+          Core.throws (Parser.exprFromText mempty (Test.Util.toDhallPath path))++        let setup = Test.Util.managedTestEnvironment prefix++        let run = Exception.catch @SomeException+              (Test.Util.load actualExpr >> return True)+              (\_ -> return False)++        succeeded <- Turtle.with setup (const run)++        if succeeded+            then fail "Import should have failed, but it succeeds"+            else return () )
+ tests/Dhall/Test/Lint.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Lint where++import Data.Text    (Text)+import Dhall.Parser (Header (..))+import Test.Tasty   (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Lint                as Lint+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty              as Pretty+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter             as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.HUnit          as Tasty.HUnit+import qualified Turtle++lintDirectory :: FilePath+lintDirectory = "./tests/lint"++getTests :: IO TestTree+getTests = do+    lintTests <- Test.Util.discover (Turtle.chars <* "A.dhall") lintTest (Turtle.lstree lintDirectory)++    let testTree = Tasty.testGroup "lint tests" [ lintTests ]++    return testTree++format :: Header -> Core.Expr Parser.Src Core.Import -> Text+format (Header header) expr =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet Pretty.Unicode expr+            <> "\n"++        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream++lintTest :: Text -> TestTree+lintTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let inputFile  = Text.unpack (prefix <> "A.dhall")+        let outputFile = Text.unpack (prefix <> "B.dhall")++        inputText <- Text.IO.readFile inputFile++        (header, parsedInput) <- Core.throws (Parser.exprAndHeaderFromText mempty inputText)++        let actualExpression = Lint.lint parsedInput++        let actualText = format header actualExpression++        expectedText <- Text.IO.readFile outputFile++        let message = "The linted expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedText actualText
+ tests/Dhall/Test/Main.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE CPP #-}+module Main where++import System.FilePath ((</>))+import Test.Tasty      (TestTree)++import qualified Dhall.Test.Dhall+import qualified Dhall.Test.Diff+import qualified Dhall.Test.DirectoryTree+import qualified Dhall.Test.Format+import qualified Dhall.Test.Freeze+import qualified Dhall.Test.Import+import qualified Dhall.Test.Lint+import qualified Dhall.Test.Normalization+import qualified Dhall.Test.Package+import qualified Dhall.Test.Parser+import qualified Dhall.Test.QuickCheck+import qualified Dhall.Test.Regression+import qualified Dhall.Test.Schemas+import qualified Dhall.Test.SemanticHash+#ifndef CROSS+import qualified Dhall.Test.TH+#endif+import qualified Dhall.Test.Tags+import qualified Dhall.Test.Tutorial+import qualified Dhall.Test.TypeInference+import qualified GHC.IO.Encoding+import qualified System.Directory+import qualified System.Environment+import qualified System.IO+import qualified Test.Tasty++getAllTests :: IO TestTree+getAllTests = do+    normalizationTests <- Dhall.Test.Normalization.getTests++    parsingTests <- Dhall.Test.Parser.getTests++    formattingTests <- Dhall.Test.Format.getTests++    typeinferenceTests <- Dhall.Test.TypeInference.getTests++    importingTests <- Dhall.Test.Import.getTests++    lintTests <- Dhall.Test.Lint.getTests++    tagsTests <- Dhall.Test.Tags.getTests++    diffTests <- Dhall.Test.Diff.getTests++    semanticHashTests <- Dhall.Test.SemanticHash.getTests++    freezeTests <- Dhall.Test.Freeze.getTests++    schemaTests <- Dhall.Test.Schemas.getTests++    let testTree =+            Test.Tasty.testGroup "Dhall Tests"+                [ normalizationTests+                , parsingTests+                , importingTests+                , typeinferenceTests+                , formattingTests+                , lintTests+                , diffTests+                , semanticHashTests+                , tagsTests+                , freezeTests+                , schemaTests+                , Dhall.Test.DirectoryTree.tests+                , Dhall.Test.Regression.tests+                , Dhall.Test.Tutorial.tests+                , Dhall.Test.QuickCheck.tests+                , Dhall.Test.Dhall.tests+#ifndef CROSS+                , Dhall.Test.TH.tests+#endif+                , Dhall.Test.Package.tests+                ]++    return testTree++main :: IO ()+main = do+    GHC.IO.Encoding.setLocaleEncoding System.IO.utf8++    pwd <- System.Directory.getCurrentDirectory++    System.Environment.setEnv "XDG_CACHE_HOME" (pwd </> ".cache")++    System.Environment.setEnv "DHALL_TEST_VAR" "6 * 7"++    -- Make test failures easier to find by eliding the successes.+    -- https://github.com/feuerbach/tasty/issues/273#issuecomment-657054281+    System.Environment.setEnv "TASTY_HIDE_SUCCESSES" "true"++    allTests <- getAllTests++    Test.Tasty.defaultMain allTests
+ tests/Dhall/Test/Normalization.hs view
@@ -0,0 +1,214 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Normalization where++import Data.Text       (Text)+import Data.Void       (Void)+import Dhall.Core      (Expr (..), Var (..), throws)+import System.FilePath ((</>))+import Test.Tasty      (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Context    as Context+import qualified Dhall.Core       as Core+import qualified Dhall.Import     as Import+import qualified Dhall.Parser     as Parser+import qualified Dhall.Test.Util  as Test.Util+import qualified Dhall.TypeCheck  as TypeCheck+import qualified System.FilePath  as FilePath+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++normalizationDirectory :: FilePath+normalizationDirectory = "./dhall-lang/tests/normalization/success"++unitDirectory :: FilePath+unitDirectory = normalizationDirectory </> "unit/"++getTests :: IO TestTree+getTests = do+    let pattern = Turtle.chars <* "A.dhall"++    let normalizationFiles = do+            path <- FilePath.normalise <$> Turtle.lstree normalizationDirectory++            unitDirectory `Test.Util.pathNotPrefixOf` path++            return path++    betaNormalizationTests <- Test.Util.discover pattern betaNormalizationTest normalizationFiles++    alphaNormalizationTests <-+        Test.Util.discover pattern alphaNormalizationTest+            (Turtle.lstree "./dhall-lang/tests/alpha-normalization/success/")++    let unitTestFiles = Turtle.lstree unitDirectory++    unitTests <- Test.Util.discover pattern unitTest unitTestFiles++    let testTree =+            Tasty.testGroup "normalization"+                [ Tasty.testGroup "beta-normalization"+                    [ betaNormalizationTests+                    ]+                , Tasty.testGroup "unit tests"+                    [ unitTests+                    ]+                , Tasty.testGroup "alpha-normalization"+                    [ alphaNormalizationTests+                    ]+                , customization+                ]++    return testTree++customization :: TestTree+customization =+    Tasty.testGroup "customization"+        [ simpleCustomization+        , nestedReduction+        ]++simpleCustomization :: TestTree+simpleCustomization = Tasty.HUnit.testCase "simpleCustomization" $ do+    let tyCtx =+            Context.insert+                "min"+                (Pi mempty "_" Natural (Pi mempty "_" Natural Natural))+                Context.empty++        valCtx e =+            case e of+                App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y) ->+                    pure (Just (NaturalLit (min x y)))+                _ ->+                    pure Nothing++    e <- Test.Util.codeWith tyCtx "min (min 11 12) 8 + 1"++    Test.Util.assertNormalizesToWith valCtx e "9"++nestedReduction :: TestTree+nestedReduction = Tasty.HUnit.testCase "doubleReduction" $ do+    minType        <- Context.insert "min"        <$> Test.Util.code "Natural → Natural → Natural"+    fiveorlessType <- Context.insert "fiveorless" <$> Test.Util.code "Natural → Natural"+    wurbleType     <- Context.insert "wurble"     <$> Test.Util.code "Natural → Natural"++    let tyCtx = minType . fiveorlessType . wurbleType $ Context.empty++        valCtx e =+            case e of+                App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y) ->+                    pure (Just (NaturalLit (min x y)))+                App (Var (V "wurble" 0)) (NaturalLit x) ->+                    pure (Just (App (Var (V "fiveorless" 0)) (NaturalPlus (NaturalLit x) (NaturalLit 2))))+                App (Var (V "fiveorless" 0)) (NaturalLit x) ->+                    pure (Just (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalPlus (NaturalLit 3) (NaturalLit 2))))+                _ ->+                    pure Nothing++    e <- Test.Util.codeWith tyCtx "wurble 6"++    Test.Util.assertNormalizesToWith valCtx e "5"++alphaNormalizationTest :: Text -> TestTree+alphaNormalizationTest prefix = do+    let prefixString = Text.unpack prefix++    Tasty.HUnit.testCase prefixString $ do+        let actualPath   = prefixString <> "A.dhall"+        let expectedPath = prefixString <> "B.dhall"++        actualCode   <- Text.IO.readFile actualPath+        expectedCode <- Text.IO.readFile expectedPath++        actualExpr <- throws (Parser.exprFromText mempty actualCode)++        actualResolved <- Import.assertNoImports actualExpr++        let actualNormalized = Core.alphaNormalize (Core.denote actualResolved)++        expectedExpr <- throws (Parser.exprFromText mempty expectedCode)++        expectedResolved <- Import.assertNoImports expectedExpr++        let expectedNormalized = Core.denote expectedResolved :: Expr Void Void++        let message =+                "The alpha-normalized expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedNormalized actualNormalized++{- Unit tests don't type-check, so we only verify that they normalize to the+   expected output+-}+unitTest :: Text -> TestTree+unitTest prefix = do+    let expectedFailures = []++    let prefixString = Text.unpack prefix++    Test.Util.testCase prefix expectedFailures $ do+        let actualPath   = prefixString <> "A.dhall"+        let expectedPath = prefixString <> "B.dhall"++        actualCode   <- Text.IO.readFile actualPath+        expectedCode <- Text.IO.readFile expectedPath++        actualExpr <- throws (Parser.exprFromText mempty actualCode)++        actualResolved <- Import.assertNoImports actualExpr++        let actualNormalized =+                Core.alphaNormalize+                    (Core.normalize actualResolved :: Expr Void Void)++        expectedExpr <- throws (Parser.exprFromText mempty expectedCode)++        expectedResolved <- Import.assertNoImports expectedExpr++        let expectedNormalized =+                Core.alphaNormalize (Core.denote expectedResolved)++        let message =+                "The normalized expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedNormalized actualNormalized++betaNormalizationTest :: Text -> TestTree+betaNormalizationTest prefix = do+    let prefixString = Text.unpack prefix++    Tasty.HUnit.testCase prefixString $ do+        let actualCode = Test.Util.toDhallPath (prefix <> "A.dhall")++        let expectedPath = prefixString <> "B.dhall"+        expectedCode <- Text.IO.readFile expectedPath++        actualExpr <- throws (Parser.exprFromText mempty actualCode)++        actualResolved <- Import.load actualExpr++        _ <- throws (TypeCheck.typeOf actualResolved)++        let actualNormalized =+                Core.alphaNormalize+                    (Core.normalize actualResolved :: Expr Void Void)++        expectedExpr <- throws (Parser.exprFromText mempty expectedCode)++        expectedResolved <- Import.load expectedExpr++        _ <- throws (TypeCheck.typeOf expectedResolved)++        -- Use `denote` instead of `normalize` to enforce that the expected+        -- expression is already in normal form+        let expectedNormalized =+                Core.alphaNormalize (Core.denote expectedResolved)++        let message =+                "The beta-normalized expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedNormalized actualNormalized
+ tests/Dhall/Test/Package.hs view
@@ -0,0 +1,270 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Package where++import           Control.Exception  (Exception, displayException, finally, try)+import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Void          (Void)+import           Dhall.Core+    ( Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , makeRecordField+    )+import qualified Dhall.Map          as Map+import           Dhall.Package+import           Lens.Micro         (set)+import qualified System.Directory   as Directory+import           System.FilePath    ((</>))+import           Test.Tasty+import           Test.Tasty.HUnit++tests :: TestTree+tests = testGroup "Package"+    [ packagePackageFile+    , packageCustomPackageFile+    , packageSingleFile+    , packageEmptyDirectory+    , packageSingleDirectory+    , packageNested+    , packageRecursive+    , packageMissingFile+    , packageFilesDifferentDirs+    , packageIncompatibleFiles+    ]++packagePackageFile :: TestTree+packagePackageFile = testCase "package file" $ do+    let path = "./tests/package" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit Map.empty++    (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/package.dhall" :| [])+    assertEqual "path" path output+    assertEqual "content" package expr++packageCustomPackageFile :: TestTree+packageCustomPackageFile = testCase "custom package file" $ do+    let path = "./tests/package" </> "custom.dhall"++    let package :: Expr Void Import+        package = RecordLit $+            Map.singleton "package" $ makeRecordField $ Embed packageDhall++    let options :: Options+        options = set packageFileName "custom.dhall" defaultOptions++    (output, expr) <- getPackagePathAndContent options ("./tests/package/package.dhall" :| [])+    assertEqual "path" path output+    assertEqual "content" package expr++packageSingleFile :: TestTree+packageSingleFile = testCase "single file" $ do+    let path = "./tests/package/dir" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit $+            Map.singleton "test" $ makeRecordField $ Embed testDhall++    (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/dir/test.dhall" :| [])+    assertEqual "path" path output+    assertEqual "content" package expr++packageEmptyDirectory :: TestTree+packageEmptyDirectory = testCase "empty directory" $ do+    let path = "./tests/package/empty" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit Map.empty++    (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/empty" :| [])+    assertEqual "path" path output+    assertEqual "content" package expr++packageSingleDirectory :: TestTree+packageSingleDirectory = testCase "single directory" $ do+    let path = "./tests/package/dir" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit $ Map.singleton "test" $+            makeRecordField $ Embed testDhall++    (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/dir" :| [])+    assertEqual "path" path output+    assertEqual "content" package expr++packageNested :: TestTree+packageNested = testCase "nested files" $ do+    let path = "./tests/package" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit $ Map.fromList+            [ ("dir", makeRecordField $ RecordLit $ Map.fromList+                [ ("test", makeRecordField $ Embed dirTestDhall)+                ]+              )+            , ("other", makeRecordField $ Embed otherPackageDhall)+            , ("test", makeRecordField $ Embed testDhall)+            ]++    (output, expr) <- getPackagePathAndContent defaultOptions+        ( "./tests/package/test.dhall" :|+        [ "./tests/package/dir/test.dhall"+        , "./tests/package/other/package.dhall"+        ])+    assertEqual "path" path output+    assertEqual "content" package expr++packageRecursive :: TestTree+packageRecursive = testCase "recursively create subpackages" $ removePackagesAfter $ do+    let path = "./tests/package/dir" </> "package.dhall"++    let package :: Expr Void Import+        package = RecordLit $ Map.fromList+            [ ("subdirectory1", makeRecordField $ Embed subdirectoryPackageDhall1)+            , ("subdirectory2", makeRecordField $ Embed subdirectoryPackageDhall2)+            , ("test", makeRecordField $ Embed testDhall)+            ]++    let options :: Options+        options = set packagingMode RecursiveSubpackages defaultOptions++    (output, expr) <- getPackagePathAndContent options+        ( "./tests/package/dir" :| [] )+    assertEqual "path" path output+    assertEqual "content" package expr+    where+        removePackagesAfter :: IO a -> IO a+        removePackagesAfter action = action `finally` do+            Directory.removePathForcibly "./tests/package/dir/subdirectory1/package.dhall"+            Directory.removePathForcibly "./tests/package/dir/subdirectory2/package.dhall"++packageMissingFile :: TestTree+packageMissingFile = testCase "missing file" $ do+    let action :: IO (FilePath, Expr Void Import)+        action = getPackagePathAndContent defaultOptions ("./tests/package/missing.dhall" :| [])++    assertThrow action $ \case+        InvalidPath "./tests/package/missing.dhall" -> True+        _ -> False++packageFilesDifferentDirs :: TestTree+packageFilesDifferentDirs = testCase "files from different directories" $ do+    let action :: IO (FilePath, Expr Void Import)+        action = getPackagePathAndContent defaultOptions+            ( "./tests/package/dir/test.dhall" :|+            [ "./tests/package/test/test.dhall"+            ])++    assertThrow action $ \case+        AmbiguousOutputDirectory "./tests/package/dir" "./tests/package/test" -> True+        _ -> False++packageIncompatibleFiles :: TestTree+packageIncompatibleFiles = testCase "files that are incompatible" $ do+    let action :: IO (FilePath, Expr Void Import)+        action = getPackagePathAndContent defaultOptions+            ( "./tests/package/test.dhall" :|+            [ "./tests/package/test/test.dhall"+            ])++    assertThrow action $ \case+        IncompatiblePaths xs -> xs == [ testDhall , testTestDhall ]+        _ -> False++packageDhall :: Import+packageDhall = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here File+            { directory = Directory []+            , file = "package.dhall"+            }+        }+    , importMode = Code+    }++testDhall :: Import+testDhall = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here File+            { directory = Directory []+            , file = "test.dhall"+            }+        }+    , importMode = Code+    }++dirTestDhall :: Import+dirTestDhall = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here $ File+            { directory = Directory {components = ["dir"]}+            , file = "test.dhall"+            }+        }+    , importMode = Code+    }++otherPackageDhall :: Import+otherPackageDhall = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here $ File+            { directory = Directory {components = ["other"]}+            , file = "package.dhall"+            }+        }+    , importMode = Code+    }++subdirectoryPackageDhall1 :: Import+subdirectoryPackageDhall1 = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here $ File+            { directory = Directory {components = ["subdirectory1"]}+            , file = "package.dhall"}+            }+        , importMode = Code+        }++subdirectoryPackageDhall2 :: Import+subdirectoryPackageDhall2 = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here $ File+            { directory = Directory {components = ["subdirectory2"]}+            , file = "package.dhall"}+            }+        , importMode = Code+        }++testTestDhall :: Import+testTestDhall = Import+    { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local Here (File+            { directory = Directory {components = ["test"]}+            , file = "test.dhall"+            })+        }+    , importMode = Code+    }++assertThrow :: (Exception e, Show a) => IO a -> (e -> Bool) -> IO ()+assertThrow k p = do+    result <- try k+    case result of+        Left e | p e -> return ()+        Left e -> assertFailure $ "Predicate did not match: " <> displayException e+        Right result' -> assertFailure $ "Expected exception, but got: " <> show result'
+ tests/Dhall/Test/Parser.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Parser where++import Data.Text       (Text)+import Data.Void       (Void)+import Dhall.Core      (Binding (..), Expr (..), Import, Var (..))+import System.FilePath ((</>))+import Test.Tasty      (TestTree)++import qualified Control.Monad        as Monad+import qualified Data.Bifunctor       as Bifunctor+import qualified Data.ByteString      as ByteString+import qualified Data.ByteString.Lazy as ByteString.Lazy+import qualified Data.Text            as Text+import qualified Data.Text.Encoding   as Text.Encoding+import qualified Data.Text.IO         as Text.IO+import qualified Dhall.Binary         as Binary+import qualified Dhall.Core           as Core+import qualified Dhall.Parser         as Parser+import qualified Dhall.Test.Util      as Test.Util+import qualified Test.Tasty           as Tasty+import qualified Test.Tasty.HUnit     as Tasty.HUnit+import qualified Text.Printf          as Printf+import qualified Turtle++parseDirectory :: FilePath+parseDirectory = "./dhall-lang/tests/parser"++binaryDecodeDirectory :: FilePath+binaryDecodeDirectory = "./dhall-lang/tests/binary-decode"++getTests :: IO TestTree+getTests = do+    let successFiles = Turtle.lstree (parseDirectory </> "success")++    successTests <-+        Test.Util.discover (Turtle.chars <* "A.dhall") shouldParse successFiles++    let failureFiles = Turtle.lstree (parseDirectory </> "failure")++    failureTests <-+        Test.Util.discover (Turtle.chars <> ".dhall") shouldNotParse failureFiles++    let binaryDecodeSuccessFiles =+            Turtle.lstree (binaryDecodeDirectory </> "success")++    binaryDecodeSuccessTests <-+        Test.Util.discover (Turtle.chars <* "A.dhallb") shouldDecode binaryDecodeSuccessFiles++    let binaryDecodeFailureFiles = Turtle.lstree (binaryDecodeDirectory </> "failure")++    binaryDecodeFailureTests <-+        Test.Util.discover (Turtle.chars <* ".dhallb") shouldNotDecode binaryDecodeFailureFiles++    let testTree =+            Tasty.testGroup "parser tests"+                [ successTests+                , failureTests+                , internalTests+                , binaryDecodeSuccessTests+                , binaryDecodeFailureTests+                ]++    return testTree++internalTests :: TestTree+internalTests =+    Tasty.testGroup "internal"+        [ notesInLetInLet ]++notesInLetInLet :: TestTree+notesInLetInLet =+    Tasty.HUnit.testCase "Notes in let-in-let" $ do+        let code = "let x = 0 let y = 1 in let z = 2 in x"++        expression <- Core.throws (Parser.exprFromText mempty code)++        let simplifyNotes = Bifunctor.first Parser.srcText++        let expected =+                (Note code+                  (Let+                    (Binding+                      (Just " ")+                      "x"+                      (Just " ")+                      Nothing+                      (Just " ")+                      (Note "0 " (Note "0" (NaturalLit 0)))+                    )+                    -- This 'Let' isn't wrapped in a 'Note'!+                    (Let+                      (Binding+                        (Just " ")+                        "y"+                        (Just " ")+                        Nothing+                        (Just " ")+                        (Note "1 " (Note "1" (NaturalLit 1)))+                      )+                      (Note "let z = 2 in x"+                        (Let+                          (Binding+                            (Just " ")+                            "z"+                            (Just " ")+                            Nothing+                            (Just " ")+                            (Note "2 " (Note "2" (NaturalLit 2)))+                          )+                          (Note "x" (Var (V "x" 0)))+                        )+                      )+                    )+                  )+                )++        let msg = "Unexpected parse result"++        Tasty.HUnit.assertEqual msg expected (simplifyNotes expression)++shouldParse :: Text -> TestTree+shouldParse path = do+    let expectedFailures = []++    let pathString = Text.unpack path++    Test.Util.testCase path expectedFailures $ do+        text <- Text.IO.readFile (pathString <> "A.dhall")++        encoded <- ByteString.Lazy.readFile (pathString <> "B.dhallb")++        expression <- case Parser.exprFromText mempty text of+            Left  exception  -> Tasty.HUnit.assertFailure (show exception)+            Right expression -> return expression++        let bytes = Binary.encodeExpression (Core.denote expression)++        let render =+                  concatMap (Printf.printf "%02x ")+                . ByteString.Lazy.unpack++        Monad.unless (encoded == bytes) $ do+            let message = "The expected CBOR representation doesn't match the actual one\n"+                          ++ "expected: " ++ render encoded ++ "\n but got: " ++ render bytes+                          ++ "\n expr: " ++ show (Core.denote expression :: Expr Void Import)++            Tasty.HUnit.assertFailure message+++shouldNotParse :: Text -> TestTree+shouldNotParse path = do+    let expectedFailures =+            [ parseDirectory </> "failure/spacing/LetNoSpace4.dhall"+            ]++    let pathString = Text.unpack path++    Test.Util.testCase path expectedFailures (do+        bytes <- ByteString.readFile pathString++        case Text.Encoding.decodeUtf8' bytes of+            Left _ -> return ()+            Right text ->+                case Parser.exprFromText mempty text of+                    Left  _ -> return ()+                    Right _ -> Tasty.HUnit.assertFailure "Unexpected successful parse" )++shouldDecode :: Text -> TestTree+shouldDecode pathText = do+    let expectedFailures =+          [ {- Note that this test actually successfully decodes the value, but+               mistakenly decodes the value to `_` instead of `x`.  This is+               because the 55799 tag causes normal decoding to fail, so it falls+               back to treating the `"x"` as a version tag instead of a label.++               Either way, fixing 55799 decoding would cause this test to pass+               again.+            -}+            binaryDecodeDirectory </> "success/unit/SelfDescribeCBORX2"+          , binaryDecodeDirectory </> "success/unit/SelfDescribeCBORX3"+          ]++    let pathString = Text.unpack pathText++    Test.Util.testCase pathText expectedFailures (do+        bytes <- ByteString.Lazy.readFile (pathString <> "A.dhallb")++        decodedExpression <- case Binary.decodeExpression bytes of+            Left exception ->+                Tasty.HUnit.assertFailure (show exception)+            Right decodedExpression ->+                return decodedExpression++        text <- Text.IO.readFile (pathString <> "B.dhall")++        parsedExpression <- Core.throws (Parser.exprFromText mempty text)++        let strippedExpression :: Expr Void Import+            strippedExpression = Core.denote parsedExpression++        let message =+                "The decoded expression didn't match the parsed expression"++        Tasty.HUnit.assertEqual message strippedExpression decodedExpression )++shouldNotDecode :: Text -> TestTree+shouldNotDecode pathText = do+    let expectedFailures = []++    let pathString = Text.unpack pathText++    Test.Util.testCase pathText expectedFailures (do+        bytes <- ByteString.Lazy.readFile (pathString <> ".dhallb")++        case Binary.decodeExpression bytes :: Either Binary.DecodingFailure (Expr Void Import) of+            Left _ -> return ()+            Right _ -> Tasty.HUnit.assertFailure "Unexpected successful decode" )
+ tests/Dhall/Test/QuickCheck.hs view
@@ -0,0 +1,802 @@+-- TODO: update because we added ShowConstructor constructor to Expr in Dhall.Syntax++{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE NamedFieldPuns      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++-- Build without optimizations to prevent out-of-memory situations in Hydra CI+{-# OPTIONS_GHC -O0 #-}++module Dhall.Test.QuickCheck where++import Data.Either            (isRight)+import Data.Either.Validation (Validation (..))+import Data.Text              (Text)+import Data.Void              (Void)+import Dhall+    ( FromDhall (..)+    , ToDhall (..)+    , Vector+    , auto+    , embed+    , extract+    , inject+    )+import Dhall.Core+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Directory (..)+    , Expr (..)+    , FieldSelection (..)+    , File (..)+    , FilePrefix (..)+    , FunctionBinding (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Scheme (..)+    , URL (..)+    , Var (..)+    , WithComponent (..)+    )+import Dhall.Map              (Map)++import Data.Functor.Identity     (Identity (..))+import Data.Proxy                (Proxy (..))+import Data.Typeable             (Typeable, typeRep)+import Dhall.Parser              (Header (..), createHeader)+import Dhall.Pretty              (CharacterSet (..))+import Dhall.Set                 (Set)+import Dhall.Src                 (Src (..))+import Dhall.Test.Format         (format)+import Dhall.TypeCheck           (TypeError, Typer)+import Generic.Random            (ConstrGen (..), W, Weights, (%), (:+) (..))+import Test.QuickCheck+    ( Arbitrary (..)+    , Gen+    , NonNegative (..)+    , Positive (..)+    , Property+    , genericShrink+    , suchThat+    , (===)+    , (==>)+    )+import Test.QuickCheck.Instances ()+import Test.Tasty                (TestTree)+import Test.Tasty.QuickCheck     (QuickCheckTests (..))+import Text.Megaparsec           (Pos, SourcePos (..))++import qualified Control.Spoon+import qualified Data.Char+import qualified Data.Foldable         as Foldable+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.HashSet+import qualified Data.List+import qualified Data.Map+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.SpecialValues+import qualified Data.Text             as Text+import qualified Data.Time             as Time+import qualified Dhall.Binary+import qualified Dhall.Context+import qualified Dhall.Core+import qualified Dhall.Diff+import qualified Dhall.Map+import qualified Dhall.Parser          as Parser+import qualified Dhall.Set+import qualified Dhall.TypeCheck+import qualified Generic.Random+import qualified Lens.Micro            as Lens+import qualified Numeric.Natural       as Nat+import qualified Test.QuickCheck+import qualified Test.Tasty+import qualified Test.Tasty.QuickCheck+import qualified Text.Megaparsec       as Megaparsec++instance (Arbitrary a, Ord a) => Arbitrary (Set a) where+  arbitrary = Dhall.Set.fromList <$> arbitrary+  shrink = map Dhall.Set.fromList . shrink . Dhall.Set.toList++lift0 :: a -> Gen a+lift0 = pure++lift1 :: Arbitrary a => (a -> b) -> Gen b+lift1 f = f <$> arbitrary++lift2 :: (Arbitrary a, Arbitrary b) => (a -> b -> c) -> Gen c+lift2 f = f <$> arbitrary <*> arbitrary++lift3 :: (Arbitrary a, Arbitrary b, Arbitrary c) => (a -> b -> c -> d) -> Gen d+lift3 f = f <$> arbitrary <*> arbitrary <*> arbitrary++lift4+    :: (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d)+    => (a -> b -> c -> d -> e) -> Gen e+lift4 f = f <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary++lift5+    :: ( Arbitrary a+       , Arbitrary b+       , Arbitrary c+       , Arbitrary d+       , Arbitrary e+       )+    => (a -> b -> c -> d -> e -> f) -> Gen f+lift5 f =+      f <$> arbitrary+        <*> arbitrary+        <*> arbitrary+        <*> arbitrary+        <*> arbitrary++lift6+    :: ( Arbitrary a+       , Arbitrary b+       , Arbitrary c+       , Arbitrary d+       , Arbitrary e+       , Arbitrary f+       )+    => (a -> b -> c -> d -> e -> f -> g) -> Gen g+lift6 f =+      f <$> arbitrary+        <*> arbitrary+        <*> arbitrary+        <*> arbitrary+        <*> arbitrary+        <*> arbitrary++integer :: (Arbitrary a, Num a) => Gen a+integer =+    Test.QuickCheck.frequency+        [ (7, arbitrary)+        , (1, fmap (\x -> x + (2 ^ (64 :: Int))) arbitrary)+        , (1, fmap (\x -> x - (2 ^ (64 :: Int))) arbitrary)+        ]++whitespace :: Gen Text+whitespace = do+      let commentChar =+              Test.QuickCheck.frequency+                  [ (20, Test.QuickCheck.elements [' ' .. '\DEL'])+                  , ( 1, arbitrary)+                  ]++          noInteriorBlockComments text =+              not (Text.isInfixOf "{-" text || Text.isInfixOf "-}" text)++          commentText =+              suchThat+                  (Text.pack <$> Test.QuickCheck.listOf commentChar)+                  noInteriorBlockComments++          multiline = do+              txt <- commentText+              pure $ "{-" <> txt <> "-}"++          singleline = do+              txt <- commentText `suchThat` (not . Text.isInfixOf "\n")+              endOfLine <- Test.QuickCheck.elements ["\n", "\r\n"]+              pure $ "--" <> txt <> endOfLine++          newlines = Text.concat <$> Test.QuickCheck.listOf (pure "\n")++      comments <- do+          n <- Test.QuickCheck.choose (0, 2)+          Test.QuickCheck.vectorOf n $ Test.QuickCheck.oneof+              [ multiline+              , singleline+              , newlines+              ]++      pure $ Text.unlines comments++shrinkWhitespace :: Text -> [Text]+shrinkWhitespace "" = []+shrinkWhitespace _  = [""]++instance Arbitrary CharacterSet where+    arbitrary = Test.QuickCheck.elements [ ASCII, Unicode ]++instance Arbitrary Header where+    arbitrary = createHeader <$> whitespace++    shrink (Header text) = Header <$> shrinkWhitespace text++instance (Arbitrary v) => Arbitrary (Map Text v) where+    arbitrary = do+        n   <- Test.QuickCheck.choose (0, 2)+        kvs <- Test.QuickCheck.vectorOf n ((,) <$> label <*> arbitrary)+        -- Sorting the fields here because serialization needs them in order+        return (Dhall.Map.fromList (Data.List.sortOn fst kvs))++    shrink =+            map Dhall.Map.fromList+        .   shrink+        .   Dhall.Map.toList++instance (Arbitrary s, Arbitrary a) => Arbitrary (Binding s a) where+    arbitrary = do+        bindingSrc0 <- arbitrary++        variable <- Test.QuickCheck.oneof [ pure "_", label ]++        bindingSrc1 <- arbitrary++        annotation <- arbitrary++        bindingSrc2 <- arbitrary++        value <- arbitrary++        return Binding{..}++    shrink = genericShrink++instance (Arbitrary s, Arbitrary a) => Arbitrary (Chunks s a) where+    arbitrary = do+        n <- Test.QuickCheck.choose (0, 2)+        Chunks <$> Test.QuickCheck.vectorOf n arbitrary <*> arbitrary++    shrink = genericShrink++instance Arbitrary Const where+    arbitrary = Test.QuickCheck.oneof [ pure Type, pure Kind, pure Sort ]++    shrink = genericShrink++instance Arbitrary DhallDouble where+    arbitrary = fmap DhallDouble (Test.QuickCheck.oneof [ arbitrary, special ])+      where+        special = Test.QuickCheck.elements Data.SpecialValues.specialValues++    shrink = genericShrink++instance Arbitrary Directory where+    arbitrary = lift1 Directory++    shrink = genericShrink++instance Arbitrary PreferAnnotation where+    arbitrary = Test.QuickCheck.oneof+        [ pure PreferFromSource+        , pure PreferFromCompletion+        ]++    shrink = genericShrink++instance (Arbitrary s, Arbitrary a) => Arbitrary (RecordField s a) where+    arbitrary = lift4 RecordField++    shrink = genericShrink++instance (Arbitrary s, Arbitrary a) => Arbitrary (FunctionBinding s a) where+    arbitrary = do+        l <- label+        type_ <- arbitrary+        return $ FunctionBinding Nothing l Nothing Nothing type_++    shrink = genericShrink++instance Arbitrary s => Arbitrary (FieldSelection s) where+    arbitrary = FieldSelection <$> pure Nothing <*> label <*> pure Nothing+    shrink = genericShrink++instance Arbitrary WithComponent where+    arbitrary =+        Test.QuickCheck.oneof [ pure WithQuestion, WithLabel <$> arbitrary ]++instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where+    arbitrary =+        Test.QuickCheck.suchThat+            (Generic.Random.withBaseCase+                (Generic.Random.genericArbitraryRecG customGens weights)+                (Var <$> arbitrary)+                )+            standardizedExpression+      where+        customGens+            :: ConstrGen "Lam" 1 (FunctionBinding s a)+            :+ ConstrGen "Pi" 1 Text+            :+ ConstrGen "Field" 1 (FieldSelection s)+            :+ ConstrGen "Project" 1 (Either [Text] (Expr s a))+            :+ Gen Integer  -- Generates all Integer fields in Expr+            :+ Gen Text     -- Generates all Text fields in Expr+            :+ ()+        customGens =+               ConstrGen arbitrary+            :+ ConstrGen label+            :+ ConstrGen arbitrary+            :+ ConstrGen projection+            :+ integer+               -- 'Lam's and 'Pi's are encoded differently when the binding is+               -- the special string "_", so we generate some of these strings+               -- to improve test coverage for these code paths.+            :+ Test.QuickCheck.oneof [pure "_", arbitrary]+            :+ ()++        projection =+            Test.QuickCheck.oneof+                [ fmap Left (Test.QuickCheck.listOf label)+                , arbitrary+                ]++        -- These weights determine the frequency of constructors in the generated+        -- Expr.+        -- They will fail to compile if the constructors don't appear in the order+        -- in which they are defined in 'Expr'!+        weights :: Weights (Expr s a)+        weights =+              (7 :: W "Const")+            % (7 :: W "Var")+            % (7 :: W "Lam")+            % (7 :: W "Pi")+            % (7 :: W "App")+            % (7 :: W "Let")+            % (1 :: W "Annot")+            % (1 :: W "Bool")+            % (7 :: W "BoolLit")+            % (1 :: W "BoolAnd")+            % (1 :: W "BoolOr")+            % (1 :: W "BoolEQ")+            % (1 :: W "BoolNE")+            % (1 :: W "BoolIf")+            % (1 :: W "Bytes")+            % (1 :: W "BytesLit")+            % (1 :: W "Natural")+            % (7 :: W "NaturalLit")+            % (1 :: W "NaturalFold")+            % (1 :: W "NaturalBuild")+            % (1 :: W "NaturalIsZero")+            % (1 :: W "NaturalEven")+            % (1 :: W "NaturalOdd")+            % (1 :: W "NaturalToInteger")+            % (1 :: W "NaturalShow")+            % (1 :: W "NaturalSubtract")+            % (1 :: W "NaturalPlus")+            % (1 :: W "NaturalTimes")+            % (1 :: W "Integer")+            % (7 :: W "IntegerLit")+            % (1 :: W "IntegerClamp")+            % (1 :: W "IntegerNegate")+            % (1 :: W "IntegerShow")+            % (1 :: W "IntegerToDouble")+            % (1 :: W "Double")+            % (7 :: W "DoubleLit")+            % (1 :: W "DoubleShow")+            % (1 :: W "Text")+            % (1 :: W "TextLit")+            % (1 :: W "TextAppend")+            % (1 :: W "TextReplace")+            % (1 :: W "TextShow")+            % (1 :: W "Date")+            % (1 :: W "DateLiteral")+            % (1 :: W "DateShow")+            % (1 :: W "Time")+            % (1 :: W "TimeLiteral")+            % (1 :: W "TimeShow")+            % (1 :: W "TimeZone")+            % (1 :: W "TimeZoneLiteral")+            % (1 :: W "TimeZoneShow")+            % (1 :: W "List")+            % (1 :: W "ListLit")+            % (1 :: W "ListAppend")+            % (1 :: W "ListBuild")+            % (1 :: W "ListFold")+            % (1 :: W "ListLength")+            % (1 :: W "ListHead")+            % (1 :: W "ListLast")+            % (1 :: W "ListIndexed")+            % (1 :: W "ListReverse")+            % (1 :: W "Optional")+            % (7 :: W "Some")+            % (1 :: W "None")+            % (1 :: W "Record")+            % (7 :: W "RecordLit")+            % (1 :: W "Union")+            % (7 :: W "Combine")+            % (1 :: W "CombineTypes")+            % (7 :: W "Prefer")+            % (7 :: W "RecordCompletion")+            % (1 :: W "Merge")+            % (1 :: W "ToMap")+            % (1 :: W "ShowConstructor")+            % (7 :: W "Field")+            % (7 :: W "Project")+            % (1 :: W "Assert")+            % (1 :: W "Equivalent")+            % (1 :: W "With")+            % (0 :: W "Note")+            % (7 :: W "ImportAlt")+            % (7 :: W "Embed")+            % ()++    shrink expression = filter standardizedExpression (genericShrink expression)++standardizedExpression :: Expr s a -> Bool+standardizedExpression (ListLit  Nothing  xs) =+    not (Data.Sequence.null xs)+standardizedExpression (ListLit (Just _ ) xs) =+    Data.Sequence.null xs+standardizedExpression (Note _ _) =+    False+standardizedExpression (Combine _ (Just _) _ _) =+    False+standardizedExpression With{} =+    False+standardizedExpression (Prefer _ PreferFromCompletion _ _) =+    False+-- The following three expressions are valid ASTs, but they can never be parsed,+-- because the annotation will associate with `Merge`/`ListLit`/`ToMap` with+-- higher precedence+standardizedExpression (Annot (Merge _ _ Nothing) _) =+    False+standardizedExpression (Annot (ListLit Nothing _) _) =+    False+standardizedExpression (Annot (ToMap _ Nothing) _) =+    False+standardizedExpression (TimeZoneLiteral (Time.TimeZone _ b t)) =+    not b && null t+standardizedExpression (TimeLiteral (Time.TimeOfDay _ _ ss) precision) =+    isInteger (ss * magnitude)+  where+    magnitude = 10 ^ precision++    isInteger x = x == fromInteger (round x)+standardizedExpression _ =+    True++chooseCharacter :: (Char, Char) -> Gen Char+chooseCharacter = Test.QuickCheck.chooseEnum++instance Arbitrary File where+    arbitrary = lift2 File++    shrink = genericShrink++instance Arbitrary FilePrefix where+    arbitrary = Test.QuickCheck.oneof [ pure Absolute, pure Here, pure Home ]++    shrink = genericShrink++instance Arbitrary Src where+    arbitrary = do+        lift2 Src <*> whitespace++    shrink (Src start end text) =+            (Src <$> shrink start <*> pure end   <*> pure text)+        ++  (Src <$> pure start   <*> shrink end <*> pure text)+        ++  (Src <$> pure start   <*> pure end   <*> shrinkWhitespace text)++instance Arbitrary SourcePos where+    arbitrary = lift3 SourcePos++    shrink = genericShrink++instance Arbitrary Pos where+    arbitrary = lift1 (Megaparsec.mkPos . getPositive)++instance Arbitrary ImportType where+    arbitrary =+        Test.QuickCheck.oneof+            [ do  prefix <- arbitrary++                  let nonEmptyText =+                          fmap Text.pack (Test.QuickCheck.listOf1 arbitrary)++                  components <- Test.QuickCheck.listOf nonEmptyText++                  file <- nonEmptyText++                  let directory = Directory{ components }++                  let path = File{ file, directory }++                  return (Local prefix path)+            , lift1 Remote+            , lift1 Env+            , lift0 Missing+            ]++    shrink = genericShrink++instance Arbitrary ImportHashed where+    arbitrary =+        lift1 (ImportHashed Nothing)++    shrink (ImportHashed { importType = oldImportType, .. }) = do+        newImportType <- shrink oldImportType+        let importHashed = ImportHashed { importType = newImportType, .. }+        return importHashed++-- The standard does not yet specify how to encode `as Text`, so don't test it+-- yet+instance Arbitrary ImportMode where+    arbitrary = Test.QuickCheck.elements [ Code, RawText, Location, RawBytes ]++    shrink = genericShrink++instance Arbitrary Import where+    arbitrary = lift2 Import++    shrink = genericShrink++instance Arbitrary Scheme where+    arbitrary = Test.QuickCheck.oneof [ pure HTTP, pure HTTPS ]++    shrink = genericShrink++instance Arbitrary URL where+    arbitrary = do+        scheme <- arbitrary++        -- TODO: the authority generator could be more precise, but it currently+        -- seems good enough.+        let validAuthorityChar =+                arbitrary `suchThat` \ch ->+                    not (Data.Char.isSpace ch) && not (Data.Char.isPunctuation ch)++        authority <- Text.pack <$> Test.QuickCheck.listOf validAuthorityChar++        let validPChar =+                Test.QuickCheck.frequency+                    [ (26, chooseCharacter ('A', 'Z'))+                    , (26, chooseCharacter ('a', 'z'))+                    , (10, chooseCharacter ('0', '9'))+                    , (17, Test.QuickCheck.elements "-._~!$&'*+;=:@")+                    ]++        let component = fmap Text.pack (Test.QuickCheck.listOf validPChar)++        components <- Test.QuickCheck.listOf component++        file <- component++        let directory = Directory{ components }++        let path = File{ file, directory }++        let validQueryCharacters =+                Test.QuickCheck.frequency+                    [ (79, validPChar)+                    , ( 2, Test.QuickCheck.elements "/?")+                    ]++        query <- Test.QuickCheck.oneof+            [ pure Nothing+            , fmap (Just . Text.pack) (Test.QuickCheck.listOf validQueryCharacters)+            ]++        headers <- arbitrary++        return URL{..}++    shrink _ = []++instance Arbitrary Var where+    arbitrary =+        Test.QuickCheck.oneof+            [ fmap (V "_") (getNonNegative <$> arbitrary)+            , fmap (\t -> V t 0) label+            , V <$> label <*> (getNonNegative <$> arbitrary)+            ]+    shrink = genericShrink++label :: Gen Text+label = fmap Text.pack (Test.QuickCheck.listOf labelCharacter)+  where+    labelCharacter =+        Test.QuickCheck.frequency+            [ (64, chooseCharacter ('\x20', '\x5F'))+            , (30, chooseCharacter ('\x61', '\x7e'))+            ]++binaryRoundtrip :: Expr () Import -> Property+binaryRoundtrip expression =+        Dhall.Binary.decodeExpression (Dhall.Binary.encodeExpression denotedExpression)+    === Right denotedExpression+  where+    denotedExpression :: Expr Void Import+    denotedExpression = denote' expression++    denote' :: Expr a Import -> Expr b Import+    denote' = Dhall.Core.denote . fmap denoteHttpHeaders++    denoteHttpHeaders import_@(Import importHashed _)+        | Remote url <- importType importHashed+        = let headers' = denote' <$> headers url+              importType' = Remote url { headers = headers' }+              importHashed' = importHashed { importType = importType' }+          in  import_ {importHashed = importHashed'}+        | otherwise = import_++everythingWellTypedNormalizes :: Expr () () -> Property+everythingWellTypedNormalizes expression =+        isRight (Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty expression)+    ==> Test.QuickCheck.total (Dhall.Core.normalize expression :: Expr () ())+  where+    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++isNormalizedIsConsistentWithNormalize :: Expr () Import -> Property+isNormalizedIsConsistentWithNormalize expression =+    case maybeProp of+        Nothing -> Test.QuickCheck.discard+        Just v -> v+  where+      denotedExpression :: Expr Void Import+      denotedExpression = Dhall.Core.denote expression++      maybeProp = do+          nf <- Control.Spoon.spoon (Dhall.Core.normalize expression)+          isNormalized <- Control.Spoon.spoon (Dhall.Core.isNormalized expression)+          -- Dhall.Core.isNormalized ignores 'Note's and other annotations.+          -- So we do the same when checking the result of 'normalize'.+          return $ isNormalized === (nf == denotedExpression)++normalizeWithMIsConsistentWithNormalize :: Expr () Import -> Property+normalizeWithMIsConsistentWithNormalize expression =+    case Control.Spoon.spoon (nfM, nf) of+        Just (a, b) -> a === b+        Nothing -> Test.QuickCheck.discard+  where nfM = runIdentity (Dhall.Core.normalizeWithM (\_ -> Identity Nothing) expression)+        nf = Dhall.Core.normalize expression :: Expr () Import++isSameAsSelf :: Expr () Import -> Property+isSameAsSelf expression =+  hasNoImportAndTypechecks ==> Dhall.Diff.same (Dhall.Diff.diff denoted denoted)+  where denoted = Dhall.Core.denote expression+        hasNoImportAndTypechecks =+          case traverse (\_ -> Left ()) expression of+            Right importlessExpression -> isRight (Dhall.TypeCheck.typeOf importlessExpression)+            Left _ -> False++inferredTypesAreNormalized :: Expr () Import -> Property+inferredTypesAreNormalized expression =+    Test.Tasty.QuickCheck.counterexample report (all Dhall.Core.isNormalized result)+  where+    report =  "Got: " ++ show result+           ++ "\nExpected: " ++ show (fmap Dhall.Core.normalize result+                                      :: Either (TypeError () Import) (Expr () Import))++    result = Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty expression++    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++normalizingAnExpressionDoesntChangeItsInferredType :: Expr () Import -> Property+normalizingAnExpressionDoesntChangeItsInferredType expression =+    case (eT0, eT1) of+        (Right t0, Right t1) -> t0 === t1+        _ -> Test.QuickCheck.discard+  where+    eT0 = typeCheck expression+    eT1 = typeCheck (Dhall.Core.normalize expression)++    typeCheck = Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty++    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++noDoubleNotes :: Expr () Import -> Property+noDoubleNotes expression =+    length+        [ ()+        | e <- Foldable.toList parsedExpression+        , Note _ (Note _ _) <- Lens.toListOf Dhall.Core.subExpressions e+        ] === 0+  where+    text = Dhall.Core.pretty expression++    parsedExpression = Parser.exprFromText "" text++embedThenExtractIsIdentity+    :: forall a. (ToDhall a, FromDhall a, Eq a, Typeable a, Arbitrary a, Show a)+    => Proxy a+    -> (String, Property, TestTree -> TestTree)+embedThenExtractIsIdentity p =+    ( "Embedding then extracting is identity for " ++ show (typeRep p)+    , Test.QuickCheck.property (prop :: a -> Bool)+    , adjustQuickCheckTests 1000+    )+  where+    prop a = case extract auto (embed inject a) of+        Success a' -> a == a'+        Failure _  -> False++idempotenceTest :: CharacterSet -> Header -> Expr Src Import -> Property+idempotenceTest characterSet header expr =+        not (any hasHttpHeaders expr)+    ==> let once = format characterSet (header, expr)+        in case Parser.exprAndHeaderFromText mempty once of+            Right (format characterSet -> twice) -> once === twice+            Left _ -> Test.QuickCheck.discard+  where+    -- Workaround for https://github.com/dhall-lang/dhall-haskell/issues/1925.+    hasHttpHeaders = \case+        Import (ImportHashed _ (Remote (URL { headers = Just _ }))) _ -> True+        _                                                             -> False++tests :: TestTree+tests =+    testProperties'+        "QuickCheck"+        [ ( "Binary serialization should round-trip"+          , Test.QuickCheck.property binaryRoundtrip+          , adjustQuickCheckTests 100+          )+        , ( "everything well-typed should normalize"+          , Test.QuickCheck.property everythingWellTypedNormalizes+          , adjustQuickCheckTests 100000+          )+        , ( "isNormalized should be consistent with normalize"+          , Test.QuickCheck.property isNormalizedIsConsistentWithNormalize+          , adjustQuickCheckTests 10000+          )+        , ( "normalizeWithM should be consistent with normalize"+          , Test.QuickCheck.property normalizeWithMIsConsistentWithNormalize+          , adjustQuickCheckTests 10000+          )+        , ( "An expression should have no difference with itself"+          , Test.QuickCheck.property isSameAsSelf+          , adjustQuickCheckTests 10000+          )+        , ( "Inferred types should be normalized"+          , Test.QuickCheck.property inferredTypesAreNormalized+          , adjustQuickCheckTests 10000+          )+        , ( "Normalizing an expression doesn't change its inferred type"+          , Test.QuickCheck.property normalizingAnExpressionDoesntChangeItsInferredType+          , adjustQuickCheckTests 10000+          )+        , ( "Parsing an expression doesn't generated doubly-nested Note constructors"+          , Test.QuickCheck.property noDoubleNotes+          , adjustQuickCheckTests 100+          )+        , embedThenExtractIsIdentity (Proxy :: Proxy (Text))+        , embedThenExtractIsIdentity (Proxy :: Proxy [Nat.Natural])+        , embedThenExtractIsIdentity (Proxy :: Proxy (Bool, Double))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Sequence.Seq ()))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Maybe Integer))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Set.Set Nat.Natural))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.HashSet.HashSet Text))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Vector Double))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Map.Map Double Bool))+        , embedThenExtractIsIdentity (Proxy :: Proxy (HashMap.HashMap Double Bool))+        , ( "Formatting should be idempotent"+          , Test.QuickCheck.property idempotenceTest+          , adjustQuickCheckTests 10000+          )+        ]++adjustQuickCheckMaxRatio :: Int -> TestTree -> TestTree+adjustQuickCheckMaxRatio maxSize =+    Test.Tasty.adjustOption (max $ Test.Tasty.QuickCheck.QuickCheckMaxRatio maxSize)++adjustQuickCheckTests :: Int -> TestTree -> TestTree+adjustQuickCheckTests nTests =+    -- Using adjustOption instead of withMaxSuccess allows us to override the number of tests+    -- with the --quickcheck-tests CLI option.+    Test.Tasty.adjustOption (max $ QuickCheckTests nTests)++testProperties' :: String -> [(String, Property, TestTree -> TestTree)] -> TestTree+testProperties' name = Test.Tasty.testGroup name . map f+  where+    f (n, p, adjust) = adjust (Test.Tasty.QuickCheck.testProperty n p)
+ tests/Dhall/Test/Regression.hs view
@@ -0,0 +1,327 @@+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Regression where++import Data.Either.Validation (Validation (..))+import Data.Void              (Void)+import Dhall.Core             (Expr (..), ReifiedNormalizer (..))+import Dhall.Import           (Imported, MissingImports (..))+import Dhall.Parser           (SourcedException (..), Src)+import Dhall.TypeCheck        (TypeError)+import Test.Tasty             (TestTree)+import Test.Tasty.HUnit       ((@?=))++import qualified Control.Exception+import qualified Data.Text.IO+import qualified Data.Text.Lazy.IO+import qualified Dhall+import qualified Dhall.Context             as Context+import qualified Dhall.Core+import qualified Dhall.Map+import qualified Dhall.Parser+import qualified Dhall.Pretty+import qualified Dhall.Test.Util           as Util+import qualified Dhall.TypeCheck+import qualified Lens.Micro                as Lens+import qualified Prettyprinter+import qualified Prettyprinter.Render.Text+import qualified System.Timeout+import qualified Test.Tasty+import qualified Test.Tasty.HUnit++tests :: TestTree+tests =+    Test.Tasty.testGroup "regression tests"+        [ issue96+        , issue126+        , issue151+        , issue164+        , issue201+        , issue216+        , issue253+        , issue1131a+        , issue1131b+        , issue1341+        , issue1584+        , issue1646+        , issue1732+        , issue1884+        , issue2088+        , issue2463+        , parsing0+        , typeChecking0+        , typeChecking1+        , typeChecking2+        , unnamedFields+        , trailingSpaceAfterStringLiterals+        ]++data Foo = Foo Integer Bool | Bar Bool Bool Bool | Baz Integer Integer+    deriving (Show, Dhall.Generic, Dhall.FromDhall, Dhall.ToDhall)++unnamedFields :: TestTree+unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do+    let ty = Dhall.auto :: Dhall.Decoder Foo+    Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty)+        (Success (Dhall.Core.Union+            (Dhall.Map.fromList+                [   ("Foo",Just (Dhall.Core.Record (Dhall.Map.fromList+                        [ ("_1", Dhall.Core.makeRecordField Dhall.Core.Integer)+                        , ("_2", Dhall.Core.makeRecordField Dhall.Core.Bool)+                        ])))+                ,   ("Bar",Just (Dhall.Core.Record (Dhall.Map.fromList+                        [ ("_1", Dhall.Core.makeRecordField Dhall.Core.Bool)+                        , ("_2", Dhall.Core.makeRecordField Dhall.Core.Bool)+                        , ("_3", Dhall.Core.makeRecordField Dhall.Core.Bool)+                        ])))+                ,   ("Baz",Just (Dhall.Core.Record (Dhall.Map.fromList+                        [ ("_1", Dhall.Core.makeRecordField Dhall.Core.Integer)+                        , ("_2", Dhall.Core.makeRecordField Dhall.Core.Integer)+                        ])))+                ]+            )+        ))++    let inj = Dhall.inject :: Dhall.Encoder Foo+    Test.Tasty.HUnit.assertEqual "Good ToDhall" (Success $ Dhall.declared inj) (Dhall.expected ty)++    let tu_ty = Dhall.auto :: Dhall.Decoder (Integer, Bool)+    Test.Tasty.HUnit.assertEqual "Auto Tuple" (Dhall.expected tu_ty) (Success $ Dhall.Core.Record (+            Dhall.Map.fromList+                [ ("_1", Dhall.Core.makeRecordField Dhall.Core.Integer)+                , ("_2", Dhall.Core.makeRecordField Dhall.Core.Bool)+                ]))++    let tu_in = Dhall.inject :: Dhall.Encoder (Integer, Bool)+    Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Success $ Dhall.declared tu_in) (Dhall.expected tu_ty)++    return () )++issue96 :: TestTree+issue96 = Test.Tasty.HUnit.testCase "Issue #96" (do+    -- Verify that parsing should not fail+    _ <- Util.code "\"bar'baz\""+    return () )++issue126 :: TestTree+issue126 = Test.Tasty.HUnit.testCase "Issue #126" (do+    e <- Util.code "''\nfoo\nbar\n''"+    Util.normalize' e @?= "''\nfoo\nbar\n''" )++issue151 :: TestTree+issue151 = Test.Tasty.HUnit.testCase "Issue #151" (do+    let shouldNotTypeCheck text = do+            let handler :: SourcedException MissingImports -> IO Bool+                handler (SourcedException _ (MissingImports [e])) =+                    case Control.Exception.fromException e :: Maybe (Imported (TypeError Src Void)) of+                        Just _ -> return True+                        Nothing -> return False+                handler _ =+                    return True++            let typeCheck = do+                    _ <- Util.code text+                    return False+            b <- Control.Exception.handle handler typeCheck+            Test.Tasty.HUnit.assertBool "The expression should not type-check" b++    -- These two examples contain the following expression that loops infinitely+    -- if you normalize the expression before type-checking the expression:+    --+    --     (λ(x : A) → x x) (λ(x : A) → x x)+    --+    -- There was a bug in the Dhall type-checker were expressions were not+    -- being type-checked before being added to the context (which is a+    -- violation of the standard type-checking rules for a pure type system).+    -- The reason this is problematic is that several places in the+    -- type-checking logic assume that the context is safe to normalize.+    --+    -- Both of these examples exercise area of the type-checker logic that+    -- assume that the context is normalized.  If you fail to type-check terms+    -- before adding them to the context then this test will "fail" with an+    -- infinite loop.  This test "succeeds" if the examples terminate+    -- immediately with a type-checking failure.+    shouldNotTypeCheck "./tests/regression/issue151a.dhall"+    shouldNotTypeCheck "./tests/regression/issue151b.dhall" )++issue164 :: TestTree+issue164 = Test.Tasty.HUnit.testCase "Issue #164" (do+    -- Verify that parsing should not fail on a single-quote within a+    -- single-quoted string+    _ <- Util.code "./tests/regression/issue164.dhall"+    return () )++issue201 :: TestTree+issue201 = Test.Tasty.HUnit.testCase "Issue #201" (do+    -- Verify that type synonyms work+    _ <- Util.code "./tests/regression/issue201.dhall"+    return () )++issue216 :: TestTree+issue216 = Test.Tasty.HUnit.testCase "Issue #216" (do+    -- Verify that pretty-printing preserves string interpolation+    source <- Data.Text.IO.readFile "./tests/regression/issue216b.dhall"+    e <- Util.code source+    let doc       = Prettyprinter.pretty e+    let docStream = Dhall.Pretty.layout doc+    let text0 = Prettyprinter.Render.Text.renderLazy docStream++    text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall"++    Test.Tasty.HUnit.assertEqual "Pretty-printing should preserve string interpolation" text1 text0 )++issue253 :: TestTree+issue253 = Test.Tasty.HUnit.testCase "Issue #253" (do+    -- Verify that type-checking rejects ill-formed custom contexts+    let context = Context.insert "x" "x" Context.empty+    let result = Dhall.TypeCheck.typeWith context "x"++    -- If the context is not validated correctly then type-checking will+    -- infinitely loop+    Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $! result)+    return () )++issue1131a :: TestTree+issue1131a = Test.Tasty.HUnit.testCase "Issue #1131 a"+    (Util.assertDoesntTypeCheck "toMap {=} : <>.x")++issue1131b :: TestTree+issue1131b = Test.Tasty.HUnit.testCase "Issue #1131 b"+    (Util.assertDoesntTypeCheck "toMap {=} : List {mapKey : Text, mapValue : 0}")++issue1341 :: TestTree+issue1341 = Test.Tasty.HUnit.testCase "Issue #1341" (do+    let nan    = Dhall.Core.DoubleLit (Dhall.Core.DhallDouble (0/0)) :: Dhall.Core.Expr () ()+    let actual = Dhall.Core.V "x" 0 `Dhall.Core.freeIn` nan+    let msg    = "NaN shouldn't contain any free variables"+    Test.Tasty.HUnit.assertEqual msg False actual)++issue1584 :: TestTree+issue1584 = Test.Tasty.HUnit.testCase "Issue #1584" (do+    -- This test ensures that we can parse variables with keyword prefixes+    -- (e.g. `ifX`)+    _ <- Util.code "./tests/regression/issue1584.dhall"+    return () )++issue1646 :: TestTree+issue1646 = Test.Tasty.HUnit.testCase "Issue #1646" (do+    -- This test ensures that the parser doesn't eagerly consume trailing+    -- whitespace after a `Double`+    _ <- Util.code "./tests/regression/issue1646.dhall"+    return () )++issue1732 :: TestTree+issue1732 = Test.Tasty.HUnit.testCase "Issue #1732" (do+    -- This test ensures that the parser allows whitespace after a record pun+    -- entry+    _ <- Util.code "./tests/regression/issue1732.dhall"+    return () )++issue1884 :: TestTree+issue1884 = Test.Tasty.HUnit.testCase "Issue #1884" (do+    -- This test ensures that the parser allows a parenthesized application+    -- expression as the first argument to a with expression+    _ <- Util.code "./tests/regression/issue1884.dhall"+    return () )++issue2088 :: TestTree+issue2088 = Test.Tasty.HUnit.testCase "Issue #2088" (do+    -- This test ensures that the parser for projection by labels doesn't+    -- accidentally swallow trailing commas OUTSIDE of the projection+    _ <- Util.code "./tests/regression/issue2088.dhall"+    return () )++issue2463 :: TestTree+issue2463 = Test.Tasty.HUnit.testCase "Issue #2463" (do+    let startingContext = Context.insert "foo" Integer Context.empty++    let normalizer (Var "foo") = Just (IntegerLit 0)+        normalizer  _          = Nothing++    let inputSettings = transform Dhall.defaultInputSettings+          where+            transform =+                  Lens.set Dhall.normalizer+                      (Just (ReifiedNormalizer (pure . normalizer)))+                . Lens.set Dhall.startingContext startingContext++    x <- Dhall.inputWithSettings inputSettings Dhall.auto "foo"++    Test.Tasty.HUnit.assertEqual "" (0 :: Integer) x )++parsing0 :: TestTree+parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (+    -- Verify that parsing should not fail+    --+    -- In 267093f8cddf1c2f909f2d997c31fd0a7cb2440a I broke the parser when left+    -- factoring the grammar by failing to handle the source tested by this+    -- regression test.  The root of the problem was that the parser was trying+    -- to parse `List ./Node` as `Field List "/Node"` instead of+    -- `App List (Embed (Path (File Homeless "./Node") Code))`.  The latter is+    -- the correct parse because `/Node` is not a valid field label, but the+    -- mistaken parser was committed to the incorrect parse and never attempted+    -- the correct parse.+    case Dhall.Parser.exprFromText mempty "List ./Node" of+        Left  e -> Control.Exception.throwIO e+        Right _ -> return () )++typeChecking0 :: TestTree+typeChecking0 = Test.Tasty.HUnit.testCase "Type-checking regression #0" (do+    -- There used to be a bug in the type-checking logic where `T` would be+    -- added to the context when inferring the type of `λ(x : T) → x`, but was+    -- missing from the context when inferring the kind of the inferred type+    -- (i.e. the kind of `∀(x : T) → T`).  This led to an unbound variable+    -- error when inferring the kind+    --+    -- This bug was originally reported in issue #10+    _ <- Util.code "let Day : Type = Natural in λ(x : Day) → x"+    return () )++typeChecking1 :: TestTree+typeChecking1 = Test.Tasty.HUnit.testCase "Type-checking regression #1" (do+    -- There used to be a bug in the type-checking logic when inferring the+    -- type of `let`.  Specifically, given an expression of the form:+    --+    --     let x : t = e1 in e2+    --+    -- ... the type-checker would not substitute `x` for `e1` in the inferred+    -- of the `let` expression.  This meant that if the inferred type contained+    -- any references to `x` then these references would escape their scope and+    -- result in unbound variable exceptions+    --+    -- This regression test exercises that code path by creating a `let`+    -- expression where the inferred type before substitution (`∀(x : b) → b` in+    -- this example), contains a reference to the `let`-bound variable (`b`)+    -- that needs to be substituted with `a` in order to produce the final+    -- correct inferred type (`∀(x : a) → a`).  If this test passes then+    -- substitution worked correctly.  If substitution doesn't occur then you+    -- expect an `Unbound variable` error from `b` escaping its scope due to+    -- being returned as part of the inferred type+    _ <- Util.code "λ(a : Type) → let b : Type = a in λ(x : b) → x"+    return () )++typeChecking2 :: TestTree+typeChecking2 = Test.Tasty.HUnit.testCase "Type-checking regression #2" (do+    -- There used to be a bug in the type-checking logic where `let` bound+    -- variables would not correctly shadow variables of the same name when+    -- inferring the type of of the `let` expression+    --+    -- This example exercises this code path with a `let` expression where the+    -- `let`-bound variable (`a`) has the same name as its own type (`a`).  If+    -- shadowing works correctly then the final `a` in the expression should+    -- refer to the `let`-bound variable and not its type.  An invalid reference+    -- to the shadowed type `a` would result in an invalid dependently typed+    -- function+    _ <- Util.code "λ(a : Type) → λ(x : a) → let a : a = x in a"+    return () )++trailingSpaceAfterStringLiterals :: TestTree+trailingSpaceAfterStringLiterals =+    Test.Tasty.HUnit.testCase "Trailing space after string literals" (do+        -- Verify that string literals parse correctly with trailing space+        -- (Yes, I did get this wrong at some point)+        _ <- Util.code "(''\nABC'' ++ \"DEF\" )"+        return () )
+ tests/Dhall/Test/Schemas.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Schemas where++import Data.Text    (Text)+import Dhall.Parser (Header (..))+import Test.Tasty   (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty              as Pretty+import qualified Dhall.Schemas             as Schemas+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter             as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.HUnit          as Tasty.HUnit+import qualified Turtle++schemasDirectory :: FilePath+schemasDirectory = "./tests/schemas"++getTests :: IO TestTree+getTests = do+    schemasTests <- Test.Util.discover (Turtle.chars <* "A.dhall") schemaTest (Turtle.lstree schemasDirectory)++    return (Tasty.testGroup "schemas tests" [ schemasTests ])++format :: Header -> Core.Expr Parser.Src Core.Import -> Text+format (Header header) expr =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet Pretty.Unicode expr+            <> "\n"++        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream++schemaTest :: Text -> TestTree+schemaTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let inputFile  = Text.unpack (prefix <> "A.dhall")+        let outputFile = Text.unpack (prefix <> "B.dhall")++        inputText  <- Text.IO.readFile inputFile++        (header, parsedInput) <- Core.throws (Parser.exprAndHeaderFromText mempty inputText)++        parsedSchema <- Core.throws (Parser.exprFromText mempty (Test.Util.toDhallPath (prefix <> "Schema.dhall")))++        actualExpression <- Schemas.rewriteWithSchemas parsedSchema parsedInput++        let actualText = format header actualExpression++        expectedText <- Text.IO.readFile outputFile++        let message = "The rewritten expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedText actualText
+ tests/Dhall/Test/SemanticHash.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.SemanticHash where++import Data.Text  (Text)+import Test.Tasty (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Core       as Core+import qualified Dhall.Import     as Import+import qualified Dhall.Parser     as Parser+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++hashDirectory :: FilePath+hashDirectory = "./dhall-lang/tests/semantic-hash"++getTests :: IO TestTree+getTests = do+    hashTests <- Test.Util.discover (Turtle.chars <* "A.dhall") hashTest (Turtle.lstree hashDirectory)++    return (Tasty.testGroup "semantic-hash tests" [ hashTests ])++hashTest :: Text -> TestTree+hashTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let codeFile = Test.Util.toDhallPath (prefix <> "A.dhall")+        let hashFile = Test.Util.toDhallPath (prefix <> "B.hash")++        expr <- Core.throws (Parser.exprFromText mempty codeFile)++        resolved <- Import.load expr++        let normalized = Core.alphaNormalize (Core.normalize resolved)++        let actualHash = Import.hashExpressionToCode normalized++        expectedHash <- Text.stripEnd <$> Text.IO.readFile (Text.unpack hashFile)++        let message = "The hash did not match the expected hash."++        Tasty.HUnit.assertEqual message expectedHash actualHash
+ tests/Dhall/Test/Substitution.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Substitution where++import Control.Exception (throwIO)+import Data.Void         (Void)+import Dhall.Core        (Expr (BoolLit, Var))+import Dhall.Src         (Src)++import qualified Data.Either.Validation+import qualified Dhall+import qualified Dhall.Map+import qualified Lens.Micro             as Lens++data Result = Failure Integer | Success String+    deriving (Eq, Dhall.Generic, Show)++instance Dhall.FromDhall Result++substituteResult :: FilePath -> IO Result+substituteResult fp = do+    rt <- resultType+    let evaluateSettings = Lens.over Dhall.substitutions (Dhall.Map.insert "Result" rt) Dhall.defaultEvaluateSettings+    Dhall.inputFileWithSettings evaluateSettings resultDecoder fp++resultDecoder :: Dhall.Decoder Result+resultDecoder = Dhall.auto++resultType :: IO (Expr Src Void)+resultType = case Dhall.expected resultDecoder of+    Data.Either.Validation.Failure e -> throwIO e+    Data.Either.Validation.Success x -> return x++substituteFoo :: FilePath -> IO Bool+substituteFoo fp = let+    evaluateSettings = Lens.set Dhall.substitutions (Dhall.Map.fromList [("Foo", Var "Bar"), ("Bar", BoolLit True)]) Dhall.defaultEvaluateSettings+    in Dhall.inputFileWithSettings evaluateSettings Dhall.auto fp
+ tests/Dhall/Test/TH.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell    #-}++module Dhall.Test.TH where++import Control.Exception      (throwIO)+import Data.Either.Validation (Validation (..))+import Data.Time              (TimeOfDay (..), TimeZone (..), fromGregorian)+import Dhall.TH               (HaskellType (..))+import Test.Tasty             (TestTree)++import qualified Data.Text+import qualified Dhall+import qualified Dhall.TH+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit++Dhall.TH.makeHaskellTypeFromUnion "T" "./tests/th/example.dhall"++deriving instance Eq   T+deriving instance Show T++Dhall.TH.makeHaskellTypes+    [ MultipleConstructors "Department" "./tests/th/Department.dhall"+    , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+    , SingleConstructor "TimeExample" "TimeExample" "./tests/th/Time.dhall"+    ]++deriving instance Eq   Department+deriving instance Show Department++deriving instance Eq   Employee+deriving instance Show Employee++deriving instance Eq   TimeExample+deriving instance Show TimeExample++Dhall.TH.makeHaskellTypes+  [ SingleConstructor "Bar" "MakeBar" "(./tests/th/issue2066.dhall).Bar"+  , SingleConstructor "Foo" "MakeFoo" "(./tests/th/issue2066.dhall).Foo"+  , MultipleConstructors "Qux" "(./tests/th/issue2066.dhall).Qux"+  ]++deriving instance Eq   Bar+deriving instance Show Bar++deriving instance Eq   Foo+deriving instance Show Foo++deriving instance Eq   Qux+deriving instance Show Qux++tests :: TestTree+tests = Tasty.testGroup "Template Haskell" [ makeHaskellTypeFromUnion ]++makeHaskellTypeFromUnion :: TestTree+makeHaskellTypeFromUnion = Tasty.HUnit.testCase "makeHaskellTypeFromUnion" $ do+    t0 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.A { x = True, y = [ \"ABC\" ] }"++    Tasty.HUnit.assertEqual "" t0 A{ x = True, y = [ "ABC" ] }++    t1 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.B (Some [ 1 ])"++    Tasty.HUnit.assertEqual "" t1 (B (Just [ 1 ]))++    t2 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.C"++    Tasty.HUnit.assertEqual "" t2 C++    employee <- Dhall.input Dhall.auto "let Department = ./tests/th/Department.dhall in { name = \"John\", department = Department.Marketing }"++    Tasty.HUnit.assertEqual "" employee MakeEmployee{ name = "John", department = Marketing }++    qux <- Dhall.input Dhall.auto "let T = ./tests/th/issue2066.dhall in T.Qux.Foo { foo = +2, bar = { baz = +3 } }"++    Tasty.HUnit.assertEqual "" qux (Foo MakeFoo{ foo = 2, bar = MakeBar{ baz = 3 } })++    timex <- Dhall.input Dhall.auto "let T = ./tests/th/Time.dhall in { txTime = 21:12:00, txDate = 1976-04-01, txTimeZone = +05:00 } : T"++    Tasty.HUnit.assertEqual "" timex TimeExample { txTime = tod, txDate = day, txTimeZone = tz}++    where+      tod = TimeOfDay { todHour = 21, todMin = 12, todSec = 0 }+      day = fromGregorian 1976 4 1+      tz = TimeZone { timeZoneMinutes = 300, timeZoneSummerOnly = False, timeZoneName = "" }+  ++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("My" <>)+    , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+    })+    [ MultipleConstructors "MyT" "./tests/th/example.dhall"+    , MultipleConstructors "MyDepartment" "./tests/th/Department.dhall"+    , SingleConstructor "MyEmployee" "Employee" "./tests/th/Employee.dhall"+    ]++  +deriving instance Eq   MyT+deriving instance Eq   MyDepartment+deriving instance Eq   MyEmployee+deriving instance Show MyT+deriving instance Show MyDepartment+deriving instance Show MyEmployee++  +Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("My" <>)+    , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    , Dhall.TH.generateToDhallInstance = False+    })+    [ SingleConstructor "MyHKSingle" "HKSingle" "./tests/th/HigherKindSingle.dhall"+    , MultipleConstructors "MyHKUnion" "./tests/th/HigherKindUnion.dhall"+    ]++type MyHKSingle_ = MyHKSingle Maybe Int+type MyHKUnion_ = MyHKUnion Bool Int++deriving instance Eq MyHKSingle_+deriving instance Show MyHKSingle_+deriving instance Dhall.Generic MyHKSingle_+instance Dhall.FromDhall MyHKSingle_+instance Dhall.ToDhall MyHKSingle_++deriving instance Eq MyHKUnion_+deriving instance Show MyHKUnion_+deriving instance Dhall.Generic MyHKUnion_+instance Dhall.FromDhall MyHKUnion_+instance Dhall.ToDhall MyHKUnion_++testMakeHaskellTypesWith :: TestTree+testMakeHaskellTypesWith = Tasty.HUnit.testCase "makeHaskellTypesWith" $ do+    let text0 = "let T = ./tests/th/example.dhall in T.A { x = True, y = [] : List Text }"+        ref0 = MyA{ myX = True, myY = [] }+    myTest text0 ref0++    let text1 = "let T = ./tests/th/example.dhall in T.B (None (List Natural))"+        ref1 = MyB Nothing+    myTest text1 ref1++    let text2 = "let T = ./tests/th/example.dhall in T.C"+        ref2 = MyC+    myTest text2 ref2++    let textDepartment = "let T = ./tests/th/Department.dhall in T.Sales"+        refDepartment = MySales+    myTest textDepartment refDepartment++    let textEmployee = "let T = ./tests/th/Department.dhall in T.Sales"+        refEmployee = MyEmployee{ myName = "", myDepartment = MySales }+    myTest textEmployee refEmployee++    let textHKSingle = "let T = (./tests/th/HigherKindSingle.dhall) Optional Int in T { foo = +1, bar = Some +2, bam = \"\" }"+        refHKSingle = MyHKSingle { myFoo = 1, myBar = Just 2, myBam = "" } :: MyHKSingle_+    myTest textHKSingle refHKSingle++    let textHKUnion0 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Foo True"+        refHKUnion0 = MyFoo True :: MyHKUnion_+    myTest textHKUnion0 refHKUnion0++    let textHKUnion1 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Bar +1"+        refHKUnion1 = MyBar 1 :: MyHKUnion_+    myTest textHKUnion1 refHKUnion1++    where+        myTest text ref = do+            expr <- Dhall.inputExpr text+            t <- case Dhall.extract Dhall.auto expr of+                Failure e -> throwIO e+                Success t -> return t++            Tasty.HUnit.assertEqual "" t ref+            Tasty.HUnit.assertEqual "" expr $ Dhall.embed Dhall.inject ref++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoFromDhall" <>)+    , Dhall.TH.fieldModifier = ("noFromDhall" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    })+    [ MultipleConstructors "NoFromDhallT" "./tests/th/example.dhall"+    ]++instance Dhall.FromDhall NoFromDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoToDhall" <>)+    , Dhall.TH.fieldModifier = ("noToDhall" <>) . Data.Text.toTitle+    , Dhall.TH.generateToDhallInstance = False+    })+    [ MultipleConstructors "NoToDhallT" "./tests/th/example.dhall"+    ]++instance Dhall.ToDhall NoToDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoInstances" <>)+    , Dhall.TH.fieldModifier = ("noInstances" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    , Dhall.TH.generateToDhallInstance = False+    })+    [ MultipleConstructors "NoInstancesT" "./tests/th/example.dhall"+    ]++deriving instance Dhall.Generic NoInstancesT+instance Dhall.FromDhall NoInstancesT+instance Dhall.ToDhall NoInstancesT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("Strict" <>)+    , Dhall.TH.fieldModifier = ("strict" <>) . Data.Text.toTitle+    , Dhall.TH.makeStrict = True+    })+    [ MultipleConstructors "StrictFields" "./tests/th/example.dhall"+    ]
+ tests/Dhall/Test/Tags.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Tags where++import Data.Text       (Text)+import Dhall.Util      (Input (..))+import System.FilePath ((</>))+import Test.Tasty      (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Tags       as Tags+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++tagsDirectory :: FilePath+tagsDirectory = "./tests/tags"++getTests :: IO TestTree+getTests = do+    tagsTests <- Test.Util.discover (Turtle.chars <* ".dhall") tagsTest (Turtle.lstree tagsDirectory)++    let testTree = Tasty.testGroup "tags tests" [ tagsTests, tagsDirTest ]++    return testTree++tagsTest :: Text -> TestTree+tagsTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        -- The use of toDhallPah is a hack to ensure we always get the same file+        -- paths, i.e. ones with a '.' prefixed and UNIX path separators.+        let inputFile  = Text.unpack (Test.Util.toDhallPath prefix <> ".dhall")+        let outputFile = Text.unpack (prefix <> ".tags")++        actualTags <- fixPathSeparators <$> Tags.generate (InputFile inputFile) Nothing False++        expectedTags <- Text.IO.readFile outputFile++        let message = "The actual tags did not match the expected tags"++        Tasty.HUnit.assertEqual message expectedTags actualTags++tagsDirTest :: TestTree+tagsDirTest =+    Tasty.HUnit.testCase "all" $ do+        let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory </> "all.tags"++        actualTags <- fmap fixPathSeparators+                      (Tags.generate+                          (InputFile (Text.unpack . Turtle.format Turtle.fp $ tagsDirectory))+                          (Just [".dhall"])+                          False)++        expectedTags <- Text.IO.readFile outputFile++        let message = "The actual tags did not match the expected tags for directory test"++        Tasty.HUnit.assertEqual message expectedTags actualTags++fixPathSeparators :: Text -> Text+fixPathSeparators = Text.replace "\\" "/"
+ tests/Dhall/Test/Tutorial.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Tutorial where++import qualified Data.Vector+import qualified Dhall+import qualified Dhall.Test.Substitution as Substitution+import qualified Dhall.Test.Util         as Util+import qualified Test.Tasty+import qualified Test.Tasty.HUnit++import Data.Text        (Text)+import Dhall            (ToDhall)+import GHC.Generics     (Generic)+import Numeric.Natural  (Natural)+import Test.Tasty       (TestTree)+import Test.Tasty.HUnit ((@?=))++tests :: TestTree+tests =+    Test.Tasty.testGroup "tutorial"+        [ Test.Tasty.testGroup "Interpolation"+            [ _Interpolation_0+            , _Interpolation_1+            ]+        , Test.Tasty.testGroup "Functions"+            [ _Functions_0+            , _Functions_1+            , _Functions_2+            ]+        , Test.Tasty.testGroup "Unions"+            [ example 0 "./tests/tutorial/unions0A.dhall" "./tests/tutorial/unions0B.dhall"+            , example 1 "./tests/tutorial/unions1A.dhall" "./tests/tutorial/unions1B.dhall"+            , example 3 "./tests/tutorial/unions3A.dhall" "./tests/tutorial/unions3B.dhall"+            , example 4 "./tests/tutorial/unions4A.dhall" "./tests/tutorial/unions4B.dhall"+            ]+        , Test.Tasty.testGroup "Substitutions"+            [ Test.Tasty.HUnit.testCase "substitution1.dhall" $ do+                res <- Substitution.substituteResult "tests/tutorial/substitution1.dhall"+                res @?= Substitution.Failure 1+            , Test.Tasty.HUnit.testCase "substitution2.dhall" $ do+                res <- Substitution.substituteResult "tests/tutorial/substitution2.dhall"+                res @?= Substitution.Failure 1+            , Test.Tasty.HUnit.testCase "substitution3.dhall" $ do+                res <- Substitution.substituteFoo "tests/tutorial/substitution3.dhall"+                res @?= True+            ]+        ]++_Interpolation_0 :: TestTree+_Interpolation_0 = Test.Tasty.HUnit.testCase "Example #0" (do+    e <- Util.code+        "    let name = \"John Doe\"                                 \n\+        \in  let age  = 21                                           \n\+        \in  \"My name is ${name} and my age is ${Natural/show age}\"\n"+    Util.assertNormalizesTo e "\"My name is John Doe and my age is 21\"" )++_Interpolation_1 :: TestTree+_Interpolation_1 = Test.Tasty.HUnit.testCase "Example #1" (do+    e <- Util.code+        "''\n\+        \    for file in *; do         \n\+        \      echo \"Found ''${file}\"\n\+        \    done                      \n\+        \''                            \n"+    Util.assertNormalized e )++_Functions_0 :: TestTree+_Functions_0 = Test.Tasty.HUnit.testCase "Example #0" (do+    let text = "\\(n : Bool) -> [ n && True, n && False, n || True, n || False ]"+    makeBools <- Dhall.input Dhall.auto text+    makeBools True @?= Data.Vector.fromList [True,False,True,True] )++_Functions_1 :: TestTree+_Functions_1 = Test.Tasty.HUnit.testCase "Example #1" (do+    let text = "λ(x : Bool) → λ(y : Bool) → x && y"+    makeBools <- Dhall.input Dhall.auto text+    makeBools True False @?= False )++data Example0 = Example0 { foo :: Bool, bar :: Bool }+    deriving (Generic, ToDhall)++_Functions_2 :: TestTree+_Functions_2 = Test.Tasty.HUnit.testCase "Example #2" (do+    f <- Dhall.input Dhall.auto "λ(r : { foo : Bool, bar : Bool }) → r.foo && r.bar"+    f (Example0 { foo = True, bar = False }) @?= False+    f (Example0 { foo = True, bar = True  }) @?= True )++example :: Natural -> Text -> Text -> TestTree+example n text0 text1 =+    Test.Tasty.HUnit.testCase+        ("Example #" <> show n)+        (Util.equivalent text0 text1)
+ tests/Dhall/Test/TypeInference.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.TypeInference where++import Control.Exception (SomeException (..))+import Data.Text         (Text)+import System.FilePath   ((</>))+import Test.Tasty        (TestTree)++import qualified Control.Exception as Exception+import qualified Data.Text         as Text+import qualified Data.Text.IO      as Text.IO+import qualified Dhall.Core        as Core+import qualified Dhall.Import      as Import+import qualified Dhall.Parser      as Parser+import qualified Dhall.Test.Util   as Test.Util+import qualified Dhall.TypeCheck   as TypeCheck+import qualified System.FilePath   as FilePath+import qualified Test.Tasty        as Tasty+import qualified Test.Tasty.HUnit  as Tasty.HUnit+import qualified Turtle++typeInferenceDirectory :: FilePath+typeInferenceDirectory = "./dhall-lang/tests/type-inference"++getTests :: IO TestTree+getTests = do+    let successTestFiles = do+            path <- Turtle.lstree (typeInferenceDirectory </> "success")++            let skip =+                    -- These tests intermittently fails with:+                    -- "Error: Remote host not found"+                    [ typeInferenceDirectory </> "success/CacheImportsA.dhall"+                    , typeInferenceDirectory </> "success/CacheImportsCanonicalizeA.dhall"+                    ]++            path `Test.Util.pathNotIn` skip++            return path++    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest successTestFiles++    let failureTestFiles = Turtle.lstree (typeInferenceDirectory </> "failure")++    failureTests <- Test.Util.discover (Turtle.chars <* ".dhall") failureTest failureTestFiles++    let testTree = Tasty.testGroup "type-inference tests"+            [ successTests+            , failureTests+            ]++    return testTree++successTest :: Text -> TestTree+successTest prefix = do+    let expectedFailures =+                []+#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+#else+            ++  [ typeInferenceDirectory </> "success/CacheImports"+                ]+#endif++    Test.Util.testCase prefix expectedFailures $ do+        let prefixFP = Text.unpack prefix++        actualCode <- Text.IO.readFile (prefixFP <> "A.dhall")++        actualExpr <- Core.throws (Parser.exprFromText mempty actualCode)++        tryResolvedExpr <-+            Exception.try+               (Test.Util.loadRelativeTo+                   (FilePath.takeDirectory prefixFP)+                   Import.IgnoreSemanticCache+                   (Core.denote actualExpr))++        resolvedExpr <- case tryResolvedExpr of+            Left  exception    -> Tasty.HUnit.assertFailure (show (exception :: SomeException))+            Right resolvedExpr -> return resolvedExpr++        expectedTypeCode <- Text.IO.readFile (prefixFP <> "B.dhall")++        expectedType <- Core.throws (Parser.exprFromText mempty expectedTypeCode)++        resolvedExpectedType <- Import.assertNoImports (Core.denote expectedType)++        inferredType <- case TypeCheck.typeOf resolvedExpr of+            Left  exception    -> Tasty.HUnit.assertFailure (show exception)+            Right inferredType -> return inferredType++        let message = "The inferred type did not match the expected type"++        Tasty.HUnit.assertEqual message resolvedExpectedType inferredType++        -- We also add this to exercise the `Dhall.Eval.conv` code path, since+        -- it's easy to forget to update it when adding new syntax+        _ <- Core.throws (TypeCheck.typeOf (Core.Annot resolvedExpr resolvedExpectedType))+        return ()++failureTest :: Text -> TestTree+failureTest prefix = do+    let expectedFailures =+               [+               -- Duplicate fields are incorrectly caught during parsing:+               -- https://github.com/dhall-lang/dhall-haskell/issues/772+                 typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields"+               , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants1"+               , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants2"+               ]++    Test.Util.testCase prefix expectedFailures $ do+        let prefixFP = Text.unpack prefix++        code <- Text.IO.readFile (prefixFP <> ".dhall")++        expression <- case Parser.exprFromText mempty code of+            Left _ -> Tasty.HUnit.assertFailure (prefixFP <> " should have parsed")+            Right e -> return e++        resolved <- Import.assertNoImports expression++        case TypeCheck.typeOf resolved of+            Left  _ -> return ()+            Right _ -> Tasty.HUnit.assertFailure (prefixFP <> " should not have type-checked")
+ tests/Dhall/Test/Util.hs view
@@ -0,0 +1,333 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE ViewPatterns      #-}++module Dhall.Test.Util+    ( code+    , codeWith+    , equivalent+    , load+    , loadRelativeTo+    , loadWith+    , normalize'+    , normalizeWith'+    , assertNormalizesTo+    , assertNormalizesToWith+    , assertNormalized+    , assertTypeChecks+    , assertDoesntTypeCheck+    , discover+    , Dhall.Test.Util.testCase+    , pathIn+    , pathNotIn+    , pathNotPrefixOf+    , pathNotSuffixOf+    , toDhallPath+    , managedTestEnvironment+    ) where++import Control.Applicative              (Alternative, liftA2, (<|>))+import Control.Exception                (tryJust)+import Control.Monad                    (guard)+import Control.Monad.Trans.State.Strict (StateT)+import Data.Bifunctor                   (first)+import Data.Text                        (Text)+import Data.Void                        (Void)+import Dhall.Context                    (Context)+import Dhall.Core+    ( Chunks (..)+    , Expr (..)+    , Import+    , Normalizer+    , ReifiedNormalizer (..)+    )+import Dhall.Import                     (SemanticCacheMode (..), Status (..))+import Dhall.Parser                     (Src)+import System.IO.Error                  (isDoesNotExistError)+import Test.Tasty                       (TestTree)+import Test.Tasty.HUnit+import Turtle                           (Pattern, Shell, fp)++import qualified Control.Exception+import qualified Control.Foldl                    as Foldl+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Functor+import qualified Data.List                        as List+import qualified Data.Text                        as Text+import qualified Data.Text.IO                     as Text.IO+import qualified Dhall.Context+import qualified Dhall.Core+import qualified Dhall.Import+import qualified Dhall.Map+import qualified Dhall.Parser+import qualified Dhall.TypeCheck+import qualified System.FilePath                  as FilePath+import qualified Test.Tasty                       as Tasty+import qualified Test.Tasty.ExpectedFailure       as Tasty.ExpectedFailure+import qualified Turtle++#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Data.Foldable+#else+import Control.Monad.IO.Class (MonadIO (..))+import Dhall.Core             (Directory (..), File (..), URL (..))+import Lens.Micro.Mtl         (zoom)++import qualified Data.Foldable+import qualified Data.Text.Encoding+import qualified Data.Text.IO+#endif++normalize' :: Expr Src Void -> Text+normalize' = Dhall.Core.pretty . Dhall.Core.normalize++normalizeWith' :: Normalizer Void -> Expr Src Void -> Text+normalizeWith' ctx t =+  Dhall.Core.pretty (Dhall.Core.normalizeWith (Just (ReifiedNormalizer ctx)) t)++code :: Text -> IO (Expr Src Void)+code = codeWith Dhall.Context.empty++codeWith :: Context (Expr Src Void) -> Text -> IO (Expr Src Void)+codeWith ctx expr = do+    expr0 <- case Dhall.Parser.exprFromText mempty expr of+        Left parseError -> Control.Exception.throwIO parseError+        Right expr0     -> return expr0+    expr1 <- load expr0+    case Dhall.TypeCheck.typeWith ctx expr1 of+        Left typeError -> Control.Exception.throwIO typeError+        Right _        -> return ()+    return expr1++load :: Expr Src Import -> IO (Expr Src Void)+load = loadRelativeTo "." UseSemanticCache++loadRelativeTo :: FilePath.FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)+loadRelativeTo rootDirectory semanticCacheMode expression =+    State.evalStateT+        (loadWith expression)+        (Dhall.Import.emptyStatus rootDirectory) { _semanticCacheMode = semanticCacheMode }++#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith = Dhall.Import.loadWith++#else+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith expr = do+    zoom Dhall.Import.remote (State.put mockRemote)+    Dhall.Import.loadWith expr++mockRemote :: Dhall.Core.URL -> StateT Status IO Data.Text.Text+mockRemote+    url@URL+        { authority = "raw.githubusercontent.com"+        , path = File (Directory components) file+        } = do+    let localDir = case reverse components of+            "dhall-lang" : "dhall-lang" : _ : rest ->+                reverse ("dhall-lang" : rest)+            "Nadrieril" : "dhall-rust" : _ : "dhall" : rest ->+                reverse ("dhall-lang" : rest)+            _ -> do+                fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++    localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file)++    liftIO (Data.Text.IO.readFile localPath)++mockRemote+    URL { authority = "prelude.dhall-lang.org"+        , path = File (Directory components) file+        } = do+    let localDir = components ++ [ "Prelude", "dhall-lang" ]++    localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file)++    liftIO (Data.Text.IO.readFile localPath)++mockRemote url@URL{ authority = "test.dhall-lang.org", path, headers } =+    case (path, fmap Dhall.Import.toHeaders headers) of+        (File (Directory []) "foo", Just [("test", _)]) ->+            return "./bar"+        (File (Directory []) "bar", Just [("test", _)]) ->+            return "True"+        (File (Directory ["cors"]) "AllowedAll.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlyGithub.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlySelf.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlyOther.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "Empty.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "NoCORS.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "Null.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "SelfImportAbsolute.dhall", _) ->+            return "https://test.dhall-lang.org/cors/NoCORS.dhall"+        (File (Directory ["cors"]) "SelfImportRelative.dhall", _) ->+            return "./NoCORS.dhall"+        (File (Directory ["cors"]) "TwoHopsFail.dhall", _) ->+            return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall"+        (File (Directory ["cors"]) "TwoHopsSuccess.dhall", _) ->+            return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall"+        _ -> do+            fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++mockRemote url@URL{ authority = "httpbin.org", path, headers } =+    case (path, fmap Dhall.Import.toHeaders headers) of+        (File (Directory []) "user-agent", Just [("user-agent", userAgent)]) -> do+            let agentText = Data.Text.Encoding.decodeUtf8 userAgent++            return ("{\n  \"user-agent\": \"" <> agentText <> "\"\n}\n")+        (File (Directory []) "user-agent", Nothing) -> do+            return ("{\n  \"user-agent\": \"Dhall\"\n}\n")+        _ -> do+            fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++mockRemote url = do+    let urlString = Text.unpack (Dhall.Core.pretty url)+    fail ("(mock http) Url does not match any of the hard-coded rules: "+        <> urlString)+#endif++{- Given a test prefix, returns a managed resource+   which sets / reverts relevant environment variables based+   on `prefix <> "ENV.dhall"` (if present)+ -}+managedTestEnvironment :: Text -> Turtle.Managed [(Text, Maybe Text)]+managedTestEnvironment prefix = Turtle.managed (Control.Exception.bracket setup cleanup)+  where+    envPath = Text.unpack (prefix <> "ENV.dhall")++    setup :: IO [(Text, Maybe Text)]+    setup = do+        envFileContents <-+            tryJust (guard . isDoesNotExistError) (Text.IO.readFile envPath)++        testEnv <- case envFileContents of+            Right contents -> do+                resolved <- code contents+                return (convertEnvExpr (Dhall.Core.normalize resolved))+            Left _ -> return []++        traverse setEnv testEnv++    cleanup :: [(Text, Maybe Text)] -> IO ()+    cleanup = Data.Foldable.traverse_ restoreEnv++    convertEnvExpr :: Expr Src Void -> [(Text, Text)]+    convertEnvExpr (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybePairs)+      where+          maybePairs = mapM toPair hs++          toPair :: Expr s a -> Maybe (Text, Text)+          toPair (RecordLit m) = do+              (Dhall.Core.recordFieldValue -> TextLit (Chunks [] key), Dhall.Core.recordFieldValue -> TextLit (Chunks [] value))+                  <- lookupHeader <|> lookupMapKey+              return (key, value)+                where+                  lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)+                  lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+          toPair _ = Nothing+    convertEnvExpr _ = []++    setEnv :: (Text, Text) -> IO (Text, Maybe Text)+    setEnv (k, v) = do+        old <- Turtle.need k+        Turtle.export k v+        return (k, old)++    restoreEnv :: (Text, Maybe Text) -> IO ()+    restoreEnv (k, Just old) = Turtle.export k old+    restoreEnv (k, Nothing) = Turtle.unset k++equivalent :: Text -> Text -> IO ()+equivalent text0 text1 = do+    expr0 <- fmap Dhall.Core.normalize (code text0) :: IO (Expr Void Void)+    expr1 <- fmap Dhall.Core.normalize (code text1) :: IO (Expr Void Void)+    assertEqual "Expressions are not equivalent" expr0 expr1++assertNormalizesTo :: Expr Src Void -> Text -> IO ()+assertNormalizesTo e expected = do+  assertBool msg (not $ Dhall.Core.isNormalized e)+  normalize' e @?= expected+  where msg = "Given expression is already in normal form"++assertNormalizesToWith :: Normalizer Void -> Expr Src Void -> Text -> IO ()+assertNormalizesToWith ctx e expected = do+  assertBool msg (not $ Dhall.Core.isNormalizedWith ctx (first (const ()) e))+  normalizeWith' ctx e @?= expected+  where msg = "Given expression is already in normal form"++assertNormalized :: Expr Src Void -> IO ()+assertNormalized e = do+  assertBool msg1 (Dhall.Core.isNormalized e)+  assertEqual msg2 (normalize' e) (Dhall.Core.pretty e)+  where msg1 = "Expression was not in normal form"+        msg2 = "Normalization is not supposed to change the expression"++assertTypeChecks :: Text -> IO ()+assertTypeChecks text = Data.Functor.void (code text)++assertDoesntTypeCheck :: Text -> IO ()+assertDoesntTypeCheck text = do+    expr0 <- case Dhall.Parser.exprFromText mempty text of+        Left parseError -> Control.Exception.throwIO parseError+        Right e         -> return e+    expr1 <- load expr0+    case Dhall.TypeCheck.typeOf expr1 of+        Left _      -> return ()+        Right type_ -> fail ("Bad type for " <> Text.unpack text <> "\n  " <> show type_)++{-| Automatically run a test on all files in a directory tree that end in+    @A.dhall@+-}+discover :: Pattern Text -> (Text -> TestTree) -> Shell FilePath -> IO TestTree+discover pattern buildTest paths = do+    let shell = do+            path_ <- paths++            let pathText = Turtle.format fp (FilePath.normalise path_)++            prefix : _ <- return (Turtle.match pattern pathText)++            return (buildTest prefix)++    tests <- Turtle.fold shell Foldl.list++    return (Tasty.testGroup "discover" tests)++testCase :: Text -> [ FilePath ] -> Assertion -> TestTree+testCase prefix expectedFailures assertion =+    if prefix `elem` map (Turtle.format fp . FilePath.normalise) expectedFailures+    then Tasty.ExpectedFailure.expectFail test+    else test+  where+    test = Test.Tasty.HUnit.testCase (Text.unpack prefix) assertion++pathIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathIn this = guard . any (FilePath.equalFilePath this)++pathNotIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathNotIn this = guard . not . any (FilePath.equalFilePath this)++pathNotPrefixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotPrefixOf this =+    guard . not . List.isPrefixOf (FilePath.normalise this) . FilePath.normalise++pathNotSuffixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotSuffixOf this =+    guard . not . List.isSuffixOf (FilePath.normalise this) . FilePath.normalise++{-| Path names on Windows are not valid Dhall paths due to using backslashes+    instead of forwardslashes to separate path components.  This utility fixes+    them if necessary+-}+toDhallPath :: Text -> Text+toDhallPath = ("./" <>) . Text.replace "\\" "/"
− tests/Format.hs
@@ -1,69 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Format where--import Data.Monoid (mempty, (<>))-import Data.Text (Text)-import Test.Tasty (TestTree)--import qualified Control.Exception-import qualified Data.Text-import qualified Data.Text.Lazy.IO-import qualified Data.Text.Prettyprint.Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text-import qualified Dhall.Parser-import qualified Test.Tasty-import qualified Test.Tasty.HUnit--formatTests :: TestTree-formatTests =-    Test.Tasty.testGroup "format tests"-        [ should-            "prefer multi-line strings when newlines present"-            "multiline"-        , should-            "escape ${ for single-quoted strings"-            "escapeSingleQuotedOpenInterpolation"-        , should-            "preserve the original order of fields"-            "fieldOrder"-        , should-            "escape numeric labels correctly"-            "escapeNumericLabel"-        , should-            "correctly handle scientific notation with a large exponent"-            "largeExponent"-        , should-            "correctly format the empty record literal"-            "emptyRecord"-        ]--opts :: Data.Text.Prettyprint.Doc.LayoutOptions-opts =-    Data.Text.Prettyprint.Doc.defaultLayoutOptions-        { Data.Text.Prettyprint.Doc.layoutPageWidth =-            Data.Text.Prettyprint.Doc.AvailablePerLine 80 1.0-        }--should :: Text -> Text -> TestTree-should name basename =-    Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do-        let inputFile =-                Data.Text.unpack ("./tests/format/" <> basename <> "A.dhall")-        let outputFile =-                Data.Text.unpack ("./tests/format/" <> basename <> "B.dhall")-        inputText <- Data.Text.Lazy.IO.readFile inputFile--        expr <- case Dhall.Parser.exprFromText mempty inputText of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr--        let doc        = Data.Text.Prettyprint.Doc.pretty expr-        let docStream  = Data.Text.Prettyprint.Doc.layoutSmart opts doc-        let actualText = Data.Text.Prettyprint.Doc.Render.Text.renderLazy docStream--        expectedText <- Data.Text.Lazy.IO.readFile outputFile--        let message =-                "The formatted expression did not match the expected output"-        Test.Tasty.HUnit.assertEqual message expectedText actualText
− tests/Normalization.hs
@@ -1,248 +0,0 @@-{-# LANGUAGE OverloadedLists   #-}-{-# LANGUAGE OverloadedStrings #-}--module Normalization (normalizationTests) where--import Data.Monoid ((<>))-import Data.Text.Lazy (Text)-import Dhall.Core (Expr)-import Dhall.TypeCheck (X)--import qualified Control.Exception-import qualified Data.Text.Lazy-import qualified Dhall.Core-import qualified Dhall.Import-import qualified Dhall.Parser-import qualified Dhall.TypeCheck--import Dhall.Core-import Dhall.Context-import Test.Tasty-import Test.Tasty.HUnit-import Util --normalizationTests :: TestTree-normalizationTests =-    testGroup "normalization"-        [ examples-        , simplifications-        , constantFolding-        , conversions-        , shouldNormalize "Optional build/fold fusion" "optionalBuildFold"-        , customization-        , shouldNormalize "a remote-systems.conf builder" "remoteSystems"-        ]--examples :: TestTree-examples =-    testGroup "Prelude examples"-        [ shouldNormalize "Bool/and" "./examples/Bool/and/0"-        , shouldNormalize "Bool/and" "./examples/Bool/and/1"-        , shouldNormalize "Bool/build" "./examples/Bool/build/0"-        , shouldNormalize "Bool/build" "./examples/Bool/build/1"-        , shouldNormalize "Bool/even" "./examples/Bool/even/0"-        , shouldNormalize "Bool/even" "./examples/Bool/even/1"-        , shouldNormalize "Bool/even" "./examples/Bool/even/2"-        , shouldNormalize "Bool/even" "./examples/Bool/even/3"-        , shouldNormalize "Bool/fold" "./examples/Bool/fold/0"-        , shouldNormalize "Bool/fold" "./examples/Bool/fold/1"-        , shouldNormalize "Bool/not" "./examples/Bool/not/0"-        , shouldNormalize "Bool/not" "./examples/Bool/not/1"-        , shouldNormalize "Bool/odd" "./examples/Bool/odd/0"-        , shouldNormalize "Bool/odd" "./examples/Bool/odd/1"-        , shouldNormalize "Bool/odd" "./examples/Bool/odd/2"-        , shouldNormalize "Bool/odd" "./examples/Bool/odd/3"-        , shouldNormalize "Bool/or" "./examples/Bool/or/0"-        , shouldNormalize "Bool/or" "./examples/Bool/or/1"-        , shouldNormalize "Bool/show" "./examples/Bool/show/0"-        , shouldNormalize "Bool/show" "./examples/Bool/show/1"-        , shouldNormalize "Double/show" "./examples/Double/show/0"-        , shouldNormalize "Double/show" "./examples/Double/show/1"-        , shouldNormalize "Integer/show" "./examples/Integer/show/0"-        , shouldNormalize "Integer/show" "./examples/Integer/show/1"-        , shouldNormalize "List/all" "./examples/List/all/0"-        , shouldNormalize "List/all" "./examples/List/all/1"-        , shouldNormalize "List/any" "./examples/List/any/0"-        , shouldNormalize "List/any" "./examples/List/any/1"-        , shouldNormalize "List/build" "./examples/List/build/0"-        , shouldNormalize "List/build" "./examples/List/build/1"-        , shouldNormalize "List/concat" "./examples/List/concat/0"-        , shouldNormalize "List/concat" "./examples/List/concat/1"-        , shouldNormalize "List/concatMap" "./examples/List/concatMap/0"-        , shouldNormalize "List/concatMap" "./examples/List/concatMap/1"-        , shouldNormalize "List/filter" "./examples/List/filter/0"-        , shouldNormalize "List/filter" "./examples/List/filter/1"-        , shouldNormalize "List/fold" "./examples/List/fold/0"-        , shouldNormalize "List/fold" "./examples/List/fold/1"-        , shouldNormalize "List/fold" "./examples/List/fold/2"-        , shouldNormalize "List/generate" "./examples/List/generate/0"-        , shouldNormalize "List/generate" "./examples/List/generate/1"-        , shouldNormalize "List/head" "./examples/List/head/0"-        , shouldNormalize "List/head" "./examples/List/head/1"-        , shouldNormalize "List/iterate" "./examples/List/iterate/0"-        , shouldNormalize "List/iterate" "./examples/List/iterate/1"-        , shouldNormalize "List/last" "./examples/List/last/0"-        , shouldNormalize "List/last" "./examples/List/last/1"-        , shouldNormalize "List/length" "./examples/List/length/0"-        , shouldNormalize "List/length" "./examples/List/length/1"-        , shouldNormalize "List/map" "./examples/List/map/0"-        , shouldNormalize "List/map" "./examples/List/map/1"-        , shouldNormalize "List/null" "./examples/List/null/0"-        , shouldNormalize "List/null" "./examples/List/null/1"-        , shouldNormalize "List/replicate" "./examples/List/replicate/0"-        , shouldNormalize "List/replicate" "./examples/List/replicate/1"-        , shouldNormalize "List/reverse" "./examples/List/reverse/0"-        , shouldNormalize "List/reverse" "./examples/List/reverse/1"-        , shouldNormalize "List/shifted" "./examples/List/shifted/0"-        , shouldNormalize "List/shifted" "./examples/List/shifted/1"-        , shouldNormalize "List/unzip" "./examples/List/unzip/0"-        , shouldNormalize "List/unzip" "./examples/List/unzip/1"-        , shouldNormalize "Natural/build" "./examples/Natural/build/0"-        , shouldNormalize "Natural/build" "./examples/Natural/build/1"-        , shouldNormalize "Natural/enumerate" "./examples/Natural/enumerate/0"-        , shouldNormalize "Natural/enumerate" "./examples/Natural/enumerate/1"-        , shouldNormalize "Natural/even" "./examples/Natural/even/0"-        , shouldNormalize "Natural/even" "./examples/Natural/even/1"-        , shouldNormalize "Natural/fold" "./examples/Natural/fold/0"-        , shouldNormalize "Natural/fold" "./examples/Natural/fold/1"-        , shouldNormalize "Natural/fold" "./examples/Natural/fold/2"-        , shouldNormalize "Natural/isZero" "./examples/Natural/isZero/0"-        , shouldNormalize "Natural/isZero" "./examples/Natural/isZero/1"-        , shouldNormalize "Natural/odd" "./examples/Natural/odd/0"-        , shouldNormalize "Natural/odd" "./examples/Natural/odd/1"-        , shouldNormalize "Natural/product" "./examples/Natural/product/0"-        , shouldNormalize "Natural/product" "./examples/Natural/product/1"-        , shouldNormalize "Natural/show" "./examples/Natural/show/0"-        , shouldNormalize "Natural/show" "./examples/Natural/show/1"-        , shouldNormalize "Natural/sum" "./examples/Natural/sum/0"-        , shouldNormalize "Natural/sum" "./examples/Natural/sum/1"-        , shouldNormalize "Natural/toInteger" "./examples/Natural/toInteger/0"-        , shouldNormalize "Natural/toInteger" "./examples/Natural/toInteger/1"-        , shouldNormalize "Optional/all" "./examples/Optional/all/0"-        , shouldNormalize "Optional/all" "./examples/Optional/all/1"-        , shouldNormalize "Optional/any" "./examples/Optional/any/0"-        , shouldNormalize "Optional/any" "./examples/Optional/any/1"-        , shouldNormalize "Optional/build" "./examples/Optional/build/0"-        , shouldNormalize "Optional/build" "./examples/Optional/build/1"-        , shouldNormalize "Optional/concat" "./examples/Optional/concat/0"-        , shouldNormalize "Optional/concat" "./examples/Optional/concat/1"-        , shouldNormalize "Optional/concat" "./examples/Optional/concat/2"-        , shouldNormalize "Optional/filter" "./examples/Optional/filter/0"-        , shouldNormalize "Optional/filter" "./examples/Optional/filter/1"-        , shouldNormalize "Optional/fold" "./examples/Optional/fold/0"-        , shouldNormalize "Optional/fold" "./examples/Optional/fold/1"-        , shouldNormalize "Optional/head" "./examples/Optional/head/0"-        , shouldNormalize "Optional/head" "./examples/Optional/head/1"-        , shouldNormalize "Optional/last" "./examples/Optional/last/0"-        , shouldNormalize "Optional/last" "./examples/Optional/last/1"-        , shouldNormalize "Optional/length" "./examples/Optional/length/0"-        , shouldNormalize "Optional/length" "./examples/Optional/length/1"-        , shouldNormalize "Optional/map" "./examples/Optional/map/0"-        , shouldNormalize "Optional/map" "./examples/Optional/map/1"-        , shouldNormalize "Optional/null" "./examples/Optional/null/0"-        , shouldNormalize "Optional/null" "./examples/Optional/null/1"-        , shouldNormalize "Optional/toList" "./examples/Optional/toList/0"-        , shouldNormalize "Optional/toList" "./examples/Optional/toList/1"-        , shouldNormalize "Optional/unzip" "./examples/Optional/unzip/0"-        , shouldNormalize "Optional/unzip" "./examples/Optional/unzip/1"-        , shouldNormalize "Text/concat" "./examples/Text/concat/0"-        , shouldNormalize "Text/concat" "./examples/Text/concat/1"-        , shouldNormalize "Text/concatMap" "./examples/Text/concatMap/0"-        , shouldNormalize "Text/concatMap" "./examples/Text/concatMap/1"-        , shouldNormalize "Text/concatMapSep" "./examples/Text/concatMapSep/0"-        , shouldNormalize "Text/concatMapSep" "./examples/Text/concatMapSep/1"-        , shouldNormalize "Text/concatSep" "./examples/Text/concatSep/0"-        , shouldNormalize "Text/concatSep" "./examples/Text/concatSep/1"-        ]--simplifications :: TestTree-simplifications =-    testGroup "Simplifications"-        [ shouldNormalize "if/then/else" "./simplifications/ifThenElse"-        , shouldNormalize "||" "./simplifications/or"-        , shouldNormalize "&&" "./simplifications/and"-        , shouldNormalize "==" "./simplifications/eq"-        , shouldNormalize "!=" "./simplifications/ne"-        ]--constantFolding :: TestTree-constantFolding =-    testGroup "folding of constants"-        [ shouldNormalize "Natural/plus"   "naturalPlus"-        , shouldNormalize "Optional/fold"  "optionalFold"-        , shouldNormalize "Optional/build" "optionalBuild"-        ]--conversions :: TestTree-conversions =-    testGroup "conversions"-        [ shouldNormalize "Natural/show" "naturalShow"-        , shouldNormalize "Integer/show" "integerShow"-        , shouldNormalize "Double/show"  "doubleShow"-        , shouldNormalize "Natural/toInteger" "naturalToInteger"-        ]--customization :: TestTree-customization =-    testGroup "customization"-        [ simpleCustomization-        , nestedReduction-        ]--simpleCustomization :: TestTree-simpleCustomization = testCase "simpleCustomization" $ do-  let tyCtx  = insert "min" (Pi "_" Natural (Pi "_" Natural Natural)) empty -      valCtx e = case e of-                    (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y)) -> Just (NaturalLit (min x y))-                    _ -> Nothing-  e <- codeWith tyCtx "min (min +11 +12) +8 + +1" -  assertNormalizesToWith valCtx e "+9"--nestedReduction :: TestTree-nestedReduction = testCase "doubleReduction" $ do-  minType        <- insert "min"        <$> code "Natural → Natural → Natural"-  fiveorlessType <- insert "fiveorless" <$> code "Natural → Natural"-  wurbleType     <- insert "wurble"     <$> code "Natural → Integer"-  let tyCtx = minType . fiveorlessType . wurbleType $ empty-      valCtx e = case e of-                    (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y)) -> Just (NaturalLit (min x y))-                    (App (Var (V "wurble" 0)) (NaturalLit x)) -> Just-                        (App (Var (V "fiveorless" 0)) (NaturalPlus (NaturalLit x) (NaturalLit 2))) -                    (App (Var (V "fiveorless" 0)) (NaturalLit x)) -> Just-                        (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalPlus (NaturalLit 3) (NaturalLit 2)))-                    _ -> Nothing-  e <- codeWith tyCtx "wurble +6"-  assertNormalizesToWith valCtx e "+5"--should :: Text -> Text -> TestTree-should name basename =-    Test.Tasty.HUnit.testCase (Data.Text.Lazy.unpack name) $ do-        let actualCode   = "./tests/normalization/" <> basename <> "A.dhall"-        let expectedCode = "./tests/normalization/" <> basename <> "B.dhall"--        actualExpr <- case Dhall.Parser.exprFromText mempty actualCode of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr-        actualResolved <- Dhall.Import.load actualExpr-        case Dhall.TypeCheck.typeOf actualResolved of-            Left  err -> Control.Exception.throwIO err-            Right _   -> return ()-        let actualNormalized = Dhall.Core.normalize actualResolved :: Expr X X--        expectedExpr <- case Dhall.Parser.exprFromText mempty expectedCode of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr-        expectedResolved <- Dhall.Import.load expectedExpr-        case Dhall.TypeCheck.typeOf expectedResolved of-            Left  err -> Control.Exception.throwIO err-            Right _   -> return ()-        -- Use `denote` instead of `normalize` to enforce that the expected-        -- expression is already in normal form-        let expectedNormalized = Dhall.Core.denote expectedResolved--        let message =-                "The normalized expression did not match the expected output"-        Test.Tasty.HUnit.assertEqual message expectedNormalized actualNormalized--shouldNormalize :: Text -> Text -> TestTree-shouldNormalize name = should ("normalize " <> name <> " correctly")
− tests/Parser.hs
@@ -1,141 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Parser where--import Data.Text (Text)-import Test.Tasty (TestTree)--import qualified Control.Exception-import qualified Data.Text-import qualified Data.Text.Lazy.IO-import qualified Dhall.Parser-import qualified Test.Tasty-import qualified Test.Tasty.HUnit--parserTests :: TestTree-parserTests =-    Test.Tasty.testGroup "parser tests"-        [ Test.Tasty.testGroup "whitespace"-            [ shouldParse-                "prefix/suffix"-                "./tests/parser/whitespace.dhall"-            , shouldParse-                "block comment"-                "./tests/parser/blockComment.dhall"-            , shouldParse-                "nested block comment"-                "./tests/parser/nestedBlockComment.dhall"-            , shouldParse-                "line comment"-                "./tests/parser/lineComment.dhall"-            , shouldParse-                "Unicode comment"-                "./tests/parser/unicodeComment.dhall"-            , shouldParse-                "whitespace buffet"-                "./tests/parser/whitespaceBuffet.dhall"-            , shouldParse-                "label"-                "./tests/parser/label.dhall"-            , shouldParse-                "quoted label"-                "./tests/parser/quotedLabel.dhall"-            , shouldParse-                "double quoted string"-                "./tests/parser/doubleQuotedString.dhall"-            , shouldParse-                "Unicode double quoted string"-                "./tests/parser/unicodeDoubleQuotedString.dhall"-            , shouldParse-                "escaped double quoted string"-                "./tests/parser/escapedDoubleQuotedString.dhall"-            , shouldParse-                "interpolated double quoted string"-                "./tests/parser/interpolatedDoubleQuotedString.dhall"-            , shouldParse-                "single quoted string"-                "./tests/parser/singleQuotedString.dhall"-            , shouldParse-                "escaped single quoted string"-                "./tests/parser/escapedSingleQuotedString.dhall"-            , shouldParse-                "interpolated single quoted string"-                "./tests/parser/interpolatedSingleQuotedString.dhall"-            , shouldParse-                "double"-                "./tests/parser/double.dhall"-            , shouldParse-                "natural"-                "./tests/parser/natural.dhall"-            , shouldParse-                "identifier"-                "./tests/parser/identifier.dhall"-            , shouldParse-                "paths"-                "./tests/parser/paths.dhall"-            , shouldParse-                "path termination"-                "./tests/parser/pathTermination.dhall"-            , shouldParse-                "urls"-                "./tests/parser/urls.dhall"-            , shouldParse-                "environmentVariables"-                "./tests/parser/environmentVariables.dhall"-            , shouldParse-                "lambda"-                "./tests/parser/lambda.dhall"-            , shouldParse-                "if then else"-                "./tests/parser/ifThenElse.dhall"-            , shouldParse-                "let"-                "./tests/parser/let.dhall"-            , shouldParse-                "forall"-                "./tests/parser/forall.dhall"-            , shouldParse-                "function type"-                "./tests/parser/functionType.dhall"-            , shouldParse-                "operators"-                "./tests/parser/operators.dhall"-            , shouldParse-                "annotations"-                "./tests/parser/annotations.dhall"-            , shouldParse-                "merge"-                "./tests/parser/merge.dhall"-            , shouldParse-                "constructors"-                "./tests/parser/constructors.dhall"-            , shouldParse-                "fields"-                "./tests/parser/fields.dhall"-            , shouldParse-                "record"-                "./tests/parser/record.dhall"-            , shouldParse-                "union"-                "./tests/parser/union.dhall"-            , shouldParse-                "list"-                "./tests/parser/list.dhall"-            , shouldParse-                "builtins"-                "./tests/parser/builtins.dhall"-            , shouldParse-                "large expression"-                "./tests/parser/largeExpression.dhall"-            , shouldParse-                "names that begin with reserved identifiers"-                "./tests/parser/reservedPrefix.dhall"-            ]-        ]--shouldParse :: Text -> FilePath -> TestTree-shouldParse name path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do-    text <- Data.Text.Lazy.IO.readFile path-    case Dhall.Parser.exprFromText mempty text of-        Left err -> Control.Exception.throwIO err-        Right _  -> return () )
− tests/Regression.hs
@@ -1,246 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeApplications #-}--module Regression where--import qualified Control.Exception-import qualified Data.HashMap.Strict.InsOrd-import qualified Data.Text.Lazy.IO-import qualified Data.Text.Prettyprint.Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text-import qualified Dhall-import qualified Dhall.Context-import qualified Dhall.Core-import qualified Dhall.Parser-import qualified Dhall.TypeCheck-import qualified System.Timeout-import qualified Test.Tasty-import qualified Test.Tasty.HUnit-import qualified Util--import Control.DeepSeq (($!!))-import Dhall.Import (Imported)-import Dhall.Parser (Src)-import Dhall.TypeCheck (TypeError, X)-import Test.Tasty (TestTree)-import Test.Tasty.HUnit ((@?=))--regressionTests :: TestTree-regressionTests =-    Test.Tasty.testGroup "regression tests"-        [ issue96-        , issue126-        , issue151-        , issue164-        , issue201-        , issue209-        , issue216-        , issue253-        , parsing0-        , typeChecking0-        , typeChecking1-        , typeChecking2-        , unnamedFields-        , trailingSpaceAfterStringLiterals-        ]--data Foo = Foo Integer Bool | Bar Bool Bool Bool | Baz Integer Integer-    deriving (Show, Dhall.Generic, Dhall.Interpret, Dhall.Inject)--unnamedFields :: TestTree-unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do-    let ty = Dhall.auto @Foo-    Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty) (Dhall.Core.Union (-            Data.HashMap.Strict.InsOrd.fromList [-                ("Bar",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [-                    ("_1",Dhall.Core.Bool),("_2",Dhall.Core.Bool),("_3",Dhall.Core.Bool)]))-                , ("Baz",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [-                    ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Integer)]))-                ,("Foo",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [-                    ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)]))]))--    let inj = Dhall.inject @Foo-    Test.Tasty.HUnit.assertEqual "Good Inject" (Dhall.declared inj) (Dhall.expected ty)--    let tu_ty = Dhall.auto @(Integer, Bool)-    Test.Tasty.HUnit.assertEqual "Auto Tuple" (Dhall.expected tu_ty) (Dhall.Core.Record (-            Data.HashMap.Strict.InsOrd.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool) ]))--    let tu_in = Dhall.inject @(Integer, Bool)-    Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Dhall.declared tu_in) (Dhall.expected tu_ty)--    return () )--issue96 :: TestTree-issue96 = Test.Tasty.HUnit.testCase "Issue #96" (do-    -- Verify that parsing should not fail-    _ <- Util.code "\"bar'baz\""-    return () )--issue126 :: TestTree-issue126 = Test.Tasty.HUnit.testCase "Issue #126" (do-    e <- Util.code-        "''\n\-        \  foo\n\-        \  bar\n\-        \''"-    Util.normalize' e @?= "''\nfoo\nbar\n''" )--issue151 :: TestTree-issue151 = Test.Tasty.HUnit.testCase "Issue #151" (do-    let shouldNotTypeCheck text = do-            let handler :: Imported (TypeError Src X) -> IO Bool-                handler _ = return True--            let typeCheck = do-                    _ <- Util.code text-                    return False-            b <- Control.Exception.handle handler typeCheck-            Test.Tasty.HUnit.assertBool "The expression should not type-check" b--    -- These two examples contain the following expression that loops infinitely-    -- if you normalize the expression before type-checking the expression:-    ---    --     (λ(x : A) → x x) (λ(x : A) → x x)-    ---    -- There was a bug in the Dhall type-checker were expressions were not-    -- being type-checked before being added to the context (which is a-    -- violation of the standard type-checking rules for a pure type system).-    -- The reason this is problematic is that several places in the-    -- type-checking logic assume that the context is safe to normalize.-    ---    -- Both of these examples exercise area of the type-checker logic that-    -- assume that the context is normalized.  If you fail to type-check terms-    -- before adding them to the context then this test will "fail" with an-    -- infinite loop.  This test "succeeds" if the examples terminate-    -- immediately with a type-checking failure.-    shouldNotTypeCheck "./tests/regression/issue151a.dhall"-    shouldNotTypeCheck "./tests/regression/issue151b.dhall" )--issue164 :: TestTree-issue164 = Test.Tasty.HUnit.testCase "Issue #164" (do-    -- Verify that parsing should not fail on a single-quote within a-    -- single-quoted string-    _ <- Util.code "./tests/regression/issue164.dhall"-    return () )--issue201 :: TestTree-issue201 = Test.Tasty.HUnit.testCase "Issue #201" (do-    -- Verify that type synonyms work-    _ <- Util.code "./tests/regression/issue201.dhall"-    return () )--issue209 :: TestTree-issue209 = Test.Tasty.HUnit.testCase "Issue #209" (do-    -- Verify that pretty-printing `constructors` doesn't trigger an infinite-    -- loop-    e <- Util.code "./tests/regression/issue209.dhall"-    let text = Dhall.Core.pretty e-    Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $!! text)-    return () )--opts :: Data.Text.Prettyprint.Doc.LayoutOptions-opts =-    Data.Text.Prettyprint.Doc.defaultLayoutOptions-        { Data.Text.Prettyprint.Doc.layoutPageWidth =-            Data.Text.Prettyprint.Doc.AvailablePerLine 80 1.0-        }--issue216 :: TestTree-issue216 = Test.Tasty.HUnit.testCase "Issue #216" (do-    -- Verify that pretty-printing preserves string interpolation-    e <- Util.code "./tests/regression/issue216a.dhall"-    let doc       = Data.Text.Prettyprint.Doc.pretty e-    let docStream = Data.Text.Prettyprint.Doc.layoutSmart opts doc-    let text0 = Data.Text.Prettyprint.Doc.Render.Text.renderLazy docStream--    text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall"--    Test.Tasty.HUnit.assertEqual "Pretty-printing should preserve string interpolation" text1 text0 )--issue253 :: TestTree-issue253 = Test.Tasty.HUnit.testCase "Issue #253" (do-    -- Verify that type-checking rejects ill-formed custom contexts-    let context = Dhall.Context.insert "x" "x" Dhall.Context.empty-    let result = Dhall.TypeCheck.typeWith context "x"--    -- If the context is not validated correctly then type-checking will-    -- infinitely loop-    Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $! result)-    return () )--parsing0 :: TestTree-parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (do-    -- Verify that parsing should not fail-    ---    -- In 267093f8cddf1c2f909f2d997c31fd0a7cb2440a I broke the parser when left-    -- factoring the grammer by failing to handle the source tested by this-    -- regression test.  The root of the problem was that the parser was trying-    -- to parse `List ./Node` as `Field List "/Node"` instead of-    -- `App List (Embed (Path (File Homeless "./Node") Code))`.  The latter is-    -- the correct parse because `/Node` is not a valid field label, but the-    -- mistaken parser was committed to the incorrect parse and never attempted-    -- the correct parse.-    case Dhall.Parser.exprFromText mempty "List ./Node" of-        Left  e -> Control.Exception.throwIO e-        Right _ -> return () )--typeChecking0 :: TestTree-typeChecking0 = Test.Tasty.HUnit.testCase "Type-checking regression #0" (do-    -- There used to be a bug in the type-checking logic where `T` would be-    -- added to the context when inferring the type of `λ(x : T) → x`, but was-    -- missing from the context when inferring the kind of the inferred type-    -- (i.e. the kind of `∀(x : T) → T`).  This led to an unbound variable-    -- error when inferring the kind-    ---    -- This bug was originally reported in issue #10-    _ <- Util.code "let Day : Type = Natural in λ(x : Day) → x"-    return () )--typeChecking1 :: TestTree-typeChecking1 = Test.Tasty.HUnit.testCase "Type-checking regression #1" (do-    -- There used to be a bug in the type-checking logic when inferring the-    -- type of `let`.  Specifically, given an expression of the form:-    ---    --     let x : t = e1 in e2-    ---    -- ... the type-checker would not substitute `x` for `e1` in the inferred-    -- of the `let` expression.  This meant that if the inferred type contained-    -- any references to `x` then these references would escape their scope and-    -- result in unbound variable exceptions-    ---    -- This regression test exercises that code path by creating a `let`-    -- expression where the inferred type before substitution (`∀(x : b) → b` in-    -- this example), contains a reference to the `let`-bound variable (`b`)-    -- that needs to be substituted with `a` in order to produce the final-    -- correct inferred type (`∀(x : a) → a`).  If this test passes then-    -- substitution worked correctly.  If substitution doesn't occur then you-    -- expect an `Unbound variable` error from `b` escaping its scope due to-    -- being returned as part of the inferred type-    _ <- Util.code "λ(a : Type) → let b : Type = a in λ(x : b) → x"-    return () )--typeChecking2 :: TestTree-typeChecking2 = Test.Tasty.HUnit.testCase "Type-checking regression #2" (do-    -- There used to be a bug in the type-checking logic where `let` bound-    -- variables would not correctly shadow variables of the same name when-    -- inferring the type of of the `let` expression-    ---    -- This example exercises this code path with a `let` expression where the-    -- `let`-bound variable (`a`) has the same name as its own type (`a`).  If-    -- shadowing works correctly then the final `a` in the expression should-    -- refer to the `let`-bound variable and not its type.  An invalid reference-    -- to the shadowed type `a` would result in an invalid dependently typed-    -- function-    _ <- Util.code "λ(a : Type) → λ(x : a) → let a : a = x in a"-    return () )--trailingSpaceAfterStringLiterals :: TestTree-trailingSpaceAfterStringLiterals =-    Test.Tasty.HUnit.testCase "Trailing space after string literals" (do-        -- Verify that string literals parse correctly with trailing space-        -- (Yes, I did get this wrong at some point)-        _ <- Util.code "(''ABC'' ++ \"DEF\" )"-        return () )
− tests/Tests.hs
@@ -1,23 +0,0 @@-module Main where--import Normalization (normalizationTests)-import Parser (parserTests)-import Regression (regressionTests)-import Tutorial (tutorialTests)-import TypeCheck (typecheckTests)-import Format (formatTests)-import Test.Tasty--allTests :: TestTree-allTests =-    testGroup "Dhall Tests"-        [ normalizationTests-        , parserTests-        , regressionTests-        , tutorialTests-        , formatTests-        , typecheckTests-        ]--main :: IO ()-main = defaultMain allTests
− tests/Tutorial.hs
@@ -1,85 +0,0 @@-{-# LANGUAGE DeriveAnyClass    #-}-{-# LANGUAGE DeriveGeneric     #-}-{-# LANGUAGE OverloadedStrings #-}--module Tutorial where--import qualified Data.Vector-import qualified Dhall-import qualified Test.Tasty-import qualified Test.Tasty.HUnit-import qualified Util--import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall (Inject)-import GHC.Generics (Generic)-import Numeric.Natural (Natural)-import Test.Tasty (TestTree)-import Test.Tasty.HUnit ((@?=))--tutorialTests :: TestTree-tutorialTests =-    Test.Tasty.testGroup "tutorial"-        [ Test.Tasty.testGroup "Interpolation"-            [ _Interpolation_0-            , _Interpolation_1-            ]-        , Test.Tasty.testGroup "Functions"-            [ _Functions_0-            , _Functions_1-            , _Functions_2-            ]-        , Test.Tasty.testGroup "Unions"-            [ example 0 "./tests/tutorial/unions0A.dhall" "./tests/tutorial/unions0B.dhall"-            , example 1 "./tests/tutorial/unions1A.dhall" "./tests/tutorial/unions1B.dhall"-            , example 2 "./tests/tutorial/unions2A.dhall" "./tests/tutorial/unions2B.dhall"-            , example 3 "./tests/tutorial/unions3A.dhall" "./tests/tutorial/unions3B.dhall"-            , example 4 "./tests/tutorial/unions4A.dhall" "./tests/tutorial/unions4B.dhall"-            ]-        ]--_Interpolation_0 :: TestTree-_Interpolation_0 = Test.Tasty.HUnit.testCase "Example #0" (do-    e <- Util.code-        "    let name = \"John Doe\"                                 \n\-        \in  let age  = 21                                           \n\-        \in  \"My name is ${name} and my age is ${Integer/show age}\"\n"-    Util.assertNormalizesTo e "\"My name is John Doe and my age is 21\"" )--_Interpolation_1 :: TestTree-_Interpolation_1 = Test.Tasty.HUnit.testCase "Example #1" (do-    e <- Util.code-        "''                            \n\-        \    for file in *; do         \n\-        \      echo \"Found ''${file}\"\n\-        \    done                      \n\-        \''                            \n"-    Util.assertNormalized e )--_Functions_0 :: TestTree-_Functions_0 = Test.Tasty.HUnit.testCase "Example #0" (do-    let text = "\\(n : Bool) -> [ n && True, n && False, n || True, n || False ]"-    makeBools <- Dhall.input Dhall.auto text-    makeBools True @?= Data.Vector.fromList [True,False,True,True] )--_Functions_1 :: TestTree-_Functions_1 = Test.Tasty.HUnit.testCase "Example #1" (do-    let text = "λ(x : Bool) → λ(y : Bool) → x && y"-    makeBools <- Dhall.input Dhall.auto text-    makeBools True False @?= False )--data Example0 = Example0 { foo :: Bool, bar :: Bool }-    deriving (Generic, Inject)--_Functions_2 :: TestTree-_Functions_2 = Test.Tasty.HUnit.testCase "Example #2" (do-    f <- Dhall.input Dhall.auto "λ(r : { foo : Bool, bar : Bool }) → r.foo && r.bar"-    f (Example0 { foo = True, bar = False }) @?= False-    f (Example0 { foo = True, bar = True  }) @?= True )--example :: Natural -> Text -> Text -> TestTree-example n text0 text1 =-    Test.Tasty.HUnit.testCase-        ("Example #" <> show n)-        (Util.equivalent text0 text1)
− tests/TypeCheck.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module TypeCheck where--import Data.Monoid (mempty, (<>))-import Data.Text.Lazy (Text)-import Test.Tasty (TestTree)--import qualified Control.Exception-import qualified Data.Text.Lazy-import qualified Dhall.Core-import qualified Dhall.Import-import qualified Dhall.Parser-import qualified Dhall.TypeCheck-import qualified Test.Tasty-import qualified Test.Tasty.HUnit--typecheckTests :: TestTree-typecheckTests =-    Test.Tasty.testGroup "typecheck tests"-        [ Test.Tasty.testGroup "Prelude examples"-            [ should "Monoid" "./examples/Monoid/00"-            , should "Monoid" "./examples/Monoid/01"-            , should "Monoid" "./examples/Monoid/02"-            , should "Monoid" "./examples/Monoid/03"-            , should "Monoid" "./examples/Monoid/04"-            , should "Monoid" "./examples/Monoid/05"-            , should "Monoid" "./examples/Monoid/06"-            , should "Monoid" "./examples/Monoid/07"-            , should "Monoid" "./examples/Monoid/08"-            , should "Monoid" "./examples/Monoid/09"-            , should "Monoid" "./examples/Monoid/10"-            ]-        , should-            "allow type-valued fields in a record"-            "fieldsAreTypes"-        , should-            "allow type-valued alternatives in a union"-            "alternativesAreTypes"-        , should-            "allow anonymous functions in types to be judgmentally equal"-            "anonymousFunctionsInTypes"-        ]--should :: Text -> Text -> TestTree-should name basename =-    Test.Tasty.HUnit.testCase (Data.Text.Lazy.unpack name) $ do-        let actualCode   = "./tests/typecheck/" <> basename <> "A.dhall"-        let expectedCode = "./tests/typecheck/" <> basename <> "B.dhall"--        actualExpr <- case Dhall.Parser.exprFromText mempty actualCode of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr-        expectedExpr <- case Dhall.Parser.exprFromText mempty expectedCode of-            Left  err  -> Control.Exception.throwIO err-            Right expr -> return expr--        let annotatedExpr = Dhall.Core.Annot actualExpr expectedExpr--        resolvedExpr <- Dhall.Import.load annotatedExpr-        case Dhall.TypeCheck.typeOf resolvedExpr of-            Left  err -> Control.Exception.throwIO err-            Right _   -> return ()
− tests/Util.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-module Util-    ( code-    , codeWith-    , equivalent-    , normalize'-    , normalizeWith'-    , assertNormalizesTo-    , assertNormalizesToWith-    , assertNormalized-    , assertTypeChecks-    ) where--import qualified Control.Exception-import qualified Data.Functor-import           Data.Bifunctor (first)-import           Data.Text (Text)-import qualified Data.Text.Lazy-import qualified Dhall.Core-import           Dhall.Core (Expr, Normalizer)-import qualified Dhall.Context-import           Dhall.Context (Context)-import qualified Dhall.Import-import qualified Dhall.Parser-import           Dhall.Parser (Src)-import qualified Dhall.TypeCheck-import           Dhall.TypeCheck (X)-import           Test.Tasty.HUnit--normalize' :: Expr Src X -> Data.Text.Lazy.Text-normalize' = Dhall.Core.pretty . Dhall.Core.normalize--normalizeWith' :: Normalizer X -> Expr Src X -> Data.Text.Lazy.Text-normalizeWith' ctx = Dhall.Core.pretty . Dhall.Core.normalizeWith ctx--code :: Data.Text.Text -> IO (Expr Src X)-code = codeWith Dhall.Context.empty--codeWith :: Context (Expr Src X) -> Data.Text.Text -> IO (Expr Src X)-codeWith ctx strictText = do-    let lazyText = Data.Text.Lazy.fromStrict strictText-    expr0 <- case Dhall.Parser.exprFromText mempty lazyText of-        Left parseError -> Control.Exception.throwIO parseError-        Right expr0     -> return expr0-    expr1 <- Dhall.Import.load expr0-    case Dhall.TypeCheck.typeWith ctx expr1 of-        Left typeError -> Control.Exception.throwIO typeError-        Right _        -> return ()-    return expr1--equivalent :: Data.Text.Text -> Data.Text.Text -> IO ()-equivalent text0 text1 = do-    expr0 <- fmap Dhall.Core.normalize (Util.code text0) :: IO (Expr X X)-    expr1 <- fmap Dhall.Core.normalize (Util.code text1) :: IO (Expr X X)-    assertEqual "Expressions are not equivalent" expr0 expr1--assertNormalizesTo :: Expr Src X -> Data.Text.Lazy.Text -> IO ()-assertNormalizesTo e expected = do -  assertBool msg (not $ Dhall.Core.isNormalized e)-  normalize' e @?= expected-  where msg = "Given expression is already in normal form"--assertNormalizesToWith :: Normalizer X -> Expr Src X -> Data.Text.Lazy.Text -> IO ()-assertNormalizesToWith ctx e expected = do-  assertBool msg (not $ Dhall.Core.isNormalizedWith ctx (first (const ()) e))-  normalizeWith' ctx e @?= expected-  where msg = "Given expression is already in normal form"--assertNormalized :: Expr Src X -> IO ()-assertNormalized e = do-  assertBool msg1 (Dhall.Core.isNormalized e)-  assertEqual msg2 (normalize' e) (Dhall.Core.pretty e)-  where msg1 = "Expression was not in normal form"-        msg2 = "Normalization is not supposed to change the expression"--assertTypeChecks :: Text -> IO ()-assertTypeChecks text = Data.Functor.void (code text)
+ tests/diff/appList.txt view
@@ -0,0 +1,4 @@+  λ(… :   …+        → …)+→ …+  …
+ tests/diff/appListA.dhall view
@@ -0,0 +1,1 @@+λ(f : List Bool -> Bool) → f ([] : List Bool)
+ tests/diff/appListB.dhall view
@@ -0,0 +1,1 @@+λ(f : List Bool -> Bool) → f ([] : List Bool)
+ tests/diff/emptyList.txt view
@@ -0,0 +1,2 @@+- [] : …++ True
+ tests/diff/emptyListA.dhall view
@@ -0,0 +1,1 @@+[] : List Natural
+ tests/diff/emptyListB.dhall view
@@ -0,0 +1,1 @@+True
+ tests/diff/function.txt view
@@ -0,0 +1,6 @@+  …+→ …+→ …@- 1+    + 0++→ …
+ tests/diff/functionA.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(b : Type) → ∀(x : a) → Bool
+ tests/diff/functionB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(b : Type) → ∀(x : b) → Bool
+ tests/diff/insideList.txt view
@@ -0,0 +1,7 @@+[ …+, { y = - 4+        + 5+  , …+  }+]+
+ tests/diff/insideListA.dhall view
@@ -0,0 +1,3 @@+[ { x = 1, y = 2 }+, { x = 3, y = 4 }+]
+ tests/diff/insideListB.dhall view
@@ -0,0 +1,3 @@+[ { x = 1, y = 2 }+, { x = 3, y = 5 }+]
+ tests/diff/nonEmptyList.txt view
@@ -0,0 +1,2 @@+- [ … ]++ True
+ tests/diff/nonEmptyListA.dhall view
@@ -0,0 +1,1 @@+[1]
+ tests/diff/nonEmptyListB.dhall view
@@ -0,0 +1,1 @@+True
+ tests/diff/with.txt view
@@ -0,0 +1,5 @@+  λ(… : { …+        })+→ … with …+ .c.d+         = - 2+           + 3
+ tests/diff/withA.dhall view
@@ -0,0 +1,1 @@+λ(r : { a : Natural }) → r with b = 2
+ tests/diff/withB.dhall view
@@ -0,0 +1,1 @@+λ(r : { a : Natural }) → r with b.c.d = 3
+ tests/format/applicationMultilineA.dhall view
@@ -0,0 +1,33 @@+{ app =+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+      aaaaaaaaaaaaaaaaa+, app2 =+    f+      a+      b+      cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, app3 =+    f+      a+      b+      c+      dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd+, some =+    Some+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+, someList =+    Some+      [ aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccc, dddddddddddddd ]+, merge1 =+    merge+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+, merge3 =+    merge+      a+      b+      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, toMap1 =+    toMap+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+}
+ tests/format/applicationMultilineB.dhall view
@@ -0,0 +1,34 @@+{ app =+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+      aaaaaaaaaaaaaaaaa+, app2 =+    f+      a+      b+      cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, app3 =+    f+      a+      b+      c+      dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd+, some = Some+    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+, someList = Some+  [ aaaaaaaaaaaaaaaaaaaaaaaaaa+  , bbbbbbbbbbbbbbbbbbbb+  , cccccccccccccccccccccccc+  , dddddddddddddd+  ]+, merge1 =+    merge+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+, merge3 =+    merge+      a+      b+      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, toMap1 = toMap+    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+}
+ tests/format/asciiA.dhall view
@@ -0,0 +1,1 @@+λ(a : Type) → ∀(b : a) → a
+ tests/format/asciiB.dhall view
@@ -0,0 +1,1 @@+\(a : Type) -> forall (b : a) -> a
+ tests/format/concatSepA.dhall view
@@ -0,0 +1,30 @@+{-+Concatenate a `List` of `Text` values with a separator in between each value+-}+let Status = < Empty | NonEmpty : Text >++let concatSep+    : ∀(separator : Text) → ∀(elements : List Text) → Text+    =   λ(separator : Text)+      → λ(elements : List Text)+      → let status =+              List/fold Text elements Status+                (   λ(element : Text)+                  → λ(status : Status)+                  → merge+                      { Empty = Status.NonEmpty element+                      , NonEmpty =+                            λ(result : Text)+                          → Status.NonEmpty (element ++ separator ++ result)+                      }+                      status+                )+                Status.Empty+        +        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 = assert : concatSep ", " [ "ABC", "DEF", "GHI" ] ≡ "ABC, DEF, GHI"++let example1 = assert : concatSep ", " ([] : List Text) ≡ ""++in  concatSep
+ tests/format/concatSepB.dhall view
@@ -0,0 +1,33 @@+{-+Concatenate a `List` of `Text` values with a separator in between each value+-}+let Status = < Empty | NonEmpty : Text >++let concatSep+    : ∀(separator : Text) → ∀(elements : List Text) → Text+    = λ(separator : Text) →+      λ(elements : List Text) →+        let status =+              List/fold+                Text+                elements+                Status+                ( λ(element : Text) →+                  λ(status : Status) →+                    merge+                      { Empty = Status.NonEmpty element+                      , NonEmpty =+                          λ(result : Text) →+                            Status.NonEmpty (element ++ separator ++ result)+                      }+                      status+                )+                Status.Empty++        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 = assert : concatSep ", " [ "ABC", "DEF", "GHI" ] ≡ "ABC, DEF, GHI"++let example1 = assert : concatSep ", " ([] : List Text) ≡ ""++in  concatSep
+ tests/format/dottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x = { y = { a = { b = 1 }, c = { d = 2 } } } }
+ tests/format/dottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x.y = { a.b = 1, c.d = 2 } }
+ tests/format/dottedFieldsCommentsA.dhall view
@@ -0,0 +1,17 @@+{   {- A -}+    a+    -- B+  . -- C+    b+  . c+    {- D -}+  . d =+      -- E+      x+,   {- F -}+    e+    {- G -}+  . f =+      {- H -}+      { g = y }+}
+ tests/format/dottedFieldsCommentsB.dhall view
@@ -0,0 +1,17 @@+{   {- A -}+    a+    -- B+  . -- C+    b+  . c+    {- D -}+  . d+  = -- E+    x+,   {- F -}+    e+    {- G -}+  . f+  = {- H -}+    { g = y }+}
+ tests/format/doubleRoundA.dhall view
@@ -0,0 +1,41 @@+[ 1.0000000000000000+, 1.0000000000000001+, 1.0000000000000002+, 1.0000000000000003+, 1.0000000000000004+, 1.0000000000000005+, 1.0000000000000006+, 1.0000000000000007+, 1.0000000000000008+, 1.0000000000000009++, 1.0000000000000000e64+, 1.0000000000000001e64+, 1.0000000000000002e64+, 1.0000000000000003e64+, 1.0000000000000004e64+, 1.0000000000000005e64+, 1.0000000000000006e64+, 1.0000000000000007e64+, 1.0000000000000008e64+, 1.0000000000000009e64++, 1.0000000000000000e100+, 1.0000000000000001e100+, 1.0000000000000002e100+, 1.0000000000000003e100+, 1.0000000000000004e100+, 1.0000000000000005e100+, 1.0000000000000006e100+, 1.0000000000000007e100+, 1.0000000000000008e100+, 1.0000000000000009e100++, 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0++, -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0+]
+ tests/format/doubleRoundB.dhall view
@@ -0,0 +1,37 @@+[ 1.0000000000000000+, 1.0000000000000001+, 1.0000000000000002+, 1.0000000000000003+, 1.0000000000000004+, 1.0000000000000005+, 1.0000000000000006+, 1.0000000000000007+, 1.0000000000000008+, 1.0000000000000009+, 1.0000000000000000e64+, 1.0000000000000001e64+, 1.0000000000000002e64+, 1.0000000000000003e64+, 1.0000000000000004e64+, 1.0000000000000005e64+, 1.0000000000000006e64+, 1.0000000000000007e64+, 1.0000000000000008e64+, 1.0000000000000009e64+, 1.0000000000000000e100+, 1.0000000000000001e100+, 1.0000000000000002e100+, 1.0000000000000003e100+, 1.0000000000000004e100+, 1.0000000000000005e100+, 1.0000000000000006e100+, 1.0000000000000007e100+, 1.0000000000000008e100+, 1.0000000000000009e100+, 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0+, -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0+]
+ tests/format/duplicatesA.dhall view
@@ -0,0 +1,4 @@+{ {- Comments around duplicate fields are not preserved -} foo.bar = 1+, foo = { baz = {- Comments within values are still preserved-} 2 }+, foo = qux+}
+ tests/format/duplicatesB.dhall view
@@ -0,0 +1,6 @@+{ foo.bar = 1+, foo.baz+  = {- Comments within values are still preserved-}+    2+, foo = qux+}
tests/format/emptyRecordB.dhall view
+ tests/format/envVarsA.dhall view
@@ -0,0 +1,1 @@+[ env:x, env:"1", env:" ", env:"\\", env:"." ]
+ tests/format/envVarsB.dhall view
@@ -0,0 +1,1 @@+[ env:x, env:"1", env:" ", env:"\\", env:"." ]
tests/format/escapeNumericLabelB.dhall view
tests/format/escapeSingleQuotedOpenInterpolationB.dhall view
tests/format/fieldOrderB.dhall view
+ tests/format/functionLikeA.dhall view
@@ -0,0 +1,6 @@+{ example0 = merge a b + merge a b+, example1 = (merge a b : T) + (merge a b : T)+, example2 = toMap a + toMap a+, example3 = (toMap a b : T) + (toMap a b : T)+, example4 = Some a + Some a+}
+ tests/format/functionLikeB.dhall view
@@ -0,0 +1,6 @@+{ example0 = merge a b + merge a b+, example1 = (merge a b : T) + (merge a b : T)+, example2 = toMap a + toMap a+, example3 = (toMap a b : T) + (toMap a b : T)+, example4 = Some a + Some a+}
+ tests/format/headerA.dhall view
@@ -0,0 +1,4 @@+   +{- bla -} +  +True
+ tests/format/headerB.dhall view
@@ -0,0 +1,2 @@+{- bla -}+True
+ tests/format/headerNoNewlineA.dhall view
@@ -0,0 +1,1 @@+{- -}0
+ tests/format/headerNoNewlineB.dhall view
@@ -0,0 +1,2 @@+{- -}+0
+ tests/format/ifThenElseA.dhall view
@@ -0,0 +1,2 @@+if True then if True then if True then 1 else 2 else if True then 3 else 4+else if True then if True then 5 else 6 else if True then 7 else 8
+ tests/format/ifThenElseB.dhall view
@@ -0,0 +1,7 @@+if    True+then  if True then if True then 1 else 2 else if True then 3 else 4+else  if True+then  if True then 5 else 6+else  if True+then  7+else  8
+ tests/format/importAccessA.dhall view
@@ -0,0 +1,1 @@+(./testImport).hello
+ tests/format/importAccessB.dhall view
@@ -0,0 +1,1 @@+(./testImport).hello
+ tests/format/importAltPrecedenceA.dhall view
@@ -0,0 +1,1 @@+a ? b || c
+ tests/format/importAltPrecedenceB.dhall view
@@ -0,0 +1,1 @@+a ? b || c
+ tests/format/importLines2A.dhall view
@@ -0,0 +1,2 @@+let _ = ./emptyRecordA.dhall+in let _ = ./emptyRecordA.dhall in 123
+ tests/format/importLines2B.dhall view
@@ -0,0 +1,1 @@+let _ = ./emptyRecordA.dhall in let _ = ./emptyRecordA.dhall in 123
+ tests/format/importLinesA.dhall view
@@ -0,0 +1,7 @@+let _ = ./emptyRecordA.dhall+let _ = ./emptyRecordA.dhall+let _ = ./emptyRecordA.dhall+let _ = ./emptyRecordA.dhall+let _ = ./emptyRecordA.dhall+let _ = ./emptyRecordA.dhall+in  123
+ tests/format/importLinesB.dhall view
@@ -0,0 +1,13 @@+let _ = ./emptyRecordA.dhall++let _ = ./emptyRecordA.dhall++let _ = ./emptyRecordA.dhall++let _ = ./emptyRecordA.dhall++let _ = ./emptyRecordA.dhall++let _ = ./emptyRecordA.dhall++in  123
+ tests/format/importSuffixA.dhall view
@@ -0,0 +1,1 @@+let a = env:AAA      as Text in a
+ tests/format/importSuffixB.dhall view
@@ -0,0 +1,1 @@+let a = env:AAA as Text in a
+ tests/format/innerMultilineA.dhall view
@@ -0,0 +1,11 @@+{ inner =+  ''++  one++  two++  three++  ''+}
+ tests/format/innerMultilineB.dhall view
@@ -0,0 +1,11 @@+{ inner =+    ''++    one++    two++    three++    ''+}
+ tests/format/interpolation0A.dhall view
@@ -0,0 +1,1 @@+"foo\n${a} bar"
+ tests/format/interpolation0B.dhall view
@@ -0,0 +1,3 @@+''+foo+${a} bar''
+ tests/format/ipfsA.dhall view
@@ -0,0 +1,163 @@+let name = "ipfs"++let labels =+      { `app.kubernetes.io/name` = name+      , `app.kubernetes.io/instance` = "wintering-rodent"+      , `app.kubernetes.io/version` = "0.4.0"+      , `app.kubernetes.io/managed-by` = "dhall"+      }++let matchLabels =+      labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` }++let k8s =+      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd++let serviceName = "ipfs"++let apiPort = k8s.IntOrString.Int 5001++let gatewayPort = k8s.IntOrString.Int 8080++let toRule =+        λ ( args+          : { host : Text+            , path : Text+            , serviceName : Text+            , servicePort : k8s.IntOrString+            }+          )+      → k8s.IngressRule::{+        , host = Some args.host+        , http =+            Some+              k8s.HTTPIngressRuleValue::{+              , paths =+                  [ k8s.HTTPIngressPath::{+                    , path = Some args.path+                    , backend =+                        k8s.IngressBackend::args.{ serviceName, servicePort }+                    }+                  ]+              }+        }++in  [ k8s.Resource.Ingress+        k8s.Ingress::{+        , metadata =+            k8s.ObjectMeta::{ labels = toMap labels, name = "${name}-api" }+        , spec =+            Some+              k8s.IngressSpec::{+              , rules =+                  [ toRule+                      { host = "localhost"+                      , path = "/"+                      , serviceName = serviceName+                      , servicePort = gatewayPort+                      }+                  , toRule+                      { host = "localhost"+                      , path = "/"+                      , serviceName = serviceName+                      , servicePort = apiPort+                      }+                  ]+              }+        }+    , k8s.Resource.Service+        k8s.Service::{+        , metadata =+            k8s.ObjectMeta::{ name = serviceName, labels = toMap labels }+        , spec =+            Some+              k8s.ServiceSpec::{+              , ports =+                  [ k8s.ServicePort::{+                    , port = 5001+                    , targetPort = Some apiPort+                    , name = Some "api"+                    }+                  , k8s.ServicePort::{+                    , port = 8080+                    , targetPort = Some gatewayPort+                    , name = Some "api"+                    }+                  ]+              , selector = toMap matchLabels+              }+        }+    , k8s.Resource.StatefulSet+        k8s.StatefulSet::{+        , metadata = k8s.ObjectMeta::{ name = name, labels = toMap labels }+        , spec =+            Some+              k8s.StatefulSetSpec::{+              , serviceName = serviceName+              , selector =+                  k8s.LabelSelector::{ matchLabels = toMap matchLabels }+              , template =+                  k8s.PodTemplateSpec::{+                  , metadata =+                      k8s.ObjectMeta::{ name = name, labels = toMap labels }+                  , spec =+                      Some+                        k8s.PodSpec::{+                        , securityContext =+                            Some+                              k8s.PodSecurityContext::{+                              , runAsUser = Some 1000+                              , runAsGroup = Some 1000+                              , fsGroup = Some 1000+                              }+                        , containers =+                            [ k8s.Container::{+                              , name = name+                              , image = Some "ipfs/go-ipfs:v0.4.22"+                              , livenessProbe =+                                  k8s.Probe::{+                                  , httpGet =+                                      Some+                                        k8s.HTTPGetAction::{+                                        , path =+                                            Some "/debug/metrics/prometheus"+                                        , port = k8s.IntOrString.String "api"+                                        }+                                  , initialDelaySeconds = Some 15+                                  , periodSeconds = Some 3+                                  }+                              , readinessProbe =+                                  k8s.Probe::{+                                  , httpGet =+                                      Some+                                        k8s.HTTPGetAction::{+                                        , path =+                                            Some "/debug/metrics/prometheus"+                                        , port = k8s.IntOrString.String "api"+                                        }+                                  , initialDelaySeconds = Some 15+                                  , periodSeconds = Some 3+                                  }+                              , ports =+                                  [ k8s.ContainerPort::{+                                    , containerPort = 5001+                                    , name = Some "api"+                                    }+                                  , k8s.ContainerPort::{+                                    , containerPort = 8080+                                    , name = Some "gateway"+                                    }+                                  ]+                              , volumeMounts =+                                  [ k8s.VolumeMount::{+                                    , name = "ipfs-storage"+                                    , mountPath = "/data/ipfs"+                                    }+                                  ]+                              }+                            ]+                        }+                  }+              }+        }+    ]
+ tests/format/ipfsB.dhall view
@@ -0,0 +1,144 @@+let name = "ipfs"++let labels =+      { `app.kubernetes.io/name` = name+      , `app.kubernetes.io/instance` = "wintering-rodent"+      , `app.kubernetes.io/version` = "0.4.0"+      , `app.kubernetes.io/managed-by` = "dhall"+      }++let matchLabels =+      labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` }++let k8s =+      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall+        sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd++let serviceName = "ipfs"++let apiPort = k8s.IntOrString.Int 5001++let gatewayPort = k8s.IntOrString.Int 8080++let toRule =+      λ ( args+        : { host : Text+          , path : Text+          , serviceName : Text+          , servicePort : k8s.IntOrString+          }+        ) →+        k8s.IngressRule::{+        , host = Some args.host+        , http = Some k8s.HTTPIngressRuleValue::{+          , paths =+            [ k8s.HTTPIngressPath::{+              , path = Some args.path+              , backend = k8s.IngressBackend::args.{ serviceName, servicePort }+              }+            ]+          }+        }++in  [ k8s.Resource.Ingress+        k8s.Ingress::{+        , metadata = k8s.ObjectMeta::{+          , labels = toMap labels+          , name = "${name}-api"+          }+        , spec = Some k8s.IngressSpec::{+          , rules =+            [ toRule+                { host = "localhost"+                , path = "/"+                , serviceName+                , servicePort = gatewayPort+                }+            , toRule+                { host = "localhost"+                , path = "/"+                , serviceName+                , servicePort = apiPort+                }+            ]+          }+        }+    , k8s.Resource.Service+        k8s.Service::{+        , metadata = k8s.ObjectMeta::{+          , name = serviceName+          , labels = toMap labels+          }+        , spec = Some k8s.ServiceSpec::{+          , ports =+            [ k8s.ServicePort::{+              , port = 5001+              , targetPort = Some apiPort+              , name = Some "api"+              }+            , k8s.ServicePort::{+              , port = 8080+              , targetPort = Some gatewayPort+              , name = Some "api"+              }+            ]+          , selector = toMap matchLabels+          }+        }+    , k8s.Resource.StatefulSet+        k8s.StatefulSet::{+        , metadata = k8s.ObjectMeta::{ name, labels = toMap labels }+        , spec = Some k8s.StatefulSetSpec::{+          , serviceName+          , selector = k8s.LabelSelector::{ matchLabels = toMap matchLabels }+          , template = k8s.PodTemplateSpec::{+            , metadata = k8s.ObjectMeta::{ name, labels = toMap labels }+            , spec = Some k8s.PodSpec::{+              , securityContext = Some k8s.PodSecurityContext::{+                , runAsUser = Some 1000+                , runAsGroup = Some 1000+                , fsGroup = Some 1000+                }+              , containers =+                [ k8s.Container::{+                  , name+                  , image = Some "ipfs/go-ipfs:v0.4.22"+                  , livenessProbe = k8s.Probe::{+                    , httpGet = Some k8s.HTTPGetAction::{+                      , path = Some "/debug/metrics/prometheus"+                      , port = k8s.IntOrString.String "api"+                      }+                    , initialDelaySeconds = Some 15+                    , periodSeconds = Some 3+                    }+                  , readinessProbe = k8s.Probe::{+                    , httpGet = Some k8s.HTTPGetAction::{+                      , path = Some "/debug/metrics/prometheus"+                      , port = k8s.IntOrString.String "api"+                      }+                    , initialDelaySeconds = Some 15+                    , periodSeconds = Some 3+                    }+                  , ports =+                    [ k8s.ContainerPort::{+                      , containerPort = 5001+                      , name = Some "api"+                      }+                    , k8s.ContainerPort::{+                      , containerPort = 8080+                      , name = Some "gateway"+                      }+                    ]+                  , volumeMounts =+                    [ k8s.VolumeMount::{+                      , name = "ipfs-storage"+                      , mountPath = "/data/ipfs"+                      }+                    ]+                  }+                ]+              }+            }+          }+        }+    ]
+ tests/format/issue1301A.dhall view
@@ -0,0 +1,5 @@+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ tests/format/issue1301B.dhall view
@@ -0,0 +1,5 @@+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ tests/format/issue1400-1A.dhall view
@@ -0,0 +1,14 @@+{ conversation =+    [ { author = "robert", content = xs }+    , { author = "robert", content = xs }+    , { author =+          "bob"+      , content =+          [ text+              ''+              any line going past the 80 characters boundary     (e.g. this one is 82)+              ''+          ]+      }+    ]+}
+ tests/format/issue1400-1B.dhall view
@@ -0,0 +1,13 @@+{ conversation =+  [ { author = "robert", content = xs }+  , { author = "robert", content = xs }+  , { author = "bob"+    , content =+      [ text+          ''+          any line going past the 80 characters boundary     (e.g. this one is 82)+          ''+      ]+    }+  ]+}
+ tests/format/issue1400-2A.dhall view
@@ -0,0 +1,14 @@+let Tagged+    : Type → Type+    =   λ ( a+          : Type+          )+      → { field :+            Text+        , nesting :+              ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+            ? ./Nesting+        , contents : a+        }++in  Tagged
+ tests/format/issue1400-2B.dhall view
@@ -0,0 +1,12 @@+let Tagged+    : Type → Type+    = λ(a : Type) →+        { field : Text+        , nesting :+              ./Nesting+                sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+            ? ./Nesting+        , contents : a+        }++in  Tagged
+ tests/format/issue1413A.dhall view
@@ -0,0 +1,6 @@+let foo =++    {- test -}+      "hello"++in  foo
+ tests/format/issue1413B.dhall view
@@ -0,0 +1,6 @@+let foo =++    {- test -}+      "hello"++in  foo
+ tests/format/issue1545-1A.dhall view
@@ -0,0 +1,1 @@+"\n\tx"
+ tests/format/issue1545-1B.dhall view
@@ -0,0 +1,3 @@+''++${"\t"}x''
+ tests/format/issue1545-2A.dhall view
@@ -0,0 +1,1 @@+"\n x"
+ tests/format/issue1545-2B.dhall view
@@ -0,0 +1,3 @@+''++${" "}x''
+ tests/format/issue1687A.dhall view
@@ -0,0 +1,7 @@+let {- foo++    bar -}+    x =+      1++in  x
+ tests/format/issue1687B.dhall view
@@ -0,0 +1,7 @@+let {- foo++    bar -}+    x =+      1++in  x
+ tests/format/issue1805KeywordRecordFieldShouldBeQuotedA.dhall view
@@ -0,0 +1,1 @@+{ `if` = True }
+ tests/format/issue1805KeywordRecordFieldShouldBeQuotedB.dhall view
@@ -0,0 +1,1 @@+{ `if` = True }
+ tests/format/issue1805SomeQuotedInLetButNotInRecordA.dhall view
@@ -0,0 +1,1 @@+let `Some` = 3 in { `if` = True, Some = 333 }
+ tests/format/issue1805SomeQuotedInLetButNotInRecordB.dhall view
@@ -0,0 +1,1 @@+let `Some` = 3 in { `if` = True, Some = 333 }
+ tests/format/issue183A.dhall view
@@ -0,0 +1,11 @@+    let foo = 1++in    λ(bar : Integer)+    →     let exposePort =+                  λ(portSpec : { ext : Integer, int : Integer })+                → Integer/show portSpec.ext ++ ":" ++ Integer/show portSpec.int+      +      in  let exposeSamePort =+                λ(port : Integer) → exposePort { ext = port, int = port }+      +      in  { blah = bar }
+ tests/format/issue183B.dhall view
@@ -0,0 +1,11 @@+let foo = 1++in  λ(bar : Integer) →+      let exposePort =+            λ(portSpec : { ext : Integer, int : Integer }) →+              Integer/show portSpec.ext ++ ":" ++ Integer/show portSpec.int++      in  let exposeSamePort =+                λ(port : Integer) → exposePort { ext = port, int = port }++          in  { blah = bar }
+ tests/format/issue2047A.dhall view
@@ -0,0 +1,4 @@+let x = ({ foo = 1 } ∧ { bar = 2 })+  with bar = 3 +  with foo = 4 +in x
+ tests/format/issue2047B.dhall view
@@ -0,0 +1,1 @@+let x = ({ foo = 1 } ∧ { bar = 2 }) with bar = 3 with foo = 4 in x
+ tests/format/issue2078A.dhall view
@@ -0,0 +1,1 @@+"'\${x}'\n"
+ tests/format/issue2078B.dhall view
@@ -0,0 +1,3 @@+''+${"'"}''${x}'+''
+ tests/format/issue2601A.dhall view
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+    : T+    = T.`Some`++let x+    : T+    = T.Type++in  True
+ tests/format/issue2601B.dhall view
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+    : T+    = T.`Some`++let x+    : T+    = T.Type++in  True
tests/format/largeExponentA.dhall view
@@ -1,1 +1,1 @@-[ 1.0, 1e1000000000, 1e-1000000000 ]+[ 1.0, 1e100, 1e-100 ]
tests/format/largeExponentB.dhall view
@@ -1,1 +1,1 @@-[ 1.0, 1.0e1000000000, 1.0e-1000000000 ]+[ 1.0, 1e100, 1e-100 ]
+ tests/format/largeRecordA.dhall view
@@ -0,0 +1,142 @@+-- This file was tested using console NetHack version 3.6.1+--+-- To exercise all options documented in https://nethackwiki.com/wiki/Options+-- see `./unvalidated.dhall`+let types = ./../types.dhall++let defaults = ./../defaults.dhall++in    defaults.Config+    ⫽ { AUTOCOMPLETE =+          [ { enable = True, value = "zap" }+          , { enable = False, value = "annotate" }+          ]+      , acoustics = Some True+      , align = Some { enable = True, value = types.Alignment.chaotic }+      , autodescribe = Some False+      , autodig = Some False+      , AUTOPICKUP_EXCEPTION =+          [ { pickup = False, name = "chest" }+          , { pickup = True, name = "dagger" }+          ]+      , BIND =+          [ { keybinding = "!", command = "loot" }+          , { keybinding = "^v", command = "untrap" }+          , { keybinding = "M-x", command = "terrain" }+          ]+      , catname = Some "Mirri"+      , checkpoint = Some True+      , checkspace = Some True+      , clicklook = Some False+      , cmdassist = Some True+      , confirm = Some True+      , dark_room = Some False+      , disclose =+          Some+          (   defaults.Disclose+            ⫽ { inventory = Some { prompt = True, default = True }+              , attributes = Some { prompt = True, default = False }+              , monsters_killed = Some { prompt = False, default = True }+              , monsters_genocided = Some { prompt = False, default = False }+              , conduct = Some { prompt = False, default = False }+              , dungeon_overview = Some { prompt = False, default = False }+              }+          )+      , dogname = Some "Cujo"+      , extmenu = Some False+      , fixinv = Some True+      , force_invmenu = Some False+      , fruit = Some "slime mold"+      , gender = Some types.Gender.female+      , goldX = Some False+      , help = Some True+      , hilite_pet = Some False+      , hilite_pile = Some False+      , hilite_status =+            defaults.HiliteStatus+          ⫽ { gold =+                [ { color = types.Color.yellow+                  , trigger = Some types.Numeric.always+                  , attributes = None types.Attributes+                  }+                ]+            }+      , hitpointbar = Some True+      , horsename = Some "Erhir"+      , ignintr = Some False+      , implicit_uncursed = Some True+      , legacy = Some True+      , lit_corridor = Some False+      , lootabc = Some False+      , mail = Some True+      , mention_walls = Some False+      , menucolors =+          [ { regex = "blessed"+            , color = Some types.Color.cyan+            , attributes = defaults.Attributes ⫽ { bold = Some True }+            }+          ]+      , menustyle = Some types.MenuStyle.traditional+      , menu_deselect_all = Some "-"+      , menu_deselect_page = Some "\\"+      , menu_first_page = Some "^"+      , menu_headings = Some types.MenuHeadings.bold+      , menu_invert_all = Some "@"+      , menu_invert_page = Some "~"+      , menu_last_page = Some "|"+      , menu_next_page = Some ">"+      , menu_objsyms = Some False+      , menu_previous_page = Some "<"+      , menu_search = Some ":"+      , menu_select_all = Some "."+      , menu_tab_sep = Some False+      , msg_window = Some types.MsgWindow.single+      , MSGTYPE = [ types.MsgType.hide "You swap places with .*" ]+      , name = Some "Kaeru"+      , news = Some True+      , nudist = Some False+      , null = Some False+      , number_pad = Some types.NumberPad.Letters+      , packorder = Some "\")[%?+!=/(*`0_"+      , paranoid_confirmation =+          defaults.ParanoidConfirmation ⫽ { pray = Some True }+      , pettype = Some types.PetType.cat+      , pickup_burden = Some types.PickupBurden.stressed+      , pickup_thrown = Some True+      , pickup_types = Some "?!/"+      , pile_limit = Some (types.PileLimit.limit 5)+      , playmode = Some types.PlayMode.normal+      , pushweapon = Some False+      , race = Some { enable = True, value = types.Race.elf }+      , rest_on_space = Some False+      , role = Some { enable = True, value = types.Role.wizard }+      , roguesymset = Some types.SymSet.RogueEpyx+      , runmode = Some types.RunMode.walk+      , safe_pet = Some True+      , sanity_check = Some False+      , scores = { own = Some True, around = Some 2, top = Some 10 }+      , showexp = Some False+      , showrace = Some False+      , showscore = Some False+      , silent = Some True+      , sortloot = Some types.SortLoot.none+      , sortpack = Some True+      , sparkle = Some True+      , standout = Some False+      , status_updates = Some True+      , statushilites = Some 10+      , suppress_alert = Some "3.3.1"+      , symset = Some types.SymSet.DECgraphics+      , time = Some False+      , timed_delay = Some True+      , tombstone = Some True+      , toptenwin = Some False+      , travel = Some True+      , verbose = Some True+      , whatis_coord = Some types.WhatisCoord.none+      , whatis_filter = Some types.WhatisFilter.no_filtering+      , whatis_menu = Some False+      , whatis_moveskip = Some False+      , windowtype = Some "tty"+      , wizkit = Some "wizkit.txt"+      }
+ tests/format/largeRecordB.dhall view
@@ -0,0 +1,141 @@+-- This file was tested using console NetHack version 3.6.1+--+-- To exercise all options documented in https://nethackwiki.com/wiki/Options+-- see `./unvalidated.dhall`+let types = ./../types.dhall++let defaults = ./../defaults.dhall++in    defaults.Config+    ⫽ { AUTOCOMPLETE =+        [ { enable = True, value = "zap" }+        , { enable = False, value = "annotate" }+        ]+      , acoustics = Some True+      , align = Some { enable = True, value = types.Alignment.chaotic }+      , autodescribe = Some False+      , autodig = Some False+      , AUTOPICKUP_EXCEPTION =+        [ { pickup = False, name = "chest" }+        , { pickup = True, name = "dagger" }+        ]+      , BIND =+        [ { keybinding = "!", command = "loot" }+        , { keybinding = "^v", command = "untrap" }+        , { keybinding = "M-x", command = "terrain" }+        ]+      , catname = Some "Mirri"+      , checkpoint = Some True+      , checkspace = Some True+      , clicklook = Some False+      , cmdassist = Some True+      , confirm = Some True+      , dark_room = Some False+      , disclose = Some+          (   defaults.Disclose+            ⫽ { inventory = Some { prompt = True, default = True }+              , attributes = Some { prompt = True, default = False }+              , monsters_killed = Some { prompt = False, default = True }+              , monsters_genocided = Some { prompt = False, default = False }+              , conduct = Some { prompt = False, default = False }+              , dungeon_overview = Some { prompt = False, default = False }+              }+          )+      , dogname = Some "Cujo"+      , extmenu = Some False+      , fixinv = Some True+      , force_invmenu = Some False+      , fruit = Some "slime mold"+      , gender = Some types.Gender.female+      , goldX = Some False+      , help = Some True+      , hilite_pet = Some False+      , hilite_pile = Some False+      , hilite_status =+            defaults.HiliteStatus+          ⫽ { gold =+              [ { color = types.Color.yellow+                , trigger = Some types.Numeric.always+                , attributes = None types.Attributes+                }+              ]+            }+      , hitpointbar = Some True+      , horsename = Some "Erhir"+      , ignintr = Some False+      , implicit_uncursed = Some True+      , legacy = Some True+      , lit_corridor = Some False+      , lootabc = Some False+      , mail = Some True+      , mention_walls = Some False+      , menucolors =+        [ { regex = "blessed"+          , color = Some types.Color.cyan+          , attributes = defaults.Attributes ⫽ { bold = Some True }+          }+        ]+      , menustyle = Some types.MenuStyle.traditional+      , menu_deselect_all = Some "-"+      , menu_deselect_page = Some "\\"+      , menu_first_page = Some "^"+      , menu_headings = Some types.MenuHeadings.bold+      , menu_invert_all = Some "@"+      , menu_invert_page = Some "~"+      , menu_last_page = Some "|"+      , menu_next_page = Some ">"+      , menu_objsyms = Some False+      , menu_previous_page = Some "<"+      , menu_search = Some ":"+      , menu_select_all = Some "."+      , menu_tab_sep = Some False+      , msg_window = Some types.MsgWindow.single+      , MSGTYPE = [ types.MsgType.hide "You swap places with .*" ]+      , name = Some "Kaeru"+      , news = Some True+      , nudist = Some False+      , null = Some False+      , number_pad = Some types.NumberPad.Letters+      , packorder = Some "\")[%?+!=/(*`0_"+      , paranoid_confirmation =+          defaults.ParanoidConfirmation ⫽ { pray = Some True }+      , pettype = Some types.PetType.cat+      , pickup_burden = Some types.PickupBurden.stressed+      , pickup_thrown = Some True+      , pickup_types = Some "?!/"+      , pile_limit = Some (types.PileLimit.limit 5)+      , playmode = Some types.PlayMode.normal+      , pushweapon = Some False+      , race = Some { enable = True, value = types.Race.elf }+      , rest_on_space = Some False+      , role = Some { enable = True, value = types.Role.wizard }+      , roguesymset = Some types.SymSet.RogueEpyx+      , runmode = Some types.RunMode.walk+      , safe_pet = Some True+      , sanity_check = Some False+      , scores = { own = Some True, around = Some 2, top = Some 10 }+      , showexp = Some False+      , showrace = Some False+      , showscore = Some False+      , silent = Some True+      , sortloot = Some types.SortLoot.none+      , sortpack = Some True+      , sparkle = Some True+      , standout = Some False+      , status_updates = Some True+      , statushilites = Some 10+      , suppress_alert = Some "3.3.1"+      , symset = Some types.SymSet.DECgraphics+      , time = Some False+      , timed_delay = Some True+      , tombstone = Some True+      , toptenwin = Some False+      , travel = Some True+      , verbose = Some True+      , whatis_coord = Some types.WhatisCoord.none+      , whatis_filter = Some types.WhatisFilter.no_filtering+      , whatis_menu = Some False+      , whatis_moveskip = Some False+      , windowtype = Some "tty"+      , wizkit = Some "wizkit.txt"+      }
+ tests/format/letA.dhall view
@@ -0,0 +1,1 @@+let x = "Lorem ipsum" let y = "Lorem ipsum" in let z = "Lorem ipsum" in x ++ y ++ z
+ tests/format/letAnnotatedShortA.dhall view
@@ -0,0 +1,1 @@+let empty : ∀(a : Type) → List a = λ(a : Type) → [] : List a in empty
+ tests/format/letAnnotatedShortB.dhall view
@@ -0,0 +1,5 @@+let empty+    : ∀(a : Type) → List a+    = λ(a : Type) → [] : List a++in  empty
+ tests/format/letB.dhall view
@@ -0,0 +1,5 @@+let x = "Lorem ipsum"++let y = "Lorem ipsum"++in  let z = "Lorem ipsum" in x ++ y ++ z
+ tests/format/letCommentsA.dhall view
@@ -0,0 +1,7 @@+let {- Example documentation for a let binding+       that spans more than one line+    -}+    x {- we can interject things here -} = -- Make sure one-line comments work+        1++in  x
+ tests/format/letCommentsB.dhall view
@@ -0,0 +1,8 @@+let {- Example documentation for a let binding+       that spans more than one line+    -}+    x {- we can interject things here -} =+    -- Make sure one-line comments work+      1++in  x
+ tests/format/letLineCommentsAfterVariableA.dhall view
@@ -0,0 +1,10 @@+let x -- xxxxxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx+    : Natural+    = 0++let y -- yyyyyyyyyy yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyy+      -- yyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyy+    : Natural+    = 1++in x + y
+ tests/format/letLineCommentsAfterVariableB.dhall view
@@ -0,0 +1,12 @@+let x+    -- xxxxxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx+    : Natural+    = 0++let y+    -- yyyyyyyyyy yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyy+    -- yyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyy+    : Natural+    = 1++in  x + y
+ tests/format/letLongCommentsA.dhall view
@@ -0,0 +1,3 @@+let x {- foo                                        -} : {- bar                                           -} Bool {- baz                           -} = {- bla                      -} True++in  x
+ tests/format/letLongCommentsB.dhall view
@@ -0,0 +1,5 @@+let x+    {- foo                                        -} : {- bar                                           -} Bool+    = {- bla                      -} True++in  x
+ tests/format/letNewlineCommentsA.dhall view
@@ -0,0 +1,7 @@+let x = 1+in+let {- aaaaaaaaaaaaaaaaaaa+    -} y : {- bbbbbbbbbbbbbbbbbbbbb+    -} Natural {- cccccccccccccc+    -} = {- ddddddddddddddddd -} 2+    in x
+ tests/format/letNewlineCommentsB.dhall view
@@ -0,0 +1,9 @@+let x = 1++in  let {- aaaaaaaaaaaaaaaaaaa+        -} y+        : {- bbbbbbbbbbbbbbbbbbbbb+          -} Natural+        = {- ddddddddddddddddd -} 2++    in  x
+ tests/format/letShortCommentsA.dhall view
@@ -0,0 +1,3 @@+let x = True+let {- 0 -} y {- 1 -} : {- 2 -} Bool = {- 3-} False+in x
+ tests/format/letShortCommentsB.dhall view
@@ -0,0 +1,7 @@+let x = True++let {- 0 -} y+    {- 1 -} : {- 2 -} Bool+    = {- 3-} False++in  x
+ tests/format/multilineArgumentA.dhall view
@@ -0,0 +1,1 @@+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff xxxxxxxxxxxxxxxx "\n"
+ tests/format/multilineArgumentB.dhall view
@@ -0,0 +1,3 @@+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+  xxxxxxxxxxxxxxxx+  "\n"
tests/format/multilineB.dhall view
+ tests/format/multilineTrailingSingleQuoteA.dhall view
@@ -0,0 +1,1 @@+"\n'"
+ tests/format/multilineTrailingSingleQuoteB.dhall view
@@ -0,0 +1,3 @@+''++${"'"}''
+ tests/format/multilineTrailingWhitespaceA.dhall view
@@ -0,0 +1,1 @@+{ x = "  \n\nfoo  \n" }
+ tests/format/multilineTrailingWhitespaceB.dhall view
@@ -0,0 +1,7 @@+{ x =+    ''+      ++    foo  +    ''+}
+ tests/format/negativeTimeZoneA.dhall view
@@ -0,0 +1,1 @@+04:00:00-04:00
+ tests/format/negativeTimeZoneB.dhall view
@@ -0,0 +1,1 @@+04:00:00-04:00
+ tests/format/nestedAnnotationA.dhall view
@@ -0,0 +1,1 @@+([] : a) : b
+ tests/format/nestedAnnotationB.dhall view
@@ -0,0 +1,1 @@+([] : a) : b
+ tests/format/numericLiteralsA.dhall view
@@ -0,0 +1,1 @@+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
+ tests/format/numericLiteralsB.dhall view
@@ -0,0 +1,1 @@+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
+ tests/format/parentA.dhall view
@@ -0,0 +1,1 @@+../a
+ tests/format/parentB.dhall view
@@ -0,0 +1,1 @@+../a
+ tests/format/parenthesizeUsingA.dhall view
@@ -0,0 +1,6 @@+-- https://github.com/dhall-lang/dhall-haskell/issues/2273+let MyPackage =+      https://server.test/package.dhall using (./headers.dhall)+        sha256:03a6e298ff140d430cea8b387fad886ce9f5bee24622c7d1102115cc08ed9cf8++in  MyPackage
+ tests/format/parenthesizeUsingB.dhall view
@@ -0,0 +1,6 @@+-- https://github.com/dhall-lang/dhall-haskell/issues/2273+let MyPackage =+      https://server.test/package.dhall using (./headers.dhall)+        sha256:03a6e298ff140d430cea8b387fad886ce9f5bee24622c7d1102115cc08ed9cf8++in  MyPackage
+ tests/format/preserveShebangA.dhall view
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"Hello, world!"
+ tests/format/preserveShebangB.dhall view
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"Hello, world!"
+ tests/format/projectionOrderA.dhall view
@@ -0,0 +1,1 @@+e.{ foo, bar, baz }
+ tests/format/projectionOrderB.dhall view
@@ -0,0 +1,1 @@+e.{ foo, bar, baz }
+ tests/format/punA.dhall view
@@ -0,0 +1,1 @@+{ x = x, y = 1, z = z }
+ tests/format/punB.dhall view
@@ -0,0 +1,1 @@+{ x, y = 1, z }
+ tests/format/punCommentsA.dhall view
@@ -0,0 +1,7 @@+{ {- A -}+  x+  {- B -}+, y =+    {- C -}+    y+}
+ tests/format/punCommentsB.dhall view
@@ -0,0 +1,7 @@+{ {- A -}+  x+  {- B -}+, y =+    {- C -}+    y+}
+ tests/format/recordCompletionA.dhall view
@@ -0,0 +1,26 @@+{ field0 =+T::{+, a = 1+, b = 1+, c = 1+, d = 1+, e = 1+, f = 1+, g = 1+, h = 1+, i = 1+, j = 1+, k = 1+, l = 1+, m = 1+, n = 1+, o = 1+, p = 1+, q = 1+, r = 1+, s = 1+, t = 1+}+, field1 = T::{ a = 1 }+, field2 = T::{ a = a }+}
+ tests/format/recordCompletionB.dhall view
@@ -0,0 +1,25 @@+{ field0 = T::{+  , a = 1+  , b = 1+  , c = 1+  , d = 1+  , e = 1+  , f = 1+  , g = 1+  , h = 1+  , i = 1+  , j = 1+  , k = 1+  , l = 1+  , m = 1+  , n = 1+  , o = 1+  , p = 1+  , q = 1+  , r = 1+  , s = 1+  , t = 1+  }+, field1 = T::{ a = 1 }+, field2 = T::{ a }+}
+ tests/format/recordLitComments0A.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  x+  {- B -}+  = {- C -}+    T+}
+ tests/format/recordLitComments0B.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  x+  {- B -}+  = {- C -}+    T+}
+ tests/format/recordLitComments1A.dhall view
@@ -0,0 +1,4 @@+{+--| a comment for y+y = 42+}
+ tests/format/recordLitComments1B.dhall view
@@ -0,0 +1,3 @@+{ --| a comment for y+  y = 42+}
+ tests/format/recordLitMultilineBlockCommentsA.dhall view
@@ -0,0 +1,9 @@+{ {- A+  A -}+  x+  {- B+  B -}+  = {- C+    C -}+    y+}
+ tests/format/recordLitMultilineBlockCommentsB.dhall view
@@ -0,0 +1,9 @@+{ {- A+  A -}+  x+  {- B+  B -}+  = {- C+    C -}+    y+}
+ tests/format/recordTypeCommentsA.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  a+  {- B -}+  : {- C -}+    A+}
+ tests/format/recordTypeCommentsB.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  a+  {- B -}+  : {- C -}+    A+}
+ tests/format/sha256PrintingA.dhall view
@@ -0,0 +1,4 @@+let replicate =+      https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c++in  replicate 5
+ tests/format/sha256PrintingB.dhall view
@@ -0,0 +1,5 @@+let replicate =+      https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate+        sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c++in  replicate 5
+ tests/format/significantLeadingSpacesA.dhall view
@@ -0,0 +1,1 @@+"  x\n\n  y\n "
+ tests/format/significantLeadingSpacesB.dhall view
@@ -0,0 +1,5 @@+''+${" "} x++${" "} y+${" "}''
+ tests/format/stringWithNullA.dhall view
@@ -0,0 +1,1 @@+"\u0000 \$ \\ \n ☺"
+ tests/format/stringWithNullB.dhall view
@@ -0,0 +1,3 @@+''+${"\u0000"} $ \ + ☺''
+ tests/format/textLitNewlinesOnlyA.dhall view
@@ -0,0 +1,1 @@+"\n\n"
+ tests/format/textLitNewlinesOnlyB.dhall view
@@ -0,0 +1,1 @@+"\n\n"
+ tests/format/timePrecisionA.dhall view
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
+ tests/format/timePrecisionB.dhall view
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
+ tests/format/unicodeA.dhall view
@@ -0,0 +1,16 @@+  λ(isActive : Bool)+→   { barLeftEnd =+        Some "┨"+    , barRightEnd =+        Some "┠"+    , separator =+        Some "┃"+    , alignment =+          < ToTheLeft | ToTheRight | Centered >.ToTheLeft+        : ./Alignment.dhall+    , barWidth =+        None Natural+    , barSegments =+        [ "index", "command", "path", "title" ]+    }+  : ./Bar.dhall
+ tests/format/unicodeB.dhall view
@@ -0,0 +1,10 @@+λ(isActive : Bool) →+    { barLeftEnd = Some "┨"+    , barRightEnd = Some "┠"+    , separator = Some "┃"+    , alignment =+        < ToTheLeft | ToTheRight | Centered >.ToTheLeft : ./Alignment.dhall+    , barWidth = None Natural+    , barSegments = [ "index", "command", "path", "title" ]+    }+  : ./Bar.dhall
+ tests/format/urlsA.dhall view
@@ -0,0 +1,7 @@+let unreserved = http://x/y%7ez++let uppercasehex = http://x/y%3bz++let reserved = http://x/y:z++in "done"
+ tests/format/urlsB.dhall view
@@ -0,0 +1,7 @@+let unreserved = http://x/y~z++let uppercasehex = http://x/y%3Bz++let reserved = http://x/y:z++in  "done"
+ tests/format/usingToMapA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/headers using (toMap { TOKEN = "AAAA" }) as Text
+ tests/format/usingToMapB.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/headers using (toMap { TOKEN = "AAAA" }) as Text
+ tests/format/withA.dhall view
@@ -0,0 +1,5 @@+r with a = Some { b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1, i = 1, j = 1, k = 1, l = 1 }+  with b = T::{ b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1, i = 1, j = 1, k = 1, l = 1 }+  with c = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]+  with d = 1+  with e = 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ tests/format/withB.dhall view
@@ -0,0 +1,58 @@+r+  with a = Some+    { b = 1+    , c = 1+    , d = 1+    , e = 1+    , f = 1+    , g = 1+    , h = 1+    , i = 1+    , j = 1+    , k = 1+    , l = 1+    }+  with b = T::{+    , b = 1+    , c = 1+    , d = 1+    , e = 1+    , f = 1+    , g = 1+    , h = 1+    , i = 1+    , j = 1+    , k = 1+    , l = 1+    }+  with c =+    [ 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    ]+  with d = 1+  with e =+      111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ tests/format/withPrecedenceA.dhall view
@@ -0,0 +1,5 @@+let Foo =+        Bar+        with default = (Bar.default ⫽ { bar = 0 })++in  Foo
+ tests/format/withPrecedenceB.dhall view
@@ -0,0 +1,1 @@+let Foo = Bar with default = Bar.default ⫽ { bar = 0 } in Foo
+ tests/format/withQuestionA.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
+ tests/format/withQuestionB.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
+ tests/freeze/cached/True.dhall view
@@ -0,0 +1,1 @@+True
+ tests/freeze/cached/cachedA.dhall view
@@ -0,0 +1,2 @@+  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/cachedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/idempotentA.dhall view
@@ -0,0 +1,5 @@+-- The purpose of this test is to verify that `dhall freeze --cached` is+-- idempotent and doesn't attempt to resolve the `missing` import+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/idempotentB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/incorrectHashA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
+ tests/freeze/cached/incorrectHashB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/protectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/cached/protectedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/unprotectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall
+ tests/freeze/cached/unprotectedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/secure/True.dhall view
@@ -0,0 +1,1 @@+True
+ tests/freeze/secure/cachedA.dhall view
@@ -0,0 +1,2 @@+  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/secure/cachedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/incorrectHashA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
+ tests/freeze/secure/incorrectHashB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/protectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/protectedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/unprotectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall
+ tests/freeze/secure/unprotectedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/lint/success/PreludeExtensionA.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/map
+ tests/lint/success/PreludeExtensionB.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/map.dhall
+ tests/lint/success/assertA.dhall view
@@ -0,0 +1,14 @@+let simpleAssert = assert : 1 + 1 ≡ 2++let assertIn1Lam = λ(n : Natural) → assert : Natural/subtract 0 n ≡ n++let assertIn2Lams =+        λ(m : Natural)+      → λ(n : Natural)+      → assert : Natural/subtract m m ≡ Natural/subtract n n++let assertInLetInLam = λ(m : Natural) → let n = m + 0 in assert : m ≡ n++let unusedNonAssert = "Foo"++in  {=}
+ tests/lint/success/assertB.dhall view
@@ -0,0 +1,12 @@+let simpleAssert = assert : 1 + 1 ≡ 2++let assertIn1Lam = λ(n : Natural) → assert : Natural/subtract 0 n ≡ n++let assertIn2Lams =+      λ(m : Natural) →+      λ(n : Natural) →+        assert : Natural/subtract m m ≡ Natural/subtract n n++let assertInLetInLam = λ(m : Natural) → let n = m + 0 in assert : m ≡ n++in  {=}
+ tests/lint/success/fixAssertA.dhall view
@@ -0,0 +1,5 @@+let example0 = 1 ≡ 1++let example1 = let x = 1 in x ≡ 1++in 1
+ tests/lint/success/fixAssertB.dhall view
@@ -0,0 +1,1 @@+let example0 = assert : 1 ≡ 1 let example1 = let x = 1 in assert : x ≡ 1 in 1
+ tests/lint/success/issue1586A.dhall view
@@ -0,0 +1,1 @@+let {- 1 -} x {- 2 -} : {- 3 -} Natural = {- 4 -} 1 {- 5 -} in x
+ tests/lint/success/issue1586B.dhall view
@@ -0,0 +1,5 @@+let {- 1 -} x+    {- 2 -} : {- 3 -} Natural+    = {- 4 -} 1++in  x
+ tests/lint/success/multiletA.dhall view
@@ -0,0 +1,34 @@+-- example0.dhall+let Person+    : Type+    =   ∀(Person : Type)+      → ∀(MakePerson : { children : List Person, name : Text } → Person)+      → Person++let example+    : Person+    =   λ(Person : Type)+      → λ(MakePerson : { children : List Person, name : Text } → Person)+      → MakePerson+        { children =+            [ MakePerson { children = [] : List Person, name = "Mary" }+            , MakePerson { children = [] : List Person, name = "Jane" }+            ]+        , name =+            "John"+        }++let everybody+    : Person → List Text+    = let concat = http://prelude.dhall-lang.org/List/concat.dhall+      +      in    λ(x : Person)+          → x+            (List Text)+            (   λ(p : { children : List (List Text), name : Text })+              → [ p.name ] # concat Text p.children+            )++let result : List Text = everybody example++in  result
+ tests/lint/success/multiletB.dhall view
@@ -0,0 +1,35 @@+-- example0.dhall+let Person+    : Type+    = ∀(Person : Type) →+      ∀(MakePerson : { children : List Person, name : Text } → Person) →+        Person++let example+    : Person+    = λ(Person : Type) →+      λ(MakePerson : { children : List Person, name : Text } → Person) →+        MakePerson+          { children =+            [ MakePerson { children = [] : List Person, name = "Mary" }+            , MakePerson { children = [] : List Person, name = "Jane" }+            ]+          , name = "John"+          }++let everybody+    : Person → List Text+    = let concat = http://prelude.dhall-lang.org/List/concat.dhall++      in  λ(x : Person) →+            x+              (List Text)+              ( λ(p : { children : List (List Text), name : Text }) →+                  [ p.name ] # concat Text p.children+              )++let result+    : List Text+    = everybody example++in  result
+ tests/lint/success/regression0A.dhall view
@@ -0,0 +1,7 @@+    let replicate = https://prelude.dhall-lang.org/List/replicate.dhall++in  let Config = { name : Text, age : Natural }++in  let Configs = List Config++in  replicate 10 Text "!"
+ tests/lint/success/regression0B.dhall view
@@ -0,0 +1,3 @@+let replicate = https://prelude.dhall-lang.org/List/replicate.dhall++in  replicate 10 Text "!"
− tests/normalization/doubleShowA.dhall
@@ -1,1 +0,0 @@-{ example0 = Double/show -0.42, example1 = Double/show 13.37 }
− tests/normalization/doubleShowB.dhall
@@ -1,1 +0,0 @@-{ example0 = "-0.42", example1 = "13.37" }
− tests/normalization/examples/Bool/and/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/and [ True, False, True ]
− tests/normalization/examples/Bool/and/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/and/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/and ([] : List Bool)
− tests/normalization/examples/Bool/and/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/build/0A.dhall
@@ -1,2 +0,0 @@-../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
− tests/normalization/examples/Bool/build/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/build/1A.dhall
@@ -1,2 +0,0 @@-../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
− tests/normalization/examples/Bool/build/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/even [ False, True, False ]
− tests/normalization/examples/Bool/even/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/even [ False, True ]
− tests/normalization/examples/Bool/even/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/even/2A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/even [ False ]
− tests/normalization/examples/Bool/even/2B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/even/3A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/even ([] : List Bool)
− tests/normalization/examples/Bool/even/3B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/fold True Integer 0 1
− tests/normalization/examples/Bool/fold/0B.dhall
@@ -1,1 +0,0 @@-0
− tests/normalization/examples/Bool/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/fold False Integer 0 1
− tests/normalization/examples/Bool/fold/1B.dhall
@@ -1,1 +0,0 @@-1
− tests/normalization/examples/Bool/not/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/not True
− tests/normalization/examples/Bool/not/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/not/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/not False
− tests/normalization/examples/Bool/not/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/odd [ True, False, True ]
− tests/normalization/examples/Bool/odd/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/odd [ True, False ]
− tests/normalization/examples/Bool/odd/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/odd/2A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/odd [ True ]
− tests/normalization/examples/Bool/odd/2B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/odd/3A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/odd ([] : List Bool)
− tests/normalization/examples/Bool/odd/3B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/or/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/or [ True, False, True ]
− tests/normalization/examples/Bool/or/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Bool/or/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/or ([] : List Bool)
− tests/normalization/examples/Bool/or/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Bool/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/show True
− tests/normalization/examples/Bool/show/0B.dhall
@@ -1,1 +0,0 @@-"True"
− tests/normalization/examples/Bool/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/show False
− tests/normalization/examples/Bool/show/1B.dhall
@@ -1,1 +0,0 @@-"False"
− tests/normalization/examples/Double/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Double/show -3.1
− tests/normalization/examples/Double/show/0B.dhall
@@ -1,1 +0,0 @@-"-3.1"
− tests/normalization/examples/Double/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Double/show 0.4
− tests/normalization/examples/Double/show/1B.dhall
@@ -1,1 +0,0 @@-"0.4"
− tests/normalization/examples/Integer/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Integer/show -3
− tests/normalization/examples/Integer/show/0B.dhall
@@ -1,1 +0,0 @@-"-3"
− tests/normalization/examples/Integer/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Integer/show 0
− tests/normalization/examples/Integer/show/1B.dhall
@@ -1,1 +0,0 @@-"0"
− tests/normalization/examples/List/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/all Natural Natural/even [ +2, +3, +5 ]
− tests/normalization/examples/List/all/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/List/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)
− tests/normalization/examples/List/all/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/List/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/any Natural Natural/even [ +2, +3, +5 ]
− tests/normalization/examples/List/any/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/List/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)
− tests/normalization/examples/List/any/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/List/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ cons "ABC" (cons "DEF" nil)-)
− tests/normalization/examples/List/build/0B.dhall
@@ -1,1 +0,0 @@-[ "ABC", "DEF" ]
− tests/normalization/examples/List/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ nil-)
− tests/normalization/examples/List/build/1B.dhall
@@ -1,1 +0,0 @@-[] : List Text
− tests/normalization/examples/List/concat/0A.dhall
@@ -1,5 +0,0 @@-../../../../../Prelude/List/concat Integer-[ [ 0, 1, 2 ]-, [ 3, 4 ]-, [ 5, 6, 7, 8 ]-]
− tests/normalization/examples/List/concat/0B.dhall
@@ -1,1 +0,0 @@-[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
− tests/normalization/examples/List/concat/1A.dhall
@@ -1,5 +0,0 @@-../../../../../Prelude/List/concat Integer-[ [] : List Integer-, [] : List Integer-, [] : List Integer-]
− tests/normalization/examples/List/concat/1B.dhall
@@ -1,1 +0,0 @@-[] : List Integer
− tests/normalization/examples/List/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ +2, +3, +5 ]
− tests/normalization/examples/List/concatMap/0B.dhall
@@ -1,1 +0,0 @@-[ +2, +2, +3, +3, +5, +5 ]
− tests/normalization/examples/List/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
− tests/normalization/examples/List/concatMap/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− tests/normalization/examples/List/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/filter Natural Natural/even [ +2, +3, +5 ]
− tests/normalization/examples/List/filter/0B.dhall
@@ -1,1 +0,0 @@-[ +2 ]
− tests/normalization/examples/List/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/filter Natural Natural/odd [ +2, +3, +5 ]
− tests/normalization/examples/List/filter/1B.dhall
@@ -1,1 +0,0 @@-[ +3, +5 ]
− tests/normalization/examples/List/fold/0A.dhall
@@ -1,6 +0,0 @@-../../../../../Prelude/List/fold-Natural-[ +2, +3, +5 ]-Natural-(λ(x : Natural) → λ(y : Natural) → x + y)-+0
− tests/normalization/examples/List/fold/0B.dhall
@@ -1,1 +0,0 @@-+10
− tests/normalization/examples/List/fold/1A.dhall
@@ -1,7 +0,0 @@-  λ(nil : Natural)-→ ../../../../../Prelude/List/fold-  Natural-  [ +2, +3, +5 ]-  Natural-  (λ(x : Natural) → λ(y : Natural) → x + y)-  nil
− tests/normalization/examples/List/fold/1B.dhall
@@ -1,1 +0,0 @@-λ(nil : Natural) → +2 + +3 + +5 + nil
− tests/normalization/examples/List/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(list : Type)-→ λ(cons : Natural → list → list)-→ λ(nil : list)-→ ../../../../../Prelude/List/fold Natural [ +2, +3, +5 ] list cons nil
− tests/normalization/examples/List/fold/2B.dhall
@@ -1,4 +0,0 @@-  λ(list : Type)-→ λ(cons : Natural → list → list)-→ λ(nil : list)-→ cons +2 (cons +3 (cons +5 nil))
− tests/normalization/examples/List/generate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/generate +5 Bool Natural/even
− tests/normalization/examples/List/generate/0B.dhall
@@ -1,1 +0,0 @@-[ True, False, True, False, True ]
− tests/normalization/examples/List/generate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/generate +0 Bool Natural/even
− tests/normalization/examples/List/generate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Bool
− tests/normalization/examples/List/head/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/head Integer [ 0, 1, 2 ]
− tests/normalization/examples/List/head/0B.dhall
@@ -1,1 +0,0 @@-[ 0 ] : Optional Integer
− tests/normalization/examples/List/head/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/head Integer ([] : List Integer)
− tests/normalization/examples/List/head/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/List/indexed/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/indexed Bool ([] : List Bool)
− tests/normalization/examples/List/indexed/0B.dhall
@@ -1,4 +0,0 @@-[ { index = +0, value = True }-, { index = +1, value = False }-, { index = +2, valu;e = True }-]
− tests/normalization/examples/List/indexed/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/indexed Bool ([] : List Bool)
− tests/normalization/examples/List/indexed/1B.dhall
@@ -1,1 +0,0 @@-[] : List { index : Natural, value : Bool }
− tests/normalization/examples/List/iterate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/iterate +10 Natural (λ(x : Natural) → x * +2) +1
− tests/normalization/examples/List/iterate/0B.dhall
@@ -1,1 +0,0 @@-[ +1, +2, +4, +8, +16, +32, +64, +128, +256, +512 ]
− tests/normalization/examples/List/iterate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/iterate +0 Natural (λ(x : Natural) → x * +2) +1
− tests/normalization/examples/List/iterate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− tests/normalization/examples/List/last/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/last Integer [ 0, 1, 2 ]
− tests/normalization/examples/List/last/0B.dhall
@@ -1,1 +0,0 @@-[ 2 ] : Optional Integer
− tests/normalization/examples/List/last/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/last Integer ([] : List Integer)
− tests/normalization/examples/List/last/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/List/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/length Integer [ 0, 1, 2 ]
− tests/normalization/examples/List/length/0B.dhall
@@ -1,1 +0,0 @@-+3
− tests/normalization/examples/List/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/length Integer ([] : List Integer)
− tests/normalization/examples/List/length/1B.dhall
@@ -1,1 +0,0 @@-+0
− tests/normalization/examples/List/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/map Natural Bool Natural/even [ +2, +3, +5 ]
− tests/normalization/examples/List/map/0B.dhall
@@ -1,1 +0,0 @@-[ True, False, False ]
− tests/normalization/examples/List/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)
− tests/normalization/examples/List/map/1B.dhall
@@ -1,1 +0,0 @@-[] : List Bool
− tests/normalization/examples/List/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/null Integer [ 0, 1, 2 ]
− tests/normalization/examples/List/null/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/List/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/null Integer ([] : List Integer)
− tests/normalization/examples/List/null/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/List/replicate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/replicate +9 Integer 1
− tests/normalization/examples/List/replicate/0B.dhall
@@ -1,1 +0,0 @@-[ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
− tests/normalization/examples/List/replicate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/replicate +0 Integer 1
− tests/normalization/examples/List/replicate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Integer
− tests/normalization/examples/List/reverse/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/reverse Integer [ 0, 1, 2 ]
− tests/normalization/examples/List/reverse/0B.dhall
@@ -1,1 +0,0 @@-[ 2, 1, 0 ]
− tests/normalization/examples/List/reverse/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/reverse Integer ([] : List Integer)
− tests/normalization/examples/List/reverse/1B.dhall
@@ -1,1 +0,0 @@-[] : List Integer
− tests/normalization/examples/List/shifted/0A.dhall
@@ -1,15 +0,0 @@-../../../../../Prelude/List/shifted-Bool-[ [ { index = +0, value = True }-  , { index = +1, value = True }-  , { index = +2, value = False }-  ]-, [ { index = +0, value = False }-  , { index = +1, value = False }-  ]-, [ { index = +0, value = True }-  , { index = +1, value = True }-  , { index = +2, value = True }-  , { index = +3, value = True }-  ]-]
− tests/normalization/examples/List/shifted/0B.dhall
@@ -1,10 +0,0 @@-[ { index = +0, value = True }-, { index = +1, value = True }-, { index = +2, value = False }-, { index = +3, value = False }-, { index = +4, value = False }-, { index = +5, value = True }-, { index = +6, value = True }-, { index = +7, value = True }-, { index = +8, value = True }-]
− tests/normalization/examples/List/shifted/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))
− tests/normalization/examples/List/shifted/1B.dhall
@@ -1,1 +0,0 @@-[] : List { index : Natural, value : Bool }
− tests/normalization/examples/List/unzip/0A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/List/unzip-Text-Bool-[ { _1 = "ABC", _2 = True }-, { _1 = "DEF", _2 = False }-, { _1 = "GHI", _2 = True }-]
− tests/normalization/examples/List/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 = [ "ABC", "DEF", "GHI" ], _2 = [ True, False, True ] }
− tests/normalization/examples/List/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })
− tests/normalization/examples/List/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 = [] : List Text, _2 = [] : List Bool }
− tests/normalization/examples/Natural/build/0A.dhall
@@ -1,6 +0,0 @@-../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ succ (succ (succ zero))-)
− tests/normalization/examples/Natural/build/0B.dhall
@@ -1,1 +0,0 @@-+3
− tests/normalization/examples/Natural/build/1A.dhall
@@ -1,6 +0,0 @@-../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ zero-)
− tests/normalization/examples/Natural/build/1B.dhall
@@ -1,1 +0,0 @@-+0
− tests/normalization/examples/Natural/enumerate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/enumerate +10
− tests/normalization/examples/Natural/enumerate/0B.dhall
@@ -1,1 +0,0 @@-[ +0, +1, +2, +3, +4, +5, +6, +7, +8, +9 ]
− tests/normalization/examples/Natural/enumerate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/enumerate +0
− tests/normalization/examples/Natural/enumerate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− tests/normalization/examples/Natural/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/even +3
− tests/normalization/examples/Natural/even/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Natural/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/even +0
− tests/normalization/examples/Natural/even/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Natural/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/fold +3 Natural (λ(x : Natural) → +5 * x) +1
− tests/normalization/examples/Natural/fold/0B.dhall
@@ -1,1 +0,0 @@-+125
− tests/normalization/examples/Natural/fold/1A.dhall
@@ -1,1 +0,0 @@-λ(zero : Natural) → ../../../../../Prelude/Natural/fold +3 Natural (λ(x : Natural) → +5 * x) zero
− tests/normalization/examples/Natural/fold/1B.dhall
@@ -1,1 +0,0 @@-λ(zero : Natural) → +5 * +5 * +5 * zero
− tests/normalization/examples/Natural/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ ../../../../../Prelude/Natural/fold +3 natural succ zero
− tests/normalization/examples/Natural/fold/2B.dhall
@@ -1,1 +0,0 @@-λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ (succ zero))
− tests/normalization/examples/Natural/isZero/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/isZero +2
− tests/normalization/examples/Natural/isZero/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Natural/isZero/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/isZero +0
− tests/normalization/examples/Natural/isZero/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Natural/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/odd +3
− tests/normalization/examples/Natural/odd/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Natural/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/odd +0
− tests/normalization/examples/Natural/odd/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Natural/product/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/product [ +2, +3, +5 ]
− tests/normalization/examples/Natural/product/0B.dhall
@@ -1,1 +0,0 @@-+30
− tests/normalization/examples/Natural/product/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/product ([] : List Natural)
− tests/normalization/examples/Natural/product/1B.dhall
@@ -1,1 +0,0 @@-+1
− tests/normalization/examples/Natural/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/show +3
− tests/normalization/examples/Natural/show/0B.dhall
@@ -1,1 +0,0 @@-"+3"
− tests/normalization/examples/Natural/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/show +0
− tests/normalization/examples/Natural/show/1B.dhall
@@ -1,1 +0,0 @@-"+0"
− tests/normalization/examples/Natural/sum/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/sum [ +2, +3, +5 ]
− tests/normalization/examples/Natural/sum/0B.dhall
@@ -1,1 +0,0 @@-+10
− tests/normalization/examples/Natural/sum/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/sum ([] : List Natural)
− tests/normalization/examples/Natural/sum/1B.dhall
@@ -1,1 +0,0 @@-+0
− tests/normalization/examples/Natural/toInteger/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/toInteger +3
− tests/normalization/examples/Natural/toInteger/0B.dhall
@@ -1,1 +0,0 @@-3
− tests/normalization/examples/Natural/toInteger/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/toInteger +0
− tests/normalization/examples/Natural/toInteger/1B.dhall
@@ -1,1 +0,0 @@-0
− tests/normalization/examples/Optional/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/all Natural Natural/even ([ +3 ] : Optional Natural)
− tests/normalization/examples/Optional/all/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Optional/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/all Natural Natural/even ([] : Optional Natural)
− tests/normalization/examples/Optional/all/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Optional/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/any Natural Natural/even ([ +2 ] : Optional Natural)
− tests/normalization/examples/Optional/any/0B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Optional/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/any Natural Natural/even ([] : Optional Natural)
− tests/normalization/examples/Optional/any/1B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Optional/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/Optional/build-Integer-( λ(optional : Type)-→ λ(just : Integer → optional)-→ λ(nothing : optional)-→ just 1-)
− tests/normalization/examples/Optional/build/0B.dhall
@@ -1,1 +0,0 @@-[ 1 ] : Optional Integer
− tests/normalization/examples/Optional/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/Optional/build-Integer-( λ(optional : Type)-→ λ(just : Integer → optional)-→ λ(nothing : optional)-→ nothing-)
− tests/normalization/examples/Optional/build/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/concat Integer ([ [ 1 ] : Optional Integer ] : Optional (Optional Integer))
− tests/normalization/examples/Optional/concat/0B.dhall
@@ -1,1 +0,0 @@-[ 1 ] : Optional Integer
− tests/normalization/examples/Optional/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/concat Integer ([ [] : Optional Integer ] : Optional (Optional Integer))
− tests/normalization/examples/Optional/concat/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/concat/2A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/concat Integer ([ [] : Optional Integer ]: Optional (Optional Integer))
− tests/normalization/examples/Optional/concat/2B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/filter Natural Natural/even ([ +2 ] : Optional Natural)
− tests/normalization/examples/Optional/filter/0B.dhall
@@ -1,1 +0,0 @@-[ +2 ] : Optional Natural
− tests/normalization/examples/Optional/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/filter Natural Natural/odd ([ +2 ] : Optional Natural)
− tests/normalization/examples/Optional/filter/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Natural
− tests/normalization/examples/Optional/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/fold Integer ([ 2 ] : Optional Integer) Integer (λ(x : Integer) → x) 0
− tests/normalization/examples/Optional/fold/0B.dhall
@@ -1,1 +0,0 @@-2
− tests/normalization/examples/Optional/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/fold Integer ([] : Optional Integer) Integer (λ(x : Integer) → x) 0
− tests/normalization/examples/Optional/fold/1B.dhall
@@ -1,1 +0,0 @@-0
− tests/normalization/examples/Optional/head/0A.dhall
@@ -1,6 +0,0 @@-../../../../../Prelude/Optional/head-Integer-[ []    : Optional Integer-, [ 1 ] : Optional Integer-, [ 2 ] : Optional Integer-]
− tests/normalization/examples/Optional/head/0B.dhall
@@ -1,1 +0,0 @@-[ 1 ] : Optional Integer
− tests/normalization/examples/Optional/head/1A.dhall
@@ -1,3 +0,0 @@-../../../../../Prelude/Optional/head-Integer-[ [] : Optional Integer, [] : Optional Integer ]
− tests/normalization/examples/Optional/head/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/last/0A.dhall
@@ -1,7 +0,0 @@-../../../../../Prelude/Optional/last-Integer-( [ [] : Optional Integer-  , [ 1 ] : Optional Integer-  , [ 2 ] : Optional Integer-  ]-)
− tests/normalization/examples/Optional/last/0B.dhall
@@ -1,1 +0,0 @@-[ 2 ] : Optional Integer
− tests/normalization/examples/Optional/last/1A.dhall
@@ -1,3 +0,0 @@-../../../../../Prelude/Optional/last-Integer-[ [] : Optional Integer, [] : Optional Integer ]
− tests/normalization/examples/Optional/last/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/last/2A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/last Integer ([] : List (Optional Integer))
− tests/normalization/examples/Optional/last/2B.dhall
@@ -1,1 +0,0 @@-[] : Optional Integer
− tests/normalization/examples/Optional/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/length Integer ([ 2 ] : Optional Integer)
− tests/normalization/examples/Optional/length/0B.dhall
@@ -1,1 +0,0 @@-+1
− tests/normalization/examples/Optional/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/length Integer ([] : Optional Integer)
− tests/normalization/examples/Optional/length/1B.dhall
@@ -1,1 +0,0 @@-+0
− tests/normalization/examples/Optional/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/map Natural Bool Natural/even ([ +3 ] : Optional Natural)
− tests/normalization/examples/Optional/map/0B.dhall
@@ -1,1 +0,0 @@-[ False ] : Optional Bool
− tests/normalization/examples/Optional/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/map Natural Bool Natural/even ([] : Optional Natural)
− tests/normalization/examples/Optional/map/1B.dhall
@@ -1,1 +0,0 @@-[] : Optional Bool
− tests/normalization/examples/Optional/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/null Integer ([ 2 ] : Optional Integer)
− tests/normalization/examples/Optional/null/0B.dhall
@@ -1,1 +0,0 @@-False
− tests/normalization/examples/Optional/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/null Integer ([] : Optional Integer)
− tests/normalization/examples/Optional/null/1B.dhall
@@ -1,1 +0,0 @@-True
− tests/normalization/examples/Optional/toList/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/toList Integer ([ 1 ] : Optional Integer)
− tests/normalization/examples/Optional/toList/0B.dhall
@@ -1,1 +0,0 @@-[ 1 ]
− tests/normalization/examples/Optional/toList/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/toList Integer ([] : Optional Integer)
− tests/normalization/examples/Optional/toList/1B.dhall
@@ -1,1 +0,0 @@-[] : List Integer
− tests/normalization/examples/Optional/unzip/0A.dhall
@@ -1,4 +0,0 @@-../../../../../Prelude/Optional/unzip-Text-Bool-([ { _1 = "ABC", _2 = True } ] : Optional { _1 : Text, _2 : Bool })
− tests/normalization/examples/Optional/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 = [ "ABC" ] : Optional Text, _2 = [ True ] : Optional Bool }
− tests/normalization/examples/Optional/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/unzip Text Bool ([] : Optional { _1 : Text, _2 : Bool })
− tests/normalization/examples/Optional/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 = [] : Optional Text, _2 = [] : Optional Bool }
− tests/normalization/examples/Text/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]
− tests/normalization/examples/Text/concat/0B.dhall
@@ -1,1 +0,0 @@-"ABCDEFGHI"
− tests/normalization/examples/Text/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concat ([] : List Text)
− tests/normalization/examples/Text/concat/1B.dhall
@@ -1,1 +0,0 @@-""
− tests/normalization/examples/Text/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatMap Integer (λ(n : Integer) → "${Integer/show n} ") [ 0, 1, 2 ]
− tests/normalization/examples/Text/concatMap/0B.dhall
@@ -1,1 +0,0 @@-"0 1 2 "
− tests/normalization/examples/Text/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatMap Integer (λ(n : Integer) → "${Integer/show n} ") ([] : List Integer)
− tests/normalization/examples/Text/concatMap/1B.dhall
@@ -1,1 +0,0 @@-""
− tests/normalization/examples/Text/concatMapSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatMapSep ", " Integer Integer/show [ 0, 1, 2 ]
− tests/normalization/examples/Text/concatMapSep/0B.dhall
@@ -1,1 +0,0 @@-"0, 1, 2"
− tests/normalization/examples/Text/concatMapSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatMapSep ", " Integer Integer/show ([] : List Integer)
− tests/normalization/examples/Text/concatMapSep/1B.dhall
@@ -1,1 +0,0 @@-""
− tests/normalization/examples/Text/concatSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]
− tests/normalization/examples/Text/concatSep/0B.dhall
@@ -1,1 +0,0 @@-"ABC, DEF, GHI"
− tests/normalization/examples/Text/concatSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concatSep ", " ([] : List Text)
− tests/normalization/examples/Text/concatSep/1B.dhall
@@ -1,1 +0,0 @@-""
− tests/normalization/integerShowA.dhall
@@ -1,4 +0,0 @@-{ example0 = Integer/show 1337-, example1 = Integer/show -42-, example2 = Integer/show 0-}
− tests/normalization/integerShowB.dhall
@@ -1,1 +0,0 @@-{ example0 = "1337", example1 = "-42", example2 = "0" }
− tests/normalization/listBuildA.dhall
@@ -1,22 +0,0 @@-{ example0 =-    List/build-    Bool-    (   λ(list : Type)-      → λ(cons : Bool → list → list)-      → λ(nil : list)-      → cons True (cons False nil)-    )-, example1 =-    List/build-    Bool-    (λ(x : Type) → λ(x : Bool → x → x) → λ(x : x@1) → x@1 True (x@1 False x))-, example2 =-      λ(id : ∀(a : Type) → a → a)-    → List/build-      Bool-      (   λ(list : Type)-        → λ(cons : Bool → list → list)-        → λ(nil : list)-        → id list (cons True (cons False nil))-      )-}
− tests/normalization/listBuildB.dhall
@@ -1,7 +0,0 @@-{ example0 =-    [ True, False ] : List Bool-, example1 =-    [ True, False ] : List Bool-, example2 =-    λ(id : ∀(a : Type) → a → a) → id (List Bool) [ True, False ]-}
− tests/normalization/naturalBuildA.dhall
@@ -1,18 +0,0 @@-{ example0 =-    Natural/build-    (   λ(natural : Type)-      → λ(succ : natural → natural)-      → λ(zero : natural)-      → succ zero-    )-, example1 =-    Natural/build (λ(x : Type) → λ(x : x → x) → λ(x : x@1) → x@1 x)-, example2 =-      λ(id : ∀(a : Type) → a → a)-    → Natural/build-      (   λ(natural : Type)-        → λ(succ : natural → natural)-        → λ(zero : natural)-        → id natural (succ zero)-      )-}
− tests/normalization/naturalBuildB.dhall
@@ -1,7 +0,0 @@-{ example0 =-    +1-, example1 =-    +1-, example2 =-    λ(id : ∀(a : Type) → a → a) → id Natural +1-}
− tests/normalization/naturalPlusA.dhall
@@ -1,1 +0,0 @@-+1 + +2
− tests/normalization/naturalPlusB.dhall
@@ -1,1 +0,0 @@-+3
− tests/normalization/naturalShowA.dhall
@@ -1,1 +0,0 @@-Natural/show +42
− tests/normalization/naturalShowB.dhall
@@ -1,1 +0,0 @@-"+42"
− tests/normalization/naturalToIntegerA.dhall
@@ -1,1 +0,0 @@-Natural/toInteger +1
− tests/normalization/naturalToIntegerB.dhall
@@ -1,1 +0,0 @@-1
− tests/normalization/optionalBuildA.dhall
@@ -1,32 +0,0 @@-{ example0 =-    Optional/build-    Natural-    (   λ(optional : Type)-      → λ(just : Natural → optional)-      → λ(nothing : optional)-      → just +1-    )-, example1 =-    Optional/build-    Integer-    (λ(optional : Type) → λ(x : Integer → optional) → λ(x : optional) → x@1 1)-, example2 =-      λ(id : ∀(a : Type) → a → a)-    → Optional/build-      Bool-      (   λ(optional : Type)-        → λ(just : Bool → optional)-        → λ(nothing : optional)-        → id optional (just True)-      )-, example3 =-      λ(a : Type)-    → λ(x : a)-    → Optional/build-      a-      (   λ(optional : Type)-        → λ(just : a → optional)-        → λ(nothing : optional)-        → just x-      )-}
− tests/normalization/optionalBuildB.dhall
@@ -1,9 +0,0 @@-{ example0 =-    [ +1 ] : Optional Natural-, example1 =-    [ 1 ] : Optional Integer-, example2 =-    λ(id : ∀(a : Type) → a → a) → id (Optional Bool) ([ True ] : Optional Bool)-, example3 =-    λ(a : Type) → λ(x : a) → [ x ] : Optional a-}
− tests/normalization/optionalBuildFoldA.dhall
@@ -1,1 +0,0 @@-Optional/build Text (Optional/fold Text ([ "foo" ] : Optional Text))
− tests/normalization/optionalBuildFoldB.dhall
@@ -1,1 +0,0 @@-[ "foo" ] : Optional Text
− tests/normalization/optionalFoldA.dhall
@@ -1,7 +0,0 @@-    let f =-            λ(o : Optional Text)-          → Optional/fold Text o Natural (λ(j : Text) → +1) +2--in  { example0 = f ([ "foo" ] : Optional Text)-    , example1 = f ([] : Optional Text)-    }
− tests/normalization/optionalFoldB.dhall
@@ -1,1 +0,0 @@-{ example0 = +1, example1 = +2 }
− tests/normalization/remoteSystemsA.dhall
@@ -1,55 +0,0 @@-    let Text/concatMap =-          ../../Prelude/Text/concatMap --in  let Text/concatSep =-          ../../Prelude/Text/concatSep --in  let Row =-          { cores :-              Natural-          , host :-              Text-          , key :-              Text-          , mandatoryFeatures :-              List Text-          , platforms :-              List Text-          , speedFactor :-              Natural-          , supportedFeatures :-              List Text-          , user :-              Optional Text-          }--in  let renderRow =-            λ ( row-              : Row-              )-          →     let host =-                      Optional/fold-                      Text-                      row.user-                      Text-                      (λ(user : Text) → "${user}@${row.host}")-                      row.host-            -            in  let platforms = Text/concatSep "," row.platforms-            -            in  let key = row.key-            -            in  let cores = Integer/show (Natural/toInteger row.cores)-            -            in  let speedFactor =-                      Integer/show (Natural/toInteger row.speedFactor)-            -            in  let supportedFeatures = Text/concatSep "," row.supportedFeatures-            -            in  let mandatoryFeatures = Text/concatSep "," row.mandatoryFeatures-            -            in  ''-                ${host} ${platforms} ${key} ${cores} ${speedFactor} ${supportedFeatures} ${mandatoryFeatures}-                ''--in  Text/concatMap Row renderRow
− tests/normalization/remoteSystemsB.dhall
@@ -1,1 +0,0 @@-λ(xs : List { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text }) → List/fold { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text } xs Text (λ(x : { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text }) → λ(y : Text) → "${Optional/fold Text x.user Text (λ(user : Text) → "${user}@${x.host}") x.host} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.platforms < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text} ${x.key} ${Integer/show (Natural/toInteger x.cores)} ${Integer/show (Natural/toInteger x.speedFactor)} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.supportedFeatures < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.mandatoryFeatures < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text}\n" ++ y) ""
− tests/normalization/simplifications/andA.dhall
@@ -1,6 +0,0 @@-{ example0 = λ(x : Bool) → x && True-, example1 = λ(x : Bool) → True && x-, example2 = λ(x : Bool) → x && False-, example3 = λ(x : Bool) → False && x-, example4 = λ(x : Bool) → x && x-}
− tests/normalization/simplifications/andB.dhall
@@ -1,6 +0,0 @@-{ example0 = λ(x : Bool) → x-, example1 = λ(x : Bool) → x-, example2 = λ(x : Bool) → False-, example3 = λ(x : Bool) → False-, example4 = λ(x : Bool) → x-}
− tests/normalization/simplifications/eqA.dhall
@@ -1,4 +0,0 @@-{ example0 = λ(x : Bool) → x == True-, example1 = λ(x : Bool) → True == x-, example2 = λ(x : Bool) → x == x-}
− tests/normalization/simplifications/eqB.dhall
@@ -1,4 +0,0 @@-{ example0 = λ(x : Bool) → x-, example1 = λ(x : Bool) → x-, example2 = λ(x : Bool) → True-}
− tests/normalization/simplifications/ifThenElseA.dhall
@@ -1,3 +0,0 @@-{ example0 = λ(x : Bool) → if x then True else False-, example1 = λ(x : Bool) → λ(y : Text) → if x then y else y-}
− tests/normalization/simplifications/ifThenElseB.dhall
@@ -1,3 +0,0 @@-{ example0 = λ(x : Bool) → x-, example1 = λ(x : Bool) → λ(y : Text) → y-}
− tests/normalization/simplifications/neA.dhall
@@ -1,4 +0,0 @@-{ example0 = λ(x : Bool) → x != False-, example1 = λ(x : Bool) → False != x-, example2 = λ(x : Bool) → x != x-}
− tests/normalization/simplifications/neB.dhall
@@ -1,4 +0,0 @@-{ example0 = λ(x : Bool) → x-, example1 = λ(x : Bool) → x-, example2 = λ(x : Bool) → False-}
− tests/normalization/simplifications/orA.dhall
@@ -1,6 +0,0 @@-{ example0 = λ(x : Bool) → x || True-, example1 = λ(x : Bool) → True || x-, example2 = λ(x : Bool) → x || False-, example3 = λ(x : Bool) → False || x-, example4 = λ(x : Bool) → x || x-}
− tests/normalization/simplifications/orB.dhall
@@ -1,6 +0,0 @@-{ example0 = λ(x : Bool) → True-, example1 = λ(x : Bool) → True-, example2 = λ(x : Bool) → x-, example3 = λ(x : Bool) → x-, example4 = λ(x : Bool) → x-}
+ tests/package/dir/package.dhall view
+ tests/package/dir/subdirectory1/test.dhall view
+ tests/package/dir/subdirectory2/wrong-extension.txt view
+ tests/package/dir/test.dhall view
+ tests/package/dir/wrong-extension.txt view
+ tests/package/empty/wrong-extension.txt view
+ tests/package/other/package.dhall view
+ tests/package/package.dhall view
+ tests/package/test.dhall view
+ tests/package/test/test.dhall view
− tests/parser/annotations.dhall
@@ -1,4 +0,0 @@-{ foo = ([] : List Integer) # [1, 2, 3] # ([1, 2, 3] : List Integer)-, bar = [] : Optional Integer-, baz = [1] : Optional Integer-} : { foo : List Integer, bar : Optional Integer, baz : Optional Integer }
− tests/parser/blockComment.dhall
@@ -1,3 +0,0 @@-{- foo -}--1
− tests/parser/builtins.dhall
@@ -1,31 +0,0 @@-  λ ( x-    : { field0 : Bool-      , field1 : Optional (Optional Bool)-      , field2 : Natural-      , field3 : Integer-      , field4 : Double-      , field5 : Text-      , field6 : List (List Bool)-      }-    )-→ { field00 = Natural/fold-  , field01 = Natural/build-  , field02 = Natural/isZero-  , field03 = Natural/even-  , field04 = Natural/odd-  , field05 = Natural/toInteger-  , field06 = Natural/show-  , field07 = Integer/show-  , field08 = Double/show-  , field09 = List/build-  , field10 = List/fold-  , field11 = List/length-  , field12 = List/head-  , field13 = List/last-  , field14 = List/indexed-  , field15 = List/reverse-  , field16 = Optional/fold-  , field17 = Optional/build-  , field18 = True-  , field19 = False-  }
− tests/parser/constructors.dhall
@@ -1,1 +0,0 @@-constructors < Left : Natural | Right : Bool >
− tests/parser/double.dhall
@@ -1,1 +0,0 @@-[ 1.1, -1.1, 1e1, 1.1e1, -1.1 ]
− tests/parser/doubleQuotedString.dhall
@@ -1,1 +0,0 @@-"ABC"
− tests/parser/environmentVariables.dhall
@@ -1,5 +0,0 @@-[ env:FOO--  -- Yes, this is legal-, env:"\"\\\a\b\f\n\r\t\v"-]
− tests/parser/escapedDoubleQuotedString.dhall
@@ -1,1 +0,0 @@-"\\\"\$\\\/\b\f\n\r\t \u2200(a : Type) \u2192 a"
− tests/parser/escapedSingleQuotedString.dhall
@@ -1,4 +0,0 @@-''-''${-'''-''
− tests/parser/fields.dhall
@@ -1,1 +0,0 @@-({ foo = { bar = { baz = 1 } } }).foo. bar .baz
− tests/parser/forall.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → forall (b : Type) -> a
− tests/parser/functionType.dhall
@@ -1,1 +0,0 @@-Bool → Bool -> Bool
− tests/parser/identifier.dhall
@@ -1,1 +0,0 @@-λ(a : Type) → λ(a : Type) → a@1
− tests/parser/ifThenElse.dhall
@@ -1,1 +0,0 @@-if True then 1 else 2
− tests/parser/interpolatedDoubleQuotedString.dhall
@@ -1,1 +0,0 @@-"ABC${Integer/show 123}"
− tests/parser/interpolatedSingleQuotedString.dhall
@@ -1,4 +0,0 @@-''-ABC-${Integer/show 123}-''
− tests/parser/label.dhall
@@ -1,2 +0,0 @@-let _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/ = 1-in  _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/
− tests/parser/lambda.dhall
@@ -1,1 +0,0 @@-λ(a : Type) → \(b : Type) -> a
− tests/parser/largeExpression.dhall
@@ -1,254 +0,0 @@-  λ ( xs-    : List-      { cores             : Natural-      , host              : Text-      , key               : Text-      , mandatoryFeatures : List Text-      , platforms         :-          List-          < AArch64_Linux  : {}-          | ARMv5tel_Linux : {}-          | ARMv7l_Linux   : {}-          | I686_Cygwin    : {}-          | I686_Linux     : {}-          | MIPS64el_Linux : {}-          | PowerPC_Linux  : {}-          | X86_64_Cygwin  : {}-          | X86_64_Darwin  : {}-          | X86_64_FreeBSD : {}-          | X86_64_Linux   : {}-          | X86_64_Solaris : {}-          >-      , speedFactor       : Natural-      , supportedFeatures : List Text-      , user              : Optional Text-      }-    )-→ List/fold-  { cores             : Natural-  , host              : Text-  , key               : Text-  , mandatoryFeatures : List Text-  , platforms         :-      List-      < AArch64_Linux  : {}-      | ARMv5tel_Linux : {}-      | ARMv7l_Linux   : {}-      | I686_Cygwin    : {}-      | I686_Linux     : {}-      | MIPS64el_Linux : {}-      | PowerPC_Linux  : {}-      | X86_64_Cygwin  : {}-      | X86_64_Darwin  : {}-      | X86_64_FreeBSD : {}-      | X86_64_Linux   : {}-      | X86_64_Solaris : {}-      >-  , speedFactor       : Natural-  , supportedFeatures : List Text-  , user              : Optional Text-  }-  xs-  Text-  (   λ ( x-        : { cores             : Natural-          , host              : Text-          , key               : Text-          , mandatoryFeatures : List Text-          , platforms         :-              List-              < AArch64_Linux  : {}-              | ARMv5tel_Linux : {}-              | ARMv7l_Linux   : {}-              | I686_Cygwin    : {}-              | I686_Linux     : {}-              | MIPS64el_Linux : {}-              | PowerPC_Linux  : {}-              | X86_64_Cygwin  : {}-              | X86_64_Darwin  : {}-              | X86_64_FreeBSD : {}-              | X86_64_Linux   : {}-              | X86_64_Solaris : {}-              >-          , speedFactor       : Natural-          , supportedFeatures : List Text-          , user              : Optional Text-          }-        )-    → λ(y : Text)-    →     (     Optional/fold-                Text-                x.user-                Text-                (λ(user : Text) → user ++ "@" ++ x.host ++ "")-                x.host-            ++  " "-            ++  ( merge-                  { Empty    = λ(_ : {}) → ""-                  , NonEmpty = λ(result : Text) → result-                  }-                  ( List/fold-                    < AArch64_Linux  : {}-                    | ARMv5tel_Linux : {}-                    | ARMv7l_Linux   : {}-                    | I686_Cygwin    : {}-                    | I686_Linux     : {}-                    | MIPS64el_Linux : {}-                    | PowerPC_Linux  : {}-                    | X86_64_Cygwin  : {}-                    | X86_64_Darwin  : {}-                    | X86_64_FreeBSD : {}-                    | X86_64_Linux   : {}-                    | X86_64_Solaris : {}-                    >-                    x.platforms-                    < Empty : {} | NonEmpty : Text >-                    (   λ ( element-                          : < AArch64_Linux  : {}-                            | ARMv5tel_Linux : {}-                            | ARMv7l_Linux   : {}-                            | I686_Cygwin    : {}-                            | I686_Linux     : {}-                            | MIPS64el_Linux : {}-                            | PowerPC_Linux  : {}-                            | X86_64_Cygwin  : {}-                            | X86_64_Darwin  : {}-                            | X86_64_FreeBSD : {}-                            | X86_64_Linux   : {}-                            | X86_64_Solaris : {}-                            >-                          )-                      → λ(status : < Empty : {} | NonEmpty : Text >)-                      → merge-                        { Empty    =-                              λ(_ : {})-                            → < NonEmpty =-                                  merge-                                  { AArch64_Linux  = λ(_ : {}) → "aarch64-linux"-                                  , ARMv5tel_Linux =-                                      λ(_ : {}) → "armv5tel-linux"-                                  , ARMv7l_Linux   = λ(_ : {}) → "armv7l-linux"-                                  , I686_Cygwin    = λ(_ : {}) → "i686-cygwin"-                                  , I686_Linux     = λ(_ : {}) → "i686-linux"-                                  , MIPS64el_Linux =-                                      λ(_ : {}) → "mips64el-linux"-                                  , PowerPC_Linux  = λ(_ : {}) → "powerpc-linux"-                                  , X86_64_Cygwin  = λ(_ : {}) → "x86_64-cygwin"-                                  , X86_64_Darwin  = λ(_ : {}) → "x86_64-darwin"-                                  , X86_64_FreeBSD =-                                      λ(_ : {}) → "x86_64-freebsd"-                                  , X86_64_Linux   = λ(_ : {}) → "x86_64-linux"-                                  , X86_64_Solaris =-                                      λ(_ : {}) → "x86_64-solaris"-                                  }-                                  element-                              | Empty    : {}-                              >-                        , NonEmpty =-                              λ(result : Text)-                            → < NonEmpty =-                                      ( merge-                                        { AArch64_Linux  =-                                            λ(_ : {}) → "aarch64-linux"-                                        , ARMv5tel_Linux =-                                            λ(_ : {}) → "armv5tel-linux"-                                        , ARMv7l_Linux   =-                                            λ(_ : {}) → "armv7l-linux"-                                        , I686_Cygwin    =-                                            λ(_ : {}) → "i686-cygwin"-                                        , I686_Linux     =-                                            λ(_ : {}) → "i686-linux"-                                        , MIPS64el_Linux =-                                            λ(_ : {}) → "mips64el-linux"-                                        , PowerPC_Linux  =-                                            λ(_ : {}) → "powerpc-linux"-                                        , X86_64_Cygwin  =-                                            λ(_ : {}) → "x86_64-cygwin"-                                        , X86_64_Darwin  =-                                            λ(_ : {}) → "x86_64-darwin"-                                        , X86_64_FreeBSD =-                                            λ(_ : {}) → "x86_64-freebsd"-                                        , X86_64_Linux   =-                                            λ(_ : {}) → "x86_64-linux"-                                        , X86_64_Solaris =-                                            λ(_ : {}) → "x86_64-solaris"-                                        }-                                        element-                                      )-                                  ++  ","-                                  ++  result-                              | Empty    : {}-                              >-                        }-                        status-                        : < Empty : {} | NonEmpty : Text >-                    )-                    < Empty = {=} | NonEmpty : Text >-                  )-                  : Text-                )-            ++  " "-            ++  x.key-            ++  " "-            ++  Integer/show (Natural/toInteger x.cores)-            ++  " "-            ++  Integer/show (Natural/toInteger x.speedFactor)-            ++  " "-            ++  ( merge-                  { Empty    = λ(_ : {}) → ""-                  , NonEmpty = λ(result : Text) → result-                  }-                  ( List/fold-                    Text-                    x.supportedFeatures-                    < Empty : {} | NonEmpty : Text >-                    (   λ(element : Text)-                      → λ(status : < Empty : {} | NonEmpty : Text >)-                      → merge-                        { Empty    =-                            λ(_ : {}) → < NonEmpty = element | Empty : {} >-                        , NonEmpty =-                              λ(result : Text)-                            → < NonEmpty = element ++ "," ++ result-                              | Empty    : {}-                              >-                        }-                        status-                        : < Empty : {} | NonEmpty : Text >-                    )-                    < Empty = {=} | NonEmpty : Text >-                  )-                  : Text-                )-            ++  " "-            ++  ( merge-                  { Empty    = λ(_ : {}) → ""-                  , NonEmpty = λ(result : Text) → result-                  }-                  ( List/fold-                    Text-                    x.mandatoryFeatures-                    < Empty : {} | NonEmpty : Text >-                    (   λ(element : Text)-                      → λ(status : < Empty : {} | NonEmpty : Text >)-                      → merge-                        { Empty    =-                            λ(_ : {}) → < NonEmpty = element | Empty : {} >-                        , NonEmpty =-                              λ(result : Text)-                            → < NonEmpty = element ++ "," ++ result-                              | Empty    : {}-                              >-                        }-                        status-                        : < Empty : {} | NonEmpty : Text >-                    )-                    < Empty = {=} | NonEmpty : Text >-                  )-                  : Text-                )-            ++  "\n"-          )-      ++  y-  )-  ""
− tests/parser/let.dhall
@@ -1,3 +0,0 @@-    let x = 1-in  let y : Integer = 2-in  x
− tests/parser/lineComment.dhall
@@ -1,3 +0,0 @@--- foo--1
− tests/parser/list.dhall
@@ -1,4 +0,0 @@-[ [1, 2, 3]-, [1, 2, 3] : List Integer-, [] : List Integer-]
− tests/parser/merge.dhall
@@ -1,7 +0,0 @@-  λ(x : <>)-→ { bar = merge {=} x : Integer-  , foo =-      merge-      { Left = λ(b : Bool) → b, Right = Natural/even }-      < Left = True | Right : Natural >-  }
− tests/parser/natural.dhall
@@ -1,1 +0,0 @@-[ +0, +1, +01, +10 ]
− tests/parser/nestedBlockComment.dhall
@@ -1,3 +0,0 @@-{- foo {- bar -} baz -}--1
− tests/parser/operators.dhall
@@ -1,2 +0,0 @@-  { foo = (False && Natural/even (+1 + +2 * +3)) || True == False != True }-∧ { bar = [ "ABC" ++ "DEF" ] # [ "GHI" ] } ⫽ { baz = True }
− tests/parser/pathTermination.dhall
@@ -1,3 +0,0 @@--- Verify that certain punctuation marks terminate paths correctly-  λ(x : ./example)-→ ./example[./example, ./example{bar = ./example<baz = ./example>, qux = ./example}, ./example]
− tests/parser/paths.dhall
@@ -1,5 +0,0 @@-[ /absolute/path-, ./relative/path-, ~/home/anchored/path-, /ipfs/QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx/Prelude-]
− tests/parser/quotedLabel.dhall
@@ -1,1 +0,0 @@-{ example1 = let `let` = 1 in `let`, example2 = let `:.` = 1 in `:.` }
− tests/parser/record.dhall
@@ -1,4 +0,0 @@-{ foo = 1-, bar = +2-, baz = True-} : { foo : Integer, bar : Natural, baz : Bool }
− tests/parser/reservedPrefix.dhall
@@ -1,1 +0,0 @@-let TypeSynonym = Integer in 1 : TypeSynonym
− tests/parser/singleQuotedString.dhall
@@ -1,4 +0,0 @@-''-ABC-DEF-''
− tests/parser/unicodeComment.dhall
@@ -1,3 +0,0 @@-{- ∀(a : Type) → a -}--1
− tests/parser/unicodeDoubleQuotedString.dhall
@@ -1,1 +0,0 @@-"∀(a : Type) → a"
− tests/parser/union.dhall
@@ -1,4 +0,0 @@-< A : {   }-| B = { = }-| C : {}-> : < A : {} | B : {} | C : {} >
− tests/parser/urls.dhall
@@ -1,11 +0,0 @@-[ http://example.com-, https://john:doe@example.com:8080/foo/bar?qux=0#xyzzy-, http://prelude.dhall-lang.org/-, https://ipfs.io/ipfs/QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx/Prelude-, https://127.0.0.1-, https://[::]-, https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]--  -- Yes, this is legal-, https://-._~%2C!$&'()*+,;=:@-._~%2C!$&'()*+,;=:/-._~%2C!$&'()*+,;=:@?/-._~%2C!$&'()*+,;=:@/?#/-._~%2C!$&'()*+,;=:@/?-]
− tests/parser/whitespace.dhall
@@ -1,3 +0,0 @@--1-
− tests/parser/whitespaceBuffet.dhall
@@ -1,9 +0,0 @@-    -- This-
-     Natural/even {--
-{- file--}
-  has-
- -}  +2 -- mixed {- line endings -}
+ tests/recursive/expr0.dhall view
@@ -0,0 +1,17 @@+  λ(Expr : Type)+→ let ExprF =+        < LitF : Natural+        | AddF : { _1 : Expr, _2 : Expr }+        | MulF : { _1 : Expr, _2 : Expr }+        >++  in    λ(Fix : ExprF → Expr)+      → let Lit = λ(x : Natural) → Fix (ExprF.LitF x)++        let Add =+              λ(x : Expr) → λ(y : Expr) → Fix (ExprF.AddF { _1 = x, _2 = y })++        let Mul =+              λ(x : Expr) → λ(y : Expr) → Fix (ExprF.MulF { _1 = x, _2 = y })++        in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))
+ tests/recursive/expr1.dhall view
@@ -0,0 +1,15 @@+  λ(a : Type)+→ let ExprF =+        < LitF : Natural+        | AddF : { _1 : a, _2 : a }+        | MulF : { _1 : a, _2 : a }+        >++  in    λ(a : ExprF → a)+      → let Lit = λ(x : Natural) → a (ExprF.LitF x)++        let Add = λ(x : a@1) → λ(y : a@1) → a (ExprF.AddF { _1 = x, _2 = y })++        let Mul = λ(x : a@1) → λ(y : a@1) → a (ExprF.MulF { _1 = x, _2 = y })++        in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))
tests/regression/issue151a.dhall view
@@ -1,1 +1,1 @@-let foo : (\(x : A) -> x x) (\(x : A) -> x x) = 1 in foo+\(A : Type) -> let foo : (\(x : A) -> x x) (\(x : A) -> x x) = 1 in foo
tests/regression/issue151b.dhall view
@@ -1,1 +1,1 @@-\(omega : ((\(x : A) -> x x) (\(x : A) -> x x))) -> omega 1+\(A : Type) -> \(omega : ((\(x : A) -> x x) (\(x : A) -> x x))) -> omega 1
+ tests/regression/issue1584.dhall view
@@ -0,0 +1,19 @@+[ let ifX = 1 in ifX+, let thenX = 1 in thenX+, let elseX = 1 in elseX+, let letX = 1 in letX+, let inX = 1 in inX+, let usingX = 1 in usingX+{- Fixing this case appears to be difficult for the current parser+   implementation+-}+-- , let missingX = 1 in missingX+, let asX = 1 in asX+, let InfinityX = 1 in InfinityX+, let NaNX = 1 in NaNX+, let mergeX = 1 in mergeX+, let SomeX = 1 in SomeX+, let toMapX = 1 in toMapX+, let assertX = 1 in assertX+, let forallX = 1 in forallX+]
tests/regression/issue164.dhall view
@@ -1,1 +1,2 @@-''Single quotes like ' should be allowed in a single-quoted string''+''+Single quotes like ' should be allowed in a single-quoted string''
+ tests/regression/issue1646.dhall view
@@ -0,0 +1,1 @@+let f = \(d : Double) -> \(i : Integer) -> {=} in f 3.1 -1
+ tests/regression/issue1732.dhall view
@@ -0,0 +1,1 @@+let x = 0 in { x , a = 0 }
+ tests/regression/issue1884.dhall view
@@ -0,0 +1,4 @@+let Make = \(T: Type) -> { Type = { a: T },  default = {=} }++in+(Make Natural) with default = { a = 2 }
+ tests/regression/issue2088.dhall view
@@ -0,0 +1,1 @@+[ { x = 1 }.{ x }, { x = 1 } ]
− tests/regression/issue209.dhall
@@ -1,1 +0,0 @@-constructors <>
tests/regression/issue216a.dhall view
@@ -1,5 +1,5 @@ let GitHubProject : Type = { owner : Text, repo : Text } in let gitHubProject = \( github : GitHubProject ) ->      let gitHubRoot = "https://github.com/${github.owner}/${github.repo}"-	 in { bugReports = "${gitHubRoot}/issues"  }+     in  { bugReports = "${gitHubRoot}/issues"  } in gitHubProject
tests/regression/issue216b.dhall view
@@ -1,10 +1,2 @@-    let GitHubProject : Type = { owner : Text, repo : Text }--in  let gitHubProject =-            λ(github : GitHubProject)-          →     let gitHubRoot =-                      "https://github.com/${github.owner}/${github.repo}"-            -            in  { bugReports = "${gitHubRoot}/issues" }--in  gitHubProject+λ(github : { owner : Text, repo : Text }) →+  { bugReports = "https://github.com/${github.owner}/${github.repo}/issues" }
+ tests/schemas/multipleA.dhall view
@@ -0,0 +1,1 @@+{=}
+ tests/schemas/multipleB.dhall view
@@ -0,0 +1,1 @@+let schemas = ./tests/schemas/multipleSchema.dhall in schemas.B::{=}
+ tests/schemas/multipleSchema.dhall view
@@ -0,0 +1,3 @@+{ A = { Type = {}, default = {=} }+, B = { Type = {}, default = {=} }+}
+ tests/schemas/personA.dhall view
@@ -0,0 +1,4 @@+{ addr = { city = None Text, country = "Switzerland" }+, alive = True+, name = "Alice"+}
+ tests/schemas/personB.dhall view
@@ -0,0 +1,6 @@+let schemas = ./tests/schemas/personSchema.dhall++in  schemas.Person::{+    , addr = schemas.Address::{ country = "Switzerland" }+    , name = "Alice"+    }
+ tests/schemas/personSchema.dhall view
@@ -0,0 +1,11 @@+let Address =+      { Type = { country : Text, city : Optional Text }+      , default.city = None Text+      }++let Person =+      { Type = { name : Text, addr : Address.Type, alive : Bool }+      , default.alive = True+      }++in  { Person, Address }
+ tests/tags/all.tags view
@@ -0,0 +1,61 @@++./tests/tags/let.dhall,66+let.dhall1,1+/let.dhall1,1+let foo foo1,5+let bar bar3,22++./tests/tags/nonunicode.dhall,63+nonunicode.dhall1,1+/nonunicode.dhall1,1+let foo foo2,12++./tests/tags/record.dhall,335+record.dhall1,1+/record.dhall1,1+let Config Config6,81+      { home home8,161+      , privateKey privateKey9,181+      , publicKey publicKey10,207+      , name name11,232+      , name : { firstName firstName11,241+               , secondName secondName12,275+let makeUser makeUser16,323+let configs configs30,804++./tests/tags/recordlit.dhall,223+recordlit.dhall1,1+/recordlit.dhall1,1+{ home home8,143+, privateKey privateKey9,171+, publicKey publicKey10,215+, name name11,263+, name = { firstName firstName11,272+         , secondName secondName12,302++./tests/tags/simple.dhall,254+simple.dhall1,1+/simple.dhall1,1+let generate generate6,100+let makeUser makeUser17,409+let buildUser buildUser26,680+let Config Config32,880+      { home home33,897+      , privateKey privateKey34,917+      , publicKey publicKey35,943++./tests/tags/unicode.dhall,57+unicode.dhall1,1+/unicode.dhall1,1+let foo foo2,15++./tests/tags/union.dhall,394+union.dhall1,1+/union.dhall1,1+let Element Element1,5+let Element = < Left Left1,17+let Element = < Left : Natural | Right Right1,34+let Element = < Left : Natural | Right : Bool | Middle Middle1,49+let Element = < Left : Natural | Right : Bool | Middle : < Top Top1,60+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom Bottom1,73+let foo foo3,95
+ tests/tags/let.dhall view
@@ -0,0 +1,4 @@+let foo = "foo"++let bar = foo+in bar
+ tests/tags/let.tags view
@@ -0,0 +1,6 @@++./tests/tags/let.dhall,66+let.dhall1,1+/let.dhall1,1+let foo foo1,5+let bar bar3,22
+ tests/tags/nonunicode.dhall view
@@ -0,0 +1,3 @@+-- abc+let foo = "bar"+in foo
+ tests/tags/nonunicode.tags view
@@ -0,0 +1,5 @@++./tests/tags/nonunicode.dhall,63+nonunicode.dhall1,1+/nonunicode.dhall1,1+let foo foo2,12
+ tests/tags/record.dhall view
@@ -0,0 +1,35 @@+{- You can optionally add types++   `x : T` means that `x` has type `T`+-}++let Config : Type =+      {- What happens if you add another field here? -}+      { home : Text+      , privateKey : Text+      , publicKey : Text+      , name : { firstName : Text+               , secondName : 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       = home+            , privateKey = privateKey+            , publicKey  = publicKey+            , name = { firstName = user+                     , secondName = ""+                     }+            }+      in  config++let configs : List Config =+      [ makeUser "bill"+      , makeUser "jane"+      ]++in  configs
+ tests/tags/record.tags view
@@ -0,0 +1,13 @@++./tests/tags/record.dhall,335+record.dhall1,1+/record.dhall1,1+let Config Config6,81+      { home home8,161+      , privateKey privateKey9,181+      , publicKey publicKey10,207+      , name name11,232+      , name : { firstName firstName11,241+               , secondName secondName12,275+let makeUser makeUser16,323+let configs configs30,804
+ tests/tags/recordlit.dhall view
@@ -0,0 +1,14 @@+{- This is an example Dhall configuration file++   Can you spot the mistake?++   Fix the typo, then move onto the "Definitions" example+-}++{ home       = "/home/bill"+, privateKey = "/home/bill/.ssh/id_ed25519"+, publicKey  = "/home/blil/.ssh/id_ed25519.pub"+, name = { firstName = "Bill"+         , secondName = "Bar"+         }+}
+ tests/tags/recordlit.tags view
@@ -0,0 +1,10 @@++./tests/tags/recordlit.dhall,223+recordlit.dhall1,1+/recordlit.dhall1,1+{ home home8,143+, privateKey privateKey9,171+, publicKey publicKey10,215+, name name11,263+, name = { firstName firstName11,272+         , secondName secondName12,302
+ tests/tags/simple.dhall view
@@ -0,0 +1,39 @@+{- Need to generate a lot of users?++   Use the `generate` function from the Dhall Prelude+-}++let generate = https://prelude.dhall-lang.org/List/generate++{- You can import Dhall expressions from URLs that support+   CORS++   The command-line tools also let you import from files,+   environment variables, and URLs without CORS support.++   Browse https://prelude.dhall-lang.org for more utilities+-}++let makeUser = \(user : Text) ->+      let home       = "/home/${user}"+      let privateKey = "${home}/.ssh/id_ed25519"+      let publicKey  = "${privateKey}.pub"+      in  { home = home+          , privateKey = privateKey+          , publicKey = publicKey+          }++let buildUser = \(index : Natural) ->+      {- `Natural/show` is a "built-in", meaning that+         you can use `Natural/show` without an import+      -}+      makeUser "build${Natural/show index}"++let Config =+      { home : Text+      , privateKey : Text+      , publicKey : Text+      }++in  {- Try generating 20 users instead of 10 -}+    generate 10 Config buildUser
+ tests/tags/simple.tags view
@@ -0,0 +1,11 @@++./tests/tags/simple.dhall,254+simple.dhall1,1+/simple.dhall1,1+let generate generate6,100+let makeUser makeUser17,409+let buildUser buildUser26,680+let Config Config32,880+      { home home33,897+      , privateKey privateKey34,917+      , publicKey publicKey35,943
+ tests/tags/unicode.dhall view
@@ -0,0 +1,3 @@+-- αβξ+let foo = "bar"+in foo
+ tests/tags/unicode.tags view
@@ -0,0 +1,5 @@++./tests/tags/unicode.dhall,57+unicode.dhall1,1+/unicode.dhall1,1+let foo foo2,15
+ tests/tags/union.dhall view
@@ -0,0 +1,4 @@+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom : Bool> >++let foo = Element.Left 6+in foo
+ tests/tags/union.tags view
@@ -0,0 +1,11 @@++./tests/tags/union.dhall,394+union.dhall1,1+/union.dhall1,1+let Element Element1,5+let Element = < Left Left1,17+let Element = < Left : Natural | Right Right1,34+let Element = < Left : Natural | Right : Bool | Middle Middle1,49+let Element = < Left : Natural | Right : Bool | Middle : < Top Top1,60+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom Bottom1,73+let foo foo3,95
+ tests/th/Department.dhall view
@@ -0,0 +1,1 @@+< Sales | Engineering | Marketing >
+ tests/th/Employee.dhall view
@@ -0,0 +1,1 @@+{ name : Text, department : ./Department.dhall }
+ tests/th/HigherKindSingle.dhall view
@@ -0,0 +1,1 @@+\(a : Type -> Type) -> \(a : Type) -> { foo : a, bar : a@1 a, bam : Text }
+ tests/th/HigherKindUnion.dhall view
@@ -0,0 +1,1 @@+\(a : Type) -> \(b : Type) -> < Foo : a | Bar : b >
+ tests/th/Time.dhall view
@@ -0,0 +1,1 @@+{ txTime : Time, txDate : Date, txTimeZone : TimeZone }
+ tests/th/example.dhall view
@@ -0,0 +1,1 @@+< A : { x : Bool, y : List Text } | B : Optional (List Natural) | C >
+ tests/th/issue2066.dhall view
@@ -0,0 +1,7 @@+let Bar = { baz : Integer }++let Foo = { foo : Integer, bar : Bar }++let Qux = < Foo : Foo | Bar : Bar >++in  { Foo, Bar, Qux }
+ tests/to-directory-tree/fixpoint-allow-path-separators.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "non-existent-1/file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      , make.directory+          { name = "non-existent-2/directory"+          , content = [] : List r+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/fixpoint-empty.dhall view
@@ -0,0 +1,3 @@+let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) -> \(make : Make r) -> [] : List r
+ tests/to-directory-tree/fixpoint-helper.dhall view
@@ -0,0 +1,30 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+      { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+      { user : Optional Access+      , group : Optional Access+      , other : Optional Access+      }++let Entry =+      \(content : Type) ->+        { name : Text+        , content : content+        , user : Optional User+        , group : Optional Group+        , mode : Optional Mode+        }++let Make =+      \(r : Type) ->+        { directory : Entry (List r) -> r+        , binary-file : Entry Bytes -> r+        , file : Entry Text -> r+        }++in  { User, Group, Access, Mode, Entry, Make }
+ tests/to-directory-tree/fixpoint-permissions.dhall view
@@ -0,0 +1,24 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Make = (./fixpoint-helper.dhall).Make++let no-access = { execute = Some False, read = Some False, write = Some False }++let full-access = { execute = Some True, read = Some True, write = Some True }++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = Some+            { user = Some full-access+            , group = Some no-access+            , other = Some no-access+            }+          }+      ]
+ tests/to-directory-tree/fixpoint-simple.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      , make.directory+          { name = "directory"+          , content = [] : List r+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/fixpoint-usergroup.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "ids"+          , content = ""+          , user = Some (User.UserId 0)+          , group = Some (Group.GroupId 0)+          , mode = None Mode+          }+      , make.file+          { name = "names"+          , content = ""+          , user = Some (User.UserName "user")+          , group = Some (Group.GroupName "group")+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/type.dhall view
@@ -0,0 +1,36 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+      { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+      { user : Optional Access+      , group : Optional Access+      , other : Optional Access+      }++let Entry =+      \(content : Type) ->+        { name : Text+        , content : content+        , user : Optional User+        , group : Optional Group+        , mode : Optional Mode+        }++in  forall (result : Type) ->+      let DirectoryEntry = Entry (List result)++      let BinaryFileEntry = Entry Bytes++      let TextFileEntry = Entry Text++      let Make =+            { directory : DirectoryEntry -> result+            , binary-file : BinaryFileEntry -> result+            , file : TextFileEntry -> result+            }++      in  forall (make : Make) -> List result
+ tests/tutorial/Union.dhall view
@@ -0,0 +1,1 @@+< Left : Natural | Right : Bool>
+ tests/tutorial/substitution1.dhall view
@@ -0,0 +1,1 @@+Result.Failure +1
+ tests/tutorial/substitution2.dhall view
@@ -0,0 +1,1 @@+./substitution1.dhall
+ tests/tutorial/substitution3.dhall view
@@ -0,0 +1,1 @@+Foo
tests/tutorial/unions0A.dhall view
@@ -1,1 +1,1 @@-./process.dhall < Left = +3 | Right : Bool >+./process.dhall ((./Union.dhall).Left 3)
tests/tutorial/unions1A.dhall view
@@ -1,1 +1,1 @@-./process.dhall < Right = True | Left : Natural >+./process.dhall ((./Union.dhall).Right True)
− tests/tutorial/unions2A.dhall
@@ -1,8 +0,0 @@-    let Empty  = < Empty = {=} | Person : { name : Text, age : Natural } >-in  let Person =-        λ(p : { name : Text, age : Natural }) → < Person = p | Empty : {} >-in  [   Empty-    ,   Person { name = "John", age = +23 }-    ,   Person { name = "Amy" , age = +25 }-    ,   Empty-    ]
− tests/tutorial/unions2B.dhall
@@ -1,5 +0,0 @@-[ < Empty = {=} | Person : { age : Natural, name : Text } >-, < Person = { age = +23, name = "John" } | Empty : {} >-, < Person = { age = +25, name = "Amy" } | Empty : {} >-, < Empty = {=} | Person : { age : Natural, name : Text } >-]
tests/tutorial/unions3A.dhall view
@@ -1,5 +1,6 @@-    let MyType = constructors < Empty : {} | Person : { name : Text, age : Natural } >-in  [   MyType.Empty {=}-    ,   MyType.Person { name = "John", age = +23 }-    ,   MyType.Person { name = "Amy" , age = +25 }+let MyType = < Empty | Person : { name : Text, age : Natural } >++in  [   MyType.Empty  -- Note the absence of any argument to `Empty`+    ,   MyType.Person { name = "John", age = 23 }+    ,   MyType.Person { name = "Amy" , age = 25 }     ]
tests/tutorial/unions3B.dhall view
@@ -1,4 +1,6 @@-[ < Empty = {=} | Person : { age : Natural, name : Text } >-, < Person = { age = +23, name = "John" } | Empty : {} >-, < Person = { age = +25, name = "Amy" } | Empty : {} >+[ < Empty | Person : { age : Natural, name : Text } >.Empty+, < Empty | Person : { age : Natural, name : Text } >.Person+  { age = 23, name = "John" }+, < Empty | Person : { age : Natural, name : Text } >.Person+  { age = 25, name = "Amy" } ]
tests/tutorial/unions4A.dhall view
@@ -1,1 +1,1 @@-constructors < Empty : {} | Person : { name : Text, age : Natural } >+< Empty : {} | Person : { name : Text, age : Natural } >
tests/tutorial/unions4B.dhall view
@@ -1,6 +1,1 @@-{ Empty  =-    λ(Empty : {}) → < Empty = Empty | Person : { age : Natural, name : Text } >-, Person =-      λ(Person : { age : Natural, name : Text })-    → < Person = Person | Empty : {} >-}+< Empty : {} | Person : { name : Text, age : Natural } >
− tests/typecheck/alternativesAreTypesA.dhall
@@ -1,1 +0,0 @@-< Left = List | Right : Type >
− tests/typecheck/alternativesAreTypesB.dhall
@@ -1,1 +0,0 @@-< Left : Type → Type | Right : Type >
− tests/typecheck/anonymousFunctionsInTypesA.dhall
@@ -1,5 +0,0 @@-    let anonymousFunction = λ(a : Type) → List a--in    λ(HigherOrderType : (Type → Type) → Type)-    → λ(x : HigherOrderType anonymousFunction)-    → (x : HigherOrderType anonymousFunction)
− tests/typecheck/anonymousFunctionsInTypesB.dhall
@@ -1,4 +0,0 @@-  ∀(HigherOrderType : (Type → Type) → Type)-→ ∀(x : HigherOrderType (λ(a : Type) → List a))-→ HigherOrderType (λ(a : Type) → List a)-
− tests/typecheck/examples/Monoid/00A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Bool/and
− tests/typecheck/examples/Monoid/00B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Bool
− tests/typecheck/examples/Monoid/01A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Bool/or
− tests/typecheck/examples/Monoid/01B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Bool
− tests/typecheck/examples/Monoid/02A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Bool/even
− tests/typecheck/examples/Monoid/02B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Bool
− tests/typecheck/examples/Monoid/03A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Bool/odd
− tests/typecheck/examples/Monoid/03B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Bool
− tests/typecheck/examples/Monoid/04A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/List/concat
− tests/typecheck/examples/Monoid/04B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../Prelude/Monoid (List a)
− tests/typecheck/examples/Monoid/05A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/List/shifted
− tests/typecheck/examples/Monoid/05B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../Prelude/Monoid (List { index : Natural, value : a })
− tests/typecheck/examples/Monoid/06A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Natural/sum
− tests/typecheck/examples/Monoid/06B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Natural
− tests/typecheck/examples/Monoid/07A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Natural/product
− tests/typecheck/examples/Monoid/07B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Natural
− tests/typecheck/examples/Monoid/08A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Optional/head
− tests/typecheck/examples/Monoid/08B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../Prelude/Monoid (Optional a)
− tests/typecheck/examples/Monoid/09A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Optional/last
− tests/typecheck/examples/Monoid/09B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../Prelude/Monoid (Optional a)
− tests/typecheck/examples/Monoid/10A.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Text/concat
− tests/typecheck/examples/Monoid/10B.dhall
@@ -1,1 +0,0 @@-../../../../Prelude/Monoid Text
− tests/typecheck/fieldsAreTypesA.dhall
@@ -1,1 +0,0 @@-{ x = Bool, y = List }
− tests/typecheck/fieldsAreTypesB.dhall
@@ -1,1 +0,0 @@-{ x : Type, y : Type → Type }