packages feed

dhall 1.32.0 → 1.42.3

raw patch · 1434 files changed

Files

CHANGELOG.md view
@@ -1,3 +1,426 @@+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)@@ -11,8 +434,6 @@         * For example, `< A : Bool | B : Type >` is legal now         * 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 }` * 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@@ -711,7 +1132,7 @@     * 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 +* 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@@ -1094,7 +1515,7 @@       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 +      features     * This also includes a breaking change to `ImportType` in the API * BREAKING CHANGE TO THE LANGUAGE: Disallow combining records of terms and   types
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2020 Gabriel Gonzalez+Copyright (c) 2020 Gabriella Gonzalez All rights reserved.  Redistribution and use in source and binary forms, with or without
benchmark/deep-nested-large-record/Main.hs view
@@ -1,13 +1,13 @@ {-# LANGUAGE OverloadedStrings #-} module Main (main) where -import Gauge(defaultMain)+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 Data.Sequence   as Seq+import qualified Dhall.Core      as Core+import qualified Dhall.Import    as Import import qualified Dhall.TypeCheck as TypeCheck-import qualified Gauge  dhallPreludeImport :: Core.Import dhallPreludeImport = Core.Import@@ -21,17 +21,20 @@     }   } -issue412 :: Core.Expr s TypeCheck.X -> Gauge.Benchmarkable-issue412 prelude = Gauge.whnf TypeCheck.typeOf expr+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"+      $ 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 TypeCheck.X -> Gauge.Benchmarkable-unionPerformance prelude = Gauge.whnf TypeCheck.typeOf expr+unionPerformance :: Core.Expr s Void -> Benchmarkable+unionPerformance prelude = whnf TypeCheck.typeOf expr   where     expr =         Core.Let@@ -48,17 +51,22 @@                         Nothing                         Nothing                         Nothing-                        (prelude `Core.Field` "types" `Core.Field` "Big")+                        (prelude `Core.Field` types `Core.Field` big)                     )-                    (Core.Prefer Core.PreferFromSource "big" "big")+                    (Core.Prefer mempty Core.PreferFromSource "big" "big")                 )             )             "x"+    types = Core.makeFieldSelection "types"+    big = Core.makeFieldSelection "Big"  main :: IO ()-main = do-  prelude <- Import.load (Core.Embed dhallPreludeImport)+main =   defaultMain-    [ Gauge.bench "issue 412" (issue412 prelude)-    , Gauge.bench "union performance" (unionPerformance prelude)+    [ env prelude $ \p ->+      bgroup "Prelude"+        [ bench "issue 412" (issue412 p)+        , bench "union performance" (unionPerformance p)+        ]     ]+  where prelude = Import.load (Core.Embed dhallPreludeImport)
− benchmark/examples/issue108.dhall
@@ -1,62 +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 : 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/examples/normalize/ChurchEval.dhall
@@ -1,22 +0,0 @@--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/examples/normalize/FunCompose.dhall
@@ -1,18 +0,0 @@--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/examples/normalize/ListBench.dhall
@@ -1,75 +0,0 @@--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/examples/normalize/ListBenchAlt.dhall
@@ -1,45 +0,0 @@--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)))
benchmark/parser/Main.hs view
@@ -1,99 +1,91 @@-{-# LANGUAGE CPP               #-}+{-# LANGUAGE BangPatterns      #-} {-# LANGUAGE OverloadedStrings #-}  module Main where -import Control.Monad (forM)-import Data.Map (Map, foldrWithKey, singleton, unions)-import Data.Monoid ((<>))-import Data.Void (Void)-import Gauge (defaultMain, bgroup, bench, nf, whnf, nfIO)--import System.Directory+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 Codec.Serialise-import qualified Gauge import qualified Data.ByteString.Lazy-import qualified Data.Text as T-import qualified Data.Text.IO as TIO+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--#if MIN_VERSION_directory(1,2,3)-#else-import Control.Exception (bracket)--withCurrentDirectory :: FilePath  -- ^ Directory to execute in-                     -> IO a      -- ^ Action to be executed-                     -> IO a-withCurrentDirectory dir action =-  bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do-    setCurrentDirectory dir-    action--listDirectory :: FilePath -> IO [FilePath]-listDirectory path = filter f <$> getDirectoryContents path-  where f filename = filename /= "." && filename /= ".."-#endif+import qualified Dhall.Core           as Dhall+import qualified Dhall.Parser         as Dhall+import qualified System.Directory     as Directory -type PreludeFiles = Map FilePath T.Text+type PreludeFiles = Map FilePath Text  loadPreludeFiles :: IO PreludeFiles loadPreludeFiles = loadDirectory "./dhall-lang/Prelude"     where         loadDirectory :: FilePath -> IO PreludeFiles         loadDirectory dir =-            withCurrentDirectory dir $ do-                files <- getCurrentDirectory >>= listDirectory+            Directory.withCurrentDirectory dir $ do+                files <- Directory.getCurrentDirectory >>= Directory.listDirectory                 results <- forM files $ \file -> do-                    file' <- makeAbsolute file-                    doesExist <- doesFileExist file'+                    file' <- Directory.makeAbsolute file+                    doesExist <- Directory.doesFileExist file'                     if doesExist                        then loadFile file'                        else loadDirectory file'-                pure $ unions results+                pure $ Map.unions results          loadFile :: FilePath -> IO PreludeFiles-        loadFile path = singleton path <$> TIO.readFile path+        loadFile path = Map.singleton path <$> Data.Text.IO.readFile path -benchParser :: PreludeFiles -> Gauge.Benchmark+benchParser :: PreludeFiles -> Benchmark benchParser =       bgroup "exprFromText"-    . foldrWithKey (\name expr -> (benchExprFromText name expr :)) []+    . Map.foldrWithKey (\name expr -> (benchExprFromText name expr :)) [] -benchExprFromText :: String -> T.Text -> Gauge.Benchmark-benchExprFromText name expr =+benchExprFromText :: String -> Text -> Benchmark+benchExprFromText name !expr =     bench name $ whnf (Dhall.exprFromText "(input)") expr -benchExprFromBytes-    :: String -> Data.ByteString.Lazy.ByteString -> Gauge.Benchmark-benchExprFromBytes name bytes = bench name (nf f bytes)+benchExprFromBytes :: String -> Data.ByteString.Lazy.ByteString -> Benchmark+benchExprFromBytes name bs = bench name (nf f bs)   where-    f bytes = do+    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-    issue108Text  <- TIO.readFile "benchmark/examples/issue108.dhall"-    issue108Bytes <- Data.ByteString.Lazy.readFile "benchmark/examples/issue108.dhall.bin"-    kubernetesExample <- Data.ByteString.Lazy.readFile "benchmark/examples/kubernetes.dhall.bin"     defaultMain-        [ bgroup "Issue #108"-            [ benchExprFromText  "Text"   issue108Text-            , benchExprFromBytes "Binary" issue108Bytes-            ]-        , benchExprFromBytes "Kubernetes/Binary" kubernetesExample-        , benchExprFromText "Long variable names" (T.replicate 1000000 "x")-        , benchExprFromText "Large number of function arguments" (T.replicate 10000 "x ")-        , benchExprFromText "Long double-quoted strings" ("\"" <> T.replicate 1000000 "x" <> "\"")-        , benchExprFromText "Long single-quoted strings" ("''" <> T.replicate 1000000 "x" <> "''")-        , benchExprFromText "Whitespace" (T.replicate 1000000 " " <> "x")-        , benchExprFromText "Line comment" ("x -- " <> T.replicate 1000000 " ")-        , benchExprFromText "Block comment" ("x {- " <> T.replicate 1000000 " " <> "-}")+        [ 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-lang/Prelude/Bool/and view
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,18 +1,3 @@-{--`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+  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
@@ -1,20 +1,3 @@-{--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+  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
@@ -1,16 +1,3 @@-{--`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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,20 +1,3 @@-{--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,25 +1,37 @@ { and =-      ./and sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d-    ? ./and+      missing+        sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d+    ? ./and.dhall , build =-      ./build sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b-    ? ./build+      missing+        sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b+    ? ./build.dhall+, equal =+      missing+        sha256:f0dc047ca14644c2a979bb126f2a3c6659ec770c66bd7beb70ae4a9d05815709+    ? ./equal.dhall , even =-      ./even sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5-    ? ./even+      missing+        sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5+    ? ./even.dhall , fold =-      ./fold sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae-    ? ./fold+      missing+        sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae+    ? ./fold.dhall , not =-      ./not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4-    ? ./not+      missing+        sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+    ? ./not.dhall , odd =-      ./odd sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999-    ? ./odd+      missing+        sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999+    ? ./odd.dhall , or =-      ./or sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4-    ? ./or+      missing+        sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4+    ? ./or.dhall , show =-      ./show sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61-    ? ./show+      missing+        sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61+    ? ./show.dhall }
dhall-lang/Prelude/Bool/show view
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,4 +1,5 @@ { show =-      ./show sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f-    ? ./show+      missing+        sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f+    ? ./show.dhall }
dhall-lang/Prelude/Double/show view
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,19 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,7 +1,13 @@ { compose =-      ./compose sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013-    ? ./compose+      missing+        sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+    ? ./compose.dhall+, composeList =+      missing+        sha256:2c6931544d8b5a5b14514098c07bd1813f67b16834588d056df3c0bc2e489937+    ? ./composeList.dhall , identity =-      ./identity sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4-    ? ./identity+      missing+        sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+    ? ./identity.dhall }
dhall-lang/Prelude/Integer/abs view
@@ -1,19 +1,3 @@-{--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+  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
@@ -1,26 +1,3 @@-{--`add m n` computes `m + n`.--}-let Integer/subtract =-        ./subtract sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda-      ? ./subtract--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,25 +1,3 @@-{--`equal` checks if two Integers are equal.--}-let Natural/equal =-        ../Natural/equal sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60-      ? ../Natural/equal--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+  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
@@ -1,30 +1,3 @@-{--`greaterThan` checks if one Integer is greater than another.--}-let Bool/not =-        ../Bool/not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4-      ? ../Bool/not--let lessThanEqual =-        ./lessThanEqual sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc-      ? ./lessThanEqual--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+  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
@@ -1,26 +1,3 @@-{--`greaterThanEqual` checks if one Integer is greater than or equal to another.--}-let lessThanEqual =-        ./lessThanEqual sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc-      ? ./lessThanEqual--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+  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
@@ -1,26 +1,3 @@-{--`lessThan` checks if one Integer is less than another.--}-let greaterThan =-        ./greaterThan sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b-      ? ./greaterThan--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+  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
@@ -1,47 +1,3 @@-{--`lessThanEqual` checks if one Integer is less than or equal to another.--}-let Natural/greaterThanEqual =-        ../Natural/greaterThanEqual sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4-      ? ../Natural/greaterThanEqual--let Natural/lessThanEqual =-        ../Natural/lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-      ? ../Natural/lessThanEqual--let nonPositive =-        ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-      ? ./nonPositive--let nonNegative =-        ./nonNegative sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663-      ? ./nonNegative--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+  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
@@ -1,48 +1,3 @@-{--`multiply m n` computes `m * n`.--}--let nonPositive =-        ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-      ? ./nonPositive--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,20 +1,3 @@-{--Returns `True` for any `Integer` less than `+0`.--`negative` is more efficient than `./lessThan +0` or `./lessThanEqual -1`.--}-let positive =-        ./positive sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3-      ? ./positive--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+  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
@@ -1,20 +1,3 @@-{--Returns `True` for `+0` and any positive `Integer`.--`nonNegative` is more efficient than `./greaterThanEqual +0` or `./greaterThan -1`.--}-let nonPositive =-        ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-      ? ./nonPositive--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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,55 +1,73 @@ { abs =-      ./abs sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1-    ? ./abs+      missing+        sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+    ? ./abs.dhall , add =-      ./add sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b-    ? ./add+      missing+        sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+    ? ./add.dhall , clamp =-      ./clamp sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2-    ? ./clamp+      missing+        sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+    ? ./clamp.dhall , equal =-      ./equal sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8-    ? ./equal+      missing+        sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+    ? ./equal.dhall , greaterThan =-      ./greaterThan sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b-    ? ./greaterThan+      missing+        sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+    ? ./greaterThan.dhall , greaterThanEqual =-      ./greaterThanEqual sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958-    ? ./greaterThanEqual+      missing+        sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+    ? ./greaterThanEqual.dhall , lessThan =-      ./lessThan sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0-    ? ./lessThan+      missing+        sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+    ? ./lessThan.dhall , lessThanEqual =-      ./lessThanEqual sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc-    ? ./lessThanEqual+      missing+        sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+    ? ./lessThanEqual.dhall , multiply =-      ./multiply sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d-    ? ./multiply+      missing+        sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+    ? ./multiply.dhall , negate =-      ./negate sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d-    ? ./negate+      missing+        sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+    ? ./negate.dhall , negative =-      ./negative sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570-    ? ./negative+      missing+        sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+    ? ./negative.dhall , nonNegative =-      ./nonNegative sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663-    ? ./nonNegative+      missing+        sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+    ? ./nonNegative.dhall , nonPositive =-      ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-    ? ./nonPositive+      missing+        sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+    ? ./nonPositive.dhall , positive =-      ./positive sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3-    ? ./positive+      missing+        sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+    ? ./positive.dhall , show =-      ./show sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9-    ? ./show+      missing+        sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+    ? ./show.dhall , subtract =-      ./subtract sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda-    ? ./subtract+      missing+        sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+    ? ./subtract.dhall , toDouble =-      ./toDouble sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7-    ? ./toDouble+      missing+        sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+    ? ./toDouble.dhall , toNatural =-      ./toNatural sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e-    ? ./toNatural+      missing+        sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+    ? ./toNatural.dhall }
dhall-lang/Prelude/Integer/positive view
@@ -1,24 +1,3 @@-{--Returns `True` for any `Integer` greater than `+0`.--`positive` is more efficient than `./greaterThan +0` or `./greaterThanEqual +1`.--}-let not =-        ../Bool/not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4-      ? ../Bool/not--let nonPositive =-        ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-      ? ./nonPositive--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,63 +1,3 @@-{--`subtract m n` computes `n - m`.--}-let nonPositive =-        ./nonPositive sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b-      ? ./nonPositive--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,19 +1,3 @@-{--Convert an `Integer` to an `Optional Natural`, with negative numbers becoming `None Natural`.--}-let nonNegative =-        ./nonNegative sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663-      ? ./nonNegative--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+  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
@@ -1,7 +1,3 @@-{- 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 >+  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
@@ -1,35 +1,3 @@-{--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+  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
@@ -1,73 +1,3 @@-{--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 :-              ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335-            ? ./Nesting-        , contents : a-        }--in  Tagged+  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
@@ -1,73 +1,3 @@-{- 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+  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
@@ -1,38 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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+  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
@@ -1,33 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,56 +1,70 @@-{- A record of functions useful for constructing `JSON` values.+{-|+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.+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.+It is used internally by `render`, `renderYAML` and `omitNullFields` instead of+`package.dhall` to avoid import cycles. -} { Type =-      ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-    ? ./Type+      missing+        sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+    ? ./Type.dhall , Tagged =-      ./Tagged sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194-    ? ./Tagged+      missing+        sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+    ? ./Tagged.dhall , Nesting =-      ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335-    ? ./Nesting+      missing+        sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+    ? ./Nesting.dhall , keyText =-      ./keyText sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc-    ? ./keyText+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./keyText.dhall , keyValue =-      ./keyValue sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c-    ? ./keyValue+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+    ? ./keyValue.dhall , string =-      ./string sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e-    ? ./string+      missing+        sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+    ? ./string.dhall , number =-      ./number sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32-    ? ./number+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./number.dhall , double =-      ./double sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32-    ? ./double+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./double.dhall , integer =-      ./integer sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40-    ? ./integer+      missing+        sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+    ? ./integer.dhall , natural =-      ./natural sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5-    ? ./natural+      missing+        sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+    ? ./natural.dhall , object =-      ./object sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac-    ? ./object+      missing+        sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+    ? ./object.dhall , array =-      ./array sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8-    ? ./array+      missing+        sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+    ? ./array.dhall , bool =-      ./bool sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39-    ? ./bool+      missing+        sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+    ? ./bool.dhall , null =-      ./null sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8-    ? ./null+      missing+        sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+    ? ./null.dhall , renderInteger =-      ./renderInteger.dhall sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+      missing+        sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c     ? ./renderInteger.dhall }
dhall-lang/Prelude/JSON/double view
@@ -1,33 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,33 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,2 +1,3 @@-  ../Map/keyText sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc-? ../Map/keyText+  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
@@ -1,2 +1,3 @@-  ../Map/keyValue sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c-? ../Map/keyValue+  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
@@ -1,29 +1,3 @@-{- Create a JSON number from a Dhall `Natural`--```-let JSON = ./package.dhall-in  JSON.render (JSON.natural 42)-= "42"-```--}-let JSON =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,28 +1,3 @@-{- Create a JSON null--```-let JSON = ./package.dhall-in  JSON.render JSON.null-= "null"-```--}-let JSON =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,25 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--let double =-        ./double sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32-      ? ./double--let number-    : Double → JSON-    = double--in  number+  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
@@ -1,52 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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+  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
@@ -1,144 +1,3 @@-{--This utility omits all `null` record fields, which is often the idiomatic way-for a configuration to encode absent fields--}-let JSON =-        ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5-      ? ./core.dhall--let List/concatMap =-        ../List/concatMap sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64-      ? ../List/concatMap--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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 = 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 = 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+  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
@@ -1,19 +1,29 @@   { render =-        ./render sha256:eb26e0a4eee530dcda9d73974e9e9256fbad264916101866406a1647e28e280d-      ? ./render+        missing+          sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836+      ? ./render.dhall+  , renderCompact =+        missing+          sha256:e6c8809fbe193fddd430f94350d69cefd45e7aaf8bd379e51b750fde75008562+      ? ./renderCompact.dhall   , renderYAML =-        ./renderYAML sha256:d406a8744b81ced6a485da3cdb40a357fdd37338f4f134b00e7da3684054ebd3-      ? ./renderYAML+        missing+          sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478+      ? ./renderYAML.dhall   , omitNullFields =-        ./omitNullFields sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0-      ? ./omitNullFields+        missing+          sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+      ? ./omitNullFields.dhall   , tagInline =-        ./tagInline sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4-      ? ./tagInline+        missing+          sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+      ? ./tagInline.dhall   , tagNested =-        ./tagNested sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f-      ? ./tagNested+        missing+          sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+      ? ./tagNested.dhall   }-∧ (   ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+∧ (   missing+        sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5     ? ./core.dhall   )
dhall-lang/Prelude/JSON/render view
@@ -1,49 +1,3 @@-{- 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 =-        ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5-      ? ./core.dhall--let renderAs =-        ./renderAs sha256:f16238edec4c6dd846f19677c6675b27c579999dcff91db6193c10ade1d83174-      ? ./renderAs--let Format =-        ./Format sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac-      ? ./Format--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+  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
@@ -1,443 +1,3 @@-{- Render a `JSON` value as `Text` in either JSON or YAML format. -}--let JSON =-        ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5-      ? ./core.dhall--let Function/identity =-        ../Function/identity sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4-      ? ../Function/identity--let Text/concatMap =-        ../Text/concatMap sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f-      ? ../Text/concatMap--let List/take =-        ../List/take sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa-      ? ../List/take--let List/drop =-        ../List/drop sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf-      ? ../List/drop--let List/null =-        ../List/null sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80-      ? ../List/null--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--let List/concatMap =-        ../List/concatMap sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64-      ? ../List/concatMap--let Optional/map =-        ../Optional/map sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa-      ? ../Optional/map--let NonEmpty-    : Type → Type-    = λ(a : Type) → { head : a, tail : List a }--let List/uncons-    : ∀(a : Type) → List a → Optional (NonEmpty a)-    =   λ(a : Type)-      → λ(ls : List a)-      → Optional/map-          a-          (NonEmpty a)-          (λ(head : a) → { head = head, tail = List/drop 1 a ls })-          (List/head a ls)--let NonEmpty/singleton-    : ∀(a : Type) → a → NonEmpty a-    = λ(a : Type) → λ(x : a) → { head = x, tail = [] : List a }--let NonEmpty/toList-    : ∀(a : Type) → NonEmpty a → List a-    = λ(a : Type) → λ(nonEmpty : NonEmpty a) → [ nonEmpty.head ] # nonEmpty.tail--let NonEmpty/concat-    : ∀(a : Type) → NonEmpty (NonEmpty a) → NonEmpty a-    =   λ(a : Type)-      → λ(lss : NonEmpty (NonEmpty a))-      → { head = lss.head.head-        , tail =-              lss.head.tail-            # List/concatMap (NonEmpty a) a (NonEmpty/toList a) lss.tail-        }--let NonEmpty/map-    : ∀(a : Type) → ∀(b : Type) → (a → b) → NonEmpty a → NonEmpty b-    =   λ(a : Type)-      → λ(b : Type)-      → λ(fn : a → b)-      → λ(ls : NonEmpty a)-      → { head = fn ls.head, tail = List/map a b fn ls.tail }--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 List/splitAt-    : Natural → ∀(a : Type) → List a → { head : List a, tail : List a }-    =   λ(index : Natural)-      → λ(a : Type)-      → λ(ls : List a)-      → { head = List/take index a ls, tail = List/drop index a ls }--let _testSplitAt0 =-        assert-      :   List/splitAt 0 Natural [ 1, 2, 3 ]-        ≡ { head = [] : List Natural, tail = [ 1, 2, 3 ] }--let _testSplitAt1 =-        assert-      : List/splitAt 1 Natural [ 1, 2, 3 ] ≡ { head = [ 1 ], tail = [ 2, 3 ] }--let _testSplitAt3 =-        assert-      :   List/splitAt 3 Natural [ 1, 2, 3 ]-        ≡ { head = [ 1, 2, 3 ], tail = [] : List Natural }--let _testSplitAt =-        assert-      :   List/splitAt 1 Natural ([] : List Natural)-        ≡ { head = [] : List Natural, tail = [] : List Natural }--let List/splitLast =-        λ(a : Type)-      → λ(ls : List a)-      → List/splitAt (Natural/subtract 1 (List/length a ls)) a ls--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 NonEmpty/append-    : ∀(a : Type) → a → NonEmpty a → NonEmpty a-    =   λ(a : Type)-      → λ(suffix : a)-      → λ(ls : NonEmpty a)-      → { head = ls.head, tail = ls.tail # [ suffix ] }--let NonEmpty/mapLast-    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a-    =   λ(a : Type)-      → λ(fn : a → a)-      → λ(ls : NonEmpty a)-      →       if List/null a ls.tail--        then  { head = fn ls.head, tail = [] : List a }--        else  let split = List/splitLast a ls.tail--              in  { head = ls.head-                  , tail = split.head # List/map a a fn split.tail-                  }--let NonEmpty/mapLeading-    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a-    =   λ(a : Type)-      → λ(fn : a → a)-      → λ(ls : NonEmpty a)-      →       if List/null a ls.tail--        then  ls--        else  let split = List/splitLast a ls.tail--              in  { head = fn ls.head-                  , tail = List/map a a fn split.head # split.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 =-        ./Format sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac-      ? ./Format--let ObjectField = { mapKey : Text, mapValue : Block }--let renderJSONStruct =-        λ(prefix : Text)-      → λ(suffix : Text)-      → λ(blocks : NonEmpty Lines)-      → let indent = NonEmpty/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        if List/null Text block.tail--            then  NonEmpty/singleton Text "${prefix} ${block.head} ${suffix}"--            else  NonEmpty/prepend-                    Text-                    prefix-                    (NonEmpty/append Text suffix (indent block))--let renderObject =-        λ(format : Format)-      → λ(fields : NonEmpty ObjectField)-      → let keystr = λ(field : ObjectField) → "${Text/show 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 (Text/show 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--in  renderAs+  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
@@ -1,18 +1,17 @@-{- Render an `Integer` value as a `JSON number`, according to the JSON-   standard, in which a number may not start with a plus sign (`+`).+{-|+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 =-        ../Integer/nonNegative sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663-      ? ../Integer/nonNegative+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ../Integer/nonNegative.dhall  let renderInteger     : Integer → Text-    =   λ(integer : Integer)-      →       if Integer/nonNegative integer-+    = λ(integer : Integer) →+        if    Integer/nonNegative integer         then  Natural/show (Integer/clamp integer)-         else  Integer/show integer  let positive = assert : renderInteger +1 ≡ "1"
dhall-lang/Prelude/JSON/renderYAML view
@@ -1,47 +1,3 @@-{- 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 =-        ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5-      ? ./core.dhall--let renderAs =-        ./renderAs sha256:f16238edec4c6dd846f19677c6675b27c579999dcff91db6193c10ade1d83174-      ? ./renderAs--let Format =-        ./Format sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac-      ? ./Format--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+  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
@@ -1,33 +1,3 @@-{- 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 =-        ./Type sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759-      ? ./Type--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+  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
@@ -1,28 +1,3 @@-{- Prepare a union value for JSON- or YAML-encoding with the inline layout--}-let Nesting =-        ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335-      ? ./Nesting--let Tagged =-        ./Tagged sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194-      ? ./Tagged--let tagInline-    : Text → ∀(a : Type) → a → Tagged a-    =   λ(tagFieldName : Text)-      → λ(a : Type)-      → λ(contents : a)-      → { nesting = Nesting.Inline, field = tagFieldName, contents = 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+  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
@@ -1,32 +1,3 @@-{- Prepare a union value for JSON- or YAML-encoding with the nested layout--}-let Nesting =-        ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335-      ? ./Nesting--let Tagged =-        ./Tagged sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194-      ? ./Tagged--let tagNested-    : Text → Text → ∀(a : Type) → a → Tagged a-    =   λ(contentsFieldName : Text)-      → λ(tagFieldName : Text)-      → λ(a : Type)-      → λ(contents : a)-      → { nesting = Nesting.Nested contentsFieldName-        , field = tagFieldName-        , contents = 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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,32 +1,3 @@-{--`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+  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
@@ -1,36 +1,3 @@-{--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+  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
@@ -1,32 +1,3 @@-{--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+  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
@@ -1,15 +1,3 @@-{--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+  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
@@ -1,29 +1,3 @@--- Remove first `n` elements of a list-let Natural/greaterThanEqual =-        ../Natural/greaterThanEqual sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4-      ? ../Natural/greaterThanEqual--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+  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
@@ -1,10 +1,3 @@-{--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+  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
@@ -1,26 +1,3 @@-{--Only keep elements of the list where the supplied function returns `True`--Examples:--}-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+  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
@@ -1,51 +1,3 @@-{--`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 ]-            Natural-            (λ(x : Natural) → λ(y : Natural) → x + y)-            0-        ≡ 10--let example1 =-        assert-      :   (   λ(nil : Natural)-            → fold-                Natural-                [ 2, 3, 5 ]-                Natural-                (λ(x : Natural) → λ(y : Natural) → x + y)-                nil-          )-        ≡ (λ(nil : Natural) → 2 + (3 + (5 + nil)))--let example2 =-        assert-      :   (   λ(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))-          )--in  fold+  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
@@ -1,35 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,19 +1,3 @@-{--Retrieve an element from a `List` using its 0-based index--}-let drop =-        ./drop sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf-      ? ./drop--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+  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
@@ -1,21 +1,3 @@-{--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+  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
@@ -1,42 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,25 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,79 +1,125 @@ { all =-      ./all sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15-    ? ./all+      missing+        sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15+    ? ./all.dhall , any =-      ./any sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8-    ? ./any+      missing+        sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8+    ? ./any.dhall , build =-      ./build sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42-    ? ./build+      missing+        sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42+    ? ./build.dhall , concat =-      ./concat sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b-    ? ./concat+      missing+        sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b+    ? ./concat.dhall , concatMap =-      ./concatMap sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64-    ? ./concatMap+      missing+        sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+    ? ./concatMap.dhall , default =-      ./default sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379-    ? ./default+      missing+        sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+    ? ./default.dhall , drop =-      ./drop sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf-    ? ./drop+      missing+        sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+    ? ./drop.dhall , empty =-      ./empty sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147-    ? ./empty+      missing+        sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+    ? ./empty.dhall , filter =-      ./filter sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6-    ? ./filter+      missing+        sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6+    ? ./filter.dhall+, filterMap =+      missing+        sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+    ? ./filterMap.dhall , fold =-      ./fold sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814-    ? ./fold+      missing+        sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814+    ? ./fold.dhall+, foldLeft =+      missing+        sha256:3c6ab57950fe644906b7bbdef0b9523440b6ee17773ebb8cbd41ffacb8bfab61+    ? ./foldLeft.dhall , generate =-      ./generate sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4-    ? ./generate+      missing+        sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4+    ? ./generate.dhall , head =-      ./head sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026-    ? ./head+      missing+        sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026+    ? ./head.dhall , index =-      ./index sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63-    ? ./index+      missing+        sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+    ? ./index.dhall , indexed =-      ./indexed sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f-    ? ./indexed+      missing+        sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f+    ? ./indexed.dhall , iterate =-      ./iterate sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26-    ? ./iterate+      missing+        sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26+    ? ./iterate.dhall , last =-      ./last sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d-    ? ./last+      missing+        sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d+    ? ./last.dhall , length =-      ./length sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461-    ? ./length+      missing+        sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461+    ? ./length.dhall , map =-      ./map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-    ? ./map+      missing+        sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+    ? ./map.dhall+, mapMaybe =+      missing+        sha256:6f3c4f8c94577b46e7d30f8df7e82a269b0ad0a7e18c0f0370f243fd1127e77f+    ? ./mapMaybe.dhall+, mapWithIndex =+      missing+        sha256:98599e0b55c5d3ae75264ba90657c6f68c7ce32834bd12b215acaea711eed6eb+    ? ./mapWithIndex.dhall , null =-      ./null sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80-    ? ./null+      missing+        sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80+    ? ./null.dhall , partition =-      ./partition sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03-    ? ./partition+      missing+        sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+    ? ./partition.dhall , replicate =-      ./replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347-    ? ./replicate+      missing+        sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+    ? ./replicate.dhall , reverse =-      ./reverse sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d-    ? ./reverse+      missing+        sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d+    ? ./reverse.dhall , shifted =-      ./shifted sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe-    ? ./shifted+      missing+        sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+    ? ./shifted.dhall , take =-      ./take sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa-    ? ./take+      missing+        sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+    ? ./take.dhall+, unpackOptionals =+      missing+        sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+    ? ./unpackOptionals.dhall , unzip =-      ./unzip sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9-    ? ./unzip+      missing+        sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+    ? ./unzip.dhall , zip =-      ./zip sha256:7be343f42cddb7e3b5884611ae5c8731e76e52b22d7bb45420cae7c9a82be0ca-    ? ./zip+      missing+        sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+    ? ./zip.dhall }
dhall-lang/Prelude/List/partition view
@@ -1,33 +1,3 @@-{--`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+  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
@@ -1,20 +1,3 @@-{--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+  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
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,83 +1,3 @@-{--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+  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
@@ -1,25 +1,3 @@--- Truncate a list to the first `n` elements-let Natural/lessThan =-        ../Natural/lessThan sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c-      ? ../Natural/lessThan--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+  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
@@ -1,52 +1,3 @@-{--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+  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
@@ -1,49 +1,3 @@-{--Zip two `List` into a single `List`--Resulting `List` will have the length of the shortest of its arguments.--}-let List/drop =-      ./drop sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf--let zip-    : ∀(a : Type) → List a → ∀(b : Type) → List b → List { _1 : a, _2 : b }-    =   λ(a : Type)-      → λ(xa : List a)-      → λ(b : Type)-      → λ(xb : List b)-      → let Carry = { acc : List { _1 : a, _2 : b }, context : List b }--        let cons =-                λ(elem : a)-              → λ(prev : Carry)-              → let nextAcc =-                      merge-                        { Some =-                            λ(bb : b) → [ { _1 = elem, _2 = bb } ] # prev.acc-                        , None = prev.acc-                        }-                        (List/head b prev.context)--                in  { acc = nextAcc, context = List/drop 1 b prev.context }--        let nil = { acc = [] : List { _1 : a, _2 : b }, context = xb }--        let result = List/fold a xa Carry cons nil--        in  result.acc--let example0 =-        assert-      :   zip Text [ "ABC", "DEF", "GHI" ] Bool [ True, False, True ]-        ≡ [ { _1 = "ABC", _2 = True }-          , { _1 = "DEF", _2 = False }-          , { _1 = "GHI", _2 = True }-          ]--let example1 =-        assert-      :   zip Text [ "ABC" ] Bool ([] : List Bool)-        ≡ ([] : List { _1 : Text, _2 : Bool })--in  zip+  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
@@ -1,18 +1,3 @@-{- 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 sha256:f428188ff9d77ea15bc2bcd0da3f8ed81b304e175b07ade42a3b0fb02941b2aa as Location-            ? missing as Location-          )-        ≡ < Environment : Text-          | Local : Text-          | Missing-          | Remote : Text-          >.Missing--in  Location+  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
@@ -1,4 +1,5 @@ { Type =-      ./Type sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529-    ? ./Type+      missing+        sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+    ? ./Type.dhall }
dhall-lang/Prelude/Map/Entry view
@@ -1,7 +1,3 @@-{- 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+  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
@@ -1,24 +1,3 @@-{- 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+  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
@@ -1,15 +1,3 @@-{--An empty `Map` of the given key and value types--}-let Map =-        ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed-      ? ./Type--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+  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
@@ -1,15 +1,3 @@-{--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+  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
@@ -1,17 +1,3 @@-{--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+  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
@@ -1,38 +1,3 @@-{--Get all of the keys of a `Map` as a `List`--}-let Map =-        ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed-      ? ./Type--let Entry =-        ./Entry sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346-      ? ./Entry--let List/map =-        ../List/map 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+  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
@@ -1,57 +1,3 @@-{--Transform a `Map` by applying a function to each value--}-let Map =-        ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed-      ? ./Type--let Entry =-        ./Entry sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346-      ? ./Entry--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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+  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
@@ -1,25 +1,41 @@ { Type =-      ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      missing+        sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed     ? ./Type , Entry =-      ./Entry sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      missing+        sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346     ? ./Entry , empty =-      ./empty sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+      missing+        sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52     ? ./empty , keyText =-      ./keyText sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc     ? ./keyText , keyValue =-      ./keyValue sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c     ? ./keyValue , keys =-      ./keys sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+      missing+        sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7     ? ./keys , map =-      ./map sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+      missing+        sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0     ? ./map+, mapMaybe =+      missing+        sha256:4ea58b720d7af38cef3ef07bef36e476caeed21032cd4a9dc733868a74d9a521+    ? ./mapMaybe.dhall+, unpackOptionals =+      missing+        sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+    ? ./unpackOptionals.dhall , values =-      ./values sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+      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
@@ -1,38 +1,3 @@-{--Get all of the values of a `Map` as a `List`--}-let Map =-        ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed-      ? ./Type--let Entry =-        ./Entry sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346-      ? ./Entry--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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+  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
@@ -1,43 +1,3 @@-{--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+  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
@@ -1,33 +1,3 @@-{--`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+  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
@@ -1,32 +1,3 @@-{--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+  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
@@ -1,18 +1,3 @@-{--`equal` checks if two Naturals are equal.--}-let lessThanEqual =-        ./lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-      ? ./lessThanEqual--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,35 +1,3 @@-{--`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 Natural (λ(x : Natural) → 5 * x) 1 ≡ 125--let example1 =-        assert-      :   (λ(zero : Natural) → fold 3 Natural (λ(x : Natural) → 5 * x) zero)-        ≡ (λ(zero : Natural) → 5 * (5 * (5 * zero)))--let example2 =-        assert-      :   (   λ(natural : Type)-            → λ(succ : natural → natural)-            → λ(zero : natural)-            → fold 3 natural succ zero-          )-        ≡ (   λ(natural : Type)-            → λ(succ : natural → natural)-            → λ(zero : natural)-            → succ (succ (succ zero))-          )--in  fold+  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
@@ -1,22 +1,3 @@-{--`greaterThan` checks if one Natural is strictly greater than another.--}-let lessThan =-        ./lessThan sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c-      ? ./lessThan--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+  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
@@ -1,22 +1,3 @@-{--`greaterThanEqual` checks if one Natural is greater than or equal to another.--}-let lessThanEqual =-        ./lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-      ? ./lessThanEqual--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,26 +1,3 @@-{--`lessThan` checks if one Natural is strictly less than another.--}-let greaterThanEqual =-        ./greaterThanEqual sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4-      ? ./greaterThanEqual--let Bool/not =-        ../Bool/not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4-      ? ../Bool/not--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+  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
@@ -1,18 +1,3 @@-{--`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+  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
@@ -1,28 +1,3 @@-{--`listMax` returns the largest element of a `List` or `None Natural` if the-`List` is empty--}-let max =-        ./max sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7-      ? ./max--let Optional/map =-        ../Optional/map sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa-      ? ../Optional/map--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+  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
@@ -1,32 +1,3 @@-{--`listMin` returns the smallest element of a `List` or `None Natural` if the-`List` is empty--}-let min =-        ./min sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710-      ? ./min--let Optional/map =-        ../Optional/map sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa-      ? ../Optional/map--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+  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
@@ -1,20 +1,3 @@-{--`max a b` returns the larger of `a` or `b`--}-let lessThanEqual =-        ./lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-      ? ./lessThanEqual--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+  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
@@ -1,18 +1,3 @@-{--`min a b` returns the smaller of `a` or `b`--}-let lessThanEqual =-        ./lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-      ? ./lessThanEqual--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,67 +1,89 @@ { build =-      ./build sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c-    ? ./build+      missing+        sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c+    ? ./build.dhall , enumerate =-      ./enumerate sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3-    ? ./enumerate+      missing+        sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+    ? ./enumerate.dhall , even =-      ./even sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66-    ? ./even+      missing+        sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66+    ? ./even.dhall , fold =-      ./fold sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06-    ? ./fold+      missing+        sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+    ? ./fold.dhall , isZero =-      ./isZero sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1-    ? ./isZero+      missing+        sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+    ? ./isZero.dhall , odd =-      ./odd sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5-    ? ./odd+      missing+        sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5+    ? ./odd.dhall , product =-      ./product sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6-    ? ./product+      missing+        sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6+    ? ./product.dhall , sum =-      ./sum sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037-    ? ./sum+      missing+        sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037+    ? ./sum.dhall , show =-      ./show sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21-    ? ./show+      missing+        sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21+    ? ./show.dhall , toDouble =-      ./toDouble sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81-    ? ./toDouble+      missing+        sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81+    ? ./toDouble.dhall , toInteger =-      ./toInteger sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f-    ? ./toInteger+      missing+        sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f+    ? ./toInteger.dhall , lessThan =-      ./lessThan sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c-    ? ./lessThan+      missing+        sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+    ? ./lessThan.dhall , lessThanEqual =-      ./lessThanEqual sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99-    ? ./lessThanEqual+      missing+        sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+    ? ./lessThanEqual.dhall , equal =-      ./equal sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60-    ? ./equal+      missing+        sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+    ? ./equal.dhall , greaterThanEqual =-      ./greaterThanEqual sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4-    ? ./greaterThanEqual+      missing+        sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+    ? ./greaterThanEqual.dhall , greaterThan =-      ./greaterThan sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c-    ? ./greaterThan+      missing+        sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+    ? ./greaterThan.dhall , min =-      ./min sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710-    ? ./min+      missing+        sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+    ? ./min.dhall , max =-      ./max sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7-    ? ./max+      missing+        sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+    ? ./max.dhall , listMin =-      ./listMin sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6-    ? ./listMin+      missing+        sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+    ? ./listMin.dhall , listMax =-      ./listMax sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472-    ? ./listMax+      missing+        sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+    ? ./listMax.dhall , sort =-      ./sort sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260-    ? ./sort+      missing+        sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+    ? ./sort.dhall , subtract =-      ./subtract sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745-    ? ./subtract+      missing+        sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+    ? ./subtract.dhall }
dhall-lang/Prelude/Natural/product view
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,60 +1,3 @@-{--`sort` sorts a `List` of `Natural`s in ascending order--}-let greaterThanEqual =-        ./greaterThanEqual sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4-      ? ./greaterThanEqual--let listMin =-        ./listMin sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6-      ? ./listMin--let List/partition =-        ../List/partition sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03-      ? ../List/partition--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+  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
@@ -1,20 +1,3 @@-{--`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+  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
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,43 +1,3 @@-{--`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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,15 +1,3 @@-{--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+  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
@@ -1,31 +1,3 @@-{--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+  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
@@ -1,23 +1,3 @@-{--`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) Natural (λ(x : Natural) → x) 0 ≡ 2--let example1 =-      assert : fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 ≡ 0--in  fold+  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
@@ -1,26 +1,3 @@-{--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+  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
@@ -1,26 +1,3 @@-{--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,16 +1,3 @@-{--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+  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
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,43 +1,65 @@ { all =-      ./all sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695-    ? ./all+      missing+        sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+    ? ./all.dhall , any =-      ./any sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435-    ? ./any+      missing+        sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+    ? ./any.dhall , build =-      ./build sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1-    ? ./build+      missing+        sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+    ? ./build.dhall , concat =-      ./concat sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a-    ? ./concat+      missing+        sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+    ? ./concat.dhall+, concatMap =+      missing+        sha256:c06ae93e900a99299c9b4ec4912ca5395a0103ea88292205b08dd7e345632818+    ? ./concatMap.dhall , default =-      ./default sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad-    ? ./default+      missing+        sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+    ? ./default.dhall+, equal =+      missing+        sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+    ? ./equal.dhall , filter =-      ./filter sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83-    ? ./filter+      missing+        sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+    ? ./filter.dhall , fold =-      ./fold sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf-    ? ./fold+      missing+        sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+    ? ./fold.dhall , head =-      ./head sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c-    ? ./head+      missing+        sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+    ? ./head.dhall , last =-      ./last sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707-    ? ./last+      missing+        sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+    ? ./last.dhall , length =-      ./length sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85-    ? ./length+      missing+        sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+    ? ./length.dhall , map =-      ./map sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa-    ? ./map+      missing+        sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+    ? ./map.dhall , null =-      ./null sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc-    ? ./null+      missing+        sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+    ? ./null.dhall , toList =-      ./toList sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4-    ? ./toList+      missing+        sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+    ? ./toList.dhall , unzip =-      ./unzip sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708-    ? ./unzip+      missing+        sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+    ? ./unzip.dhall }
dhall-lang/Prelude/Optional/toList view
@@ -1,14 +1,3 @@-{--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+  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
@@ -1,32 +1,3 @@-{--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+  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
@@ -1,13 +1,3 @@-{--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+  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
@@ -1,24 +1,3 @@-{--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+  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
@@ -1,38 +1,3 @@-{--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+  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
@@ -1,33 +1,3 @@-{--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+  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
@@ -1,12 +1,3 @@-{--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+  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
@@ -1,15 +1,3 @@-{--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+  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
@@ -1,28 +1,53 @@ { concat =-      ./concat sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0-    ? ./concat+      missing+        sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+    ? ./concat.dhall , concatMap =-      ./concatMap sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f-    ? ./concatMap+      missing+        sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+    ? ./concatMap.dhall , concatMapSep =-      ./concatMapSep sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840-    ? ./concatMapSep+      missing+        sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+    ? ./concatMapSep.dhall , concatSep =-      ./concatSep sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58-    ? ./concatSep+      missing+        sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+    ? ./concatSep.dhall , default =-      ./default sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf-    ? ./default+      missing+        sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+    ? ./default.dhall , defaultMap =-      ./defaultMap sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588-    ? ./defaultMap+      missing+        sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+    ? ./defaultMap.dhall+, lowerASCII =+      missing+        sha256:26b076651120b907e869396bd3dc16271f2e12433062b2f26f296968a69515e7+    ? ./lowerASCII.dhall+, replace =+      missing+        sha256:7d132df0e091a43817bba8afa06d1bb487ee51c091430404ad6f8c78bc0328a6+    ? ./replace.dhall , replicate =-      ./replicate sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f-    ? ./replicate+      missing+        sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+    ? ./replicate.dhall+, shell-escape =+      missing+        sha256:d53521b3f478cb18a7d63730bc0e3153c2124b70d6ac9a1f610ce7db67cfc7a2+    ? ./shell-escape.dhall , show =-      ./show sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784-    ? ./show+      missing+        sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+    ? ./show.dhall , spaces =-      ./spaces sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc-    ? ./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
@@ -1,21 +1,3 @@-{--Build a Text by copying the given Text the specified number of times--}--let concat =-        ./concat sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0-      ? ./concat--let List/replicate =-        ../List/replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347-      ? ../List/replicate--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+  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
@@ -1,19 +1,3 @@-{--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+  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
@@ -1,20 +1,3 @@-{--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 =-        ./replicate sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f-      ? ./replicate--let spaces-    : Natural → Text-    = λ(a : Natural) → replicate a " "--let example0 = assert : spaces 1 ≡ " "--let example1 = assert : spaces 0 ≡ ""--in  spaces+  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
@@ -1,62 +1,3 @@-{- 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-       , 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-            , element :-                  { attributes : List { mapKey : Text, mapValue : Text }-                  , content : List XML-                  , name : Text-                  }-                → XML-            }-          )-      → XML--in  XML/Type+  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
@@ -1,7 +1,3 @@-{- 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+  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
@@ -1,57 +1,3 @@-{- 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 =-        ./Type sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c-      ? ./Type--let List/map =-        ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680-      ? ../List/map--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-            , 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+  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
@@ -1,3 +1,3 @@-{- Create an empty XML attribute List. -}--[] : List { mapKey : Text, mapValue : Text }+  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
@@ -1,30 +1,3 @@-{- 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 =-        ./Type sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c-      ? ./Type--let element =-        ./element sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b-      ? ./element--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+  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
@@ -1,22 +1,33 @@ { Type =-      ./Type sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c-    ? ./Type+      missing+        sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+    ? ./Type.dhall , attribute =-      ./attribute sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc-    ? ./attribute+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./attribute.dhall , render =-      ./render sha256:8d034f7f97cded14a96147565d489be840e5678480d175b962b2600d85a3230e-    ? ./render+      missing+        sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66+    ? ./render.dhall , element =-      ./element sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b-    ? ./element+      missing+        sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+    ? ./element.dhall , leaf =-      ./leaf sha256:4383e4fc4bf6a29ac2052776972eb59d5355a1cd067cded80d4ff32840969261-    ? ./leaf+      missing+        sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506+    ? ./leaf.dhall , text =-      ./text sha256:c83cd721d32d7dc28c04ce429c0cb22812639e572637ec348578a58ffb68844f-    ? ./text+      missing+        sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+    ? ./text.dhall+, rawText =+      missing+        sha256:2af9d72c151677d4110039e361b7e9faaf2947e6c9d29aa72aea351ad797e05d+    ? ./rawText.dhall , emptyAttributes =-      ./emptyAttributes sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5-    ? ./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
@@ -1,66 +1,3 @@-{- Render an `XML` value as `Text`--   *WARNING:* rendering does not include any XML injection mitigations,-   therefore it should not be used to process arbitrary strings into-   element attributes or element data.--   For indentation and schema validation, see the `xmllint` utility-   bundled with libxml2.--```-let XML = ./package.dhall--in  XML.render-    ( XML.node-      { 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 =-        ./Type sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c-      ? ./Type--let Text/concatMap =-        ../Text/concatMap sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f-      ? ../Text/concatMap--let Text/concat =-        ../Text/concat sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0-      ? ../Text/concat--let Attr = { mapKey : Text, mapValue : Text }--let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${x.mapValue}\""--let render-    : XML → Text-    =   λ(x : XML)-      → x-          Text-          { text = λ(d : Text) → d-          , 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}>"-                        )-          }--in  render+  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
@@ -1,37 +1,3 @@-{- Create a Text value to be inserted into an XML element as content.--```-let XML = ./package.dhall--in  XML.render-    ( XML.node-      { name = "location"-      , attributes = XML.emptyAttributes-      , content = [ XML.text "/foo/bar" ]-      }-    )-= "<location>/foo/bar</location>"-```--}--let XML =-        ./Type sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c-      ? ./Type--let text-    : Text → XML-    =   λ(d : Text)-      → λ(XML : Type)-      → λ ( xml-          : { text : Text → XML-            , element :-                  { attributes : List { mapKey : Text, mapValue : Text }-                  , content : List XML-                  , name : Text-                  }-                → XML-            }-          )-      → xml.text d--in  text+  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
@@ -1,40 +1,73 @@ { Bool =-      ./Bool/package.dhall sha256:7ee950e7c2142be5923f76d00263e536b71d96cb9c190d7743c1679501ddeb0a+      missing+        sha256:dde2b9b71afdd26878c06e90cd2cde4488063457d5fbe30e02baed3bec5eede6     ? ./Bool/package.dhall+, Date =+      missing+        sha256:fc0c5efc924fa99aa8e5dea5d78c3dc1a24cb550028342b90149ea78cb5ca873+    ? ./Date/package.dhall , Double =-      ./Double/package.dhall sha256:b8d20ab3216083622ae371fb42a6732bc67bb2d66e84989c8ddba7556a336cf7+      missing+        sha256:b8d20ab3216083622ae371fb42a6732bc67bb2d66e84989c8ddba7556a336cf7     ? ./Double/package.dhall , Function =-      ./Function/package.dhall sha256:6d17cf0fd4fabe1737fb117f87c04b8ff82b299915a5b673c0a543b134b8fffe+      missing+        sha256:f4ca848f69034f9d7a74e12c556c3a3396966c1de3a9427a102d1aff4580192f     ? ./Function/package.dhall , Integer =-      ./Integer/package.dhall sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0+      missing+        sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0     ? ./Integer/package.dhall+, JSON =+      missing+        sha256:5f98b7722fd13509ef448b075e02b9ff98312ae7a406cf53ed25012dbc9990ac+    ? ./JSON/package.dhall , List =-      ./List/package.dhall sha256:10b6d87a09a77bfc1fdef554b7e62abb1b1f0a9267776d834f598ab240ef526c+      missing+        sha256:26d1b4cd800219d8b67043c638926aa6e5517ea74a0bd3e371974514621bca04     ? ./List/package.dhall , Location =-      ./Location/package.dhall sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470+      missing+        sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470     ? ./Location/package.dhall , Map =-      ./Map/package.dhall sha256:598e9c76103b2686fbbda6cc30078f9e60dd846d9eaf155d0149cf0ae06c21c5+      missing+        sha256:c5e79a9de642644a09b96a2ec3147c5d8662b7926f09610e751c0c0f6ed0b30a     ? ./Map/package.dhall , Monoid =-      ./Monoid sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af-    ? ./Monoid+      missing+        sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+    ? ./Monoid.dhall , Natural =-      ./Natural/package.dhall sha256:ee9ed2b28a417ed4e9a0c284801b928bf91b3fbdc1a68616347678c1821f1ddf+      missing+        sha256:ee9ed2b28a417ed4e9a0c284801b928bf91b3fbdc1a68616347678c1821f1ddf     ? ./Natural/package.dhall+, NonEmpty =+      missing+        sha256:c24686a230a4b3cd51e5a57cd4510b4f8242f813d7823d41bac5954e7af56f7a+    ? ./NonEmpty/package.dhall+, Operator =+      missing+        sha256:861f724704a7b4755c96f173e54d03f314492a2d046723404c31ff612b7bf2e6+    ? ./Operator/package.dhall , Optional =-      ./Optional/package.dhall sha256:4324b2bf84ded40f67485f14355e4cb7b237a8f173e713c791ec44cebebc552c+      missing+        sha256:74331dfe59c09db65edc7ec4498bff92473c8c06d92752f9470d26e25f91320c     ? ./Optional/package.dhall-, JSON =-      ./JSON/package.dhall sha256:1b02c5ff4710f90ee3f8dc1a2565f1b52b45e5317e2df4775307e2ba0cadcf21-    ? ./JSON/package.dhall , Text =-      ./Text/package.dhall sha256:819a967038fbf6f28cc289fa2651e42835f70b326210c86e51acf48f46f913d8+      missing+        sha256:79b671a70ac459b799a53bbb8a383cc8b81b40421745c54bf0fb1143168cbd6f     ? ./Text/package.dhall+, Time =+      missing+        sha256:6715c4c71a113429fef8b94e4561a93c288942dad9dfd75ac545de96c5b5652a+    ? ./Time/package.dhall+, TimeZone =+      missing+        sha256:c17fd403c637856f34c8287168b92974e8c1a3a7331967f75276d179057084fd+    ? ./TimeZone/package.dhall , XML =-      ./XML/package.dhall sha256:137e7b106b2e9743970e5d37b21a165f2e40f56ab593a4dd10605c9acd686fc6+      missing+        sha256:2e111f0952087d42072b059f0bf4c95861a46bffa67ad4c8c39086edf405f32e     ? ./XML/package.dhall }
+ 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/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/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/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/cache/dhall/1220efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd

binary file changed (49 → absent bytes)

+ 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
@@ -1,1 +1,1 @@-../failure/cycle.dhall+../failure/unit/Cycle.dhall
+ dhall-lang/tests/import/data/doesNotParse.dhall view
@@ -0,0 +1,1 @@+[
+ dhall-lang/tests/import/data/example.bin view
@@ -0,0 +1,1 @@+#Eg‰«Íï
+ dhall-lang/tests/import/data/userAgent.dhall view
@@ -0,0 +1,1 @@+"Dhall (from import)"
− dhall-lang/tests/import/failure/cycle.dhall
@@ -1,1 +0,0 @@-../data/cycle.dhall
− dhall-lang/tests/import/failure/hashMismatch.dhall
@@ -1,1 +0,0 @@-../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
− dhall-lang/tests/import/failure/importBoundary.dhall
@@ -1,1 +0,0 @@-\(x: Bool) -> ../data/importBoundary.dhall
− dhall-lang/tests/import/failure/missing.dhall
@@ -1,1 +0,0 @@-missing
+ 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/referentiallyInsane.dhall
@@ -1,13 +0,0 @@-{- 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/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/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/hashFromCacheA.dhall view
@@ -6,6 +6,6 @@ resolved by its hash.  (If you're interested, the value is a fully-αβ-normalized copy of-Prelude/Optional/null at time of test creation)+Prelude/Optional/null) -}-missing sha256:efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd+missing sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
dhall-lang/tests/import/success/hashFromCacheB.dhall view
@@ -1,3 +1,3 @@-  λ(_ : Type)-→ λ(_ : Optional _)-→ Optional/fold _@1 _ Bool (λ(_ : _@1) → False) True+λ(_ : Type) →+λ(_ : Optional _) →+  merge { None = True, Some = λ(_ : _@1) → False } _
dhall-lang/tests/import/success/headerForwardingA.dhall view
@@ -1,16 +1,12 @@ {- This test verifies that header-forwarding works correctly for relative    imports within the same domain -   `test.dhall-lang.org` is the same as `prelude.dhall-lang.org` except that-   `test.dhall-lang.org` rejects all requests without a `Test` header.+   `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/Bool/package.dhall` forwards the `Test` header-   to the transitive relative imports of `https://test.dhall-lang.org/Bool/*` in+   `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.--   Note: You will need to update this test whenever the `Bool` package in the-   Prelude changes (sorry) -}-https://test.dhall-lang.org/Bool/package.dhall-  using [ { mapKey = "Test", mapValue = "Example" } ]+https://test.dhall-lang.org/foo using (toMap { Test = "Example" })
dhall-lang/tests/import/success/headerForwardingB.dhall view
@@ -1,26 +1,1 @@-{ and =-      λ(xs : List Bool)-    → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l && r) True-, build =-      λ(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool)-    → f Bool True False-, even =-      λ(xs : List Bool)-    → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x == y) True-, fold =-      λ(b : Bool)-    → λ(bool : Type)-    → λ(true : bool)-    → λ(false : bool)-    → if b then true else false-, not =-    λ(b : Bool) → b == False-, odd =-      λ(xs : List Bool)-    → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x != y) False-, or =-      λ(xs : List Bool)-    → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l || r) False-, show =-    λ(b : Bool) → if b then "True" else "False"-}+True
+ 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/AlternativeHashMismatchA.dhall
@@ -1,1 +0,0 @@-../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ? 42
− dhall-lang/tests/import/success/unit/AlternativeHashMismatchB.dhall
@@ -1,1 +0,0 @@-42
− dhall-lang/tests/import/success/unit/AlternativeParseErrorA.dhall
@@ -1,1 +0,0 @@-../../data/example.txt ? 42
− dhall-lang/tests/import/success/unit/AlternativeParseErrorB.dhall
@@ -1,1 +0,0 @@-42
− dhall-lang/tests/import/success/unit/AlternativeTypeErrorA.dhall
@@ -1,1 +0,0 @@-../../data/doesNotTypecheck.dhall ? 42
− dhall-lang/tests/import/success/unit/AlternativeTypeErrorB.dhall
@@ -1,1 +0,0 @@-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/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/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/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/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/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/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/remoteSystemsA.dhall view
@@ -1,6 +1,6 @@-let Text/concatMap = ../../../Prelude/Text/concatMap+let Text/concatMap = ../../../Prelude/Text/concatMap.dhall -let Text/concatSep = ../../../Prelude/Text/concatSep+let Text/concatSep = ../../../Prelude/Text/concatSep.dhall  let Row =       { cores :@@ -26,12 +26,11 @@           : Row           )       → let host =-              Optional/fold-              Text-              row.user-              Text-              (λ(user : Text) → "${user}@${row.host}")-              row.host+              merge+                { None = row.host+                , Some = λ(user : Text) → "${user}@${row.host}"+                }+                row.user                  let platforms = Text/concatSep "," row.platforms         
dhall-lang/tests/normalization/success/remoteSystemsB.dhall view
@@ -59,12 +59,9 @@         )     → λ(y : Text)     →     ''-          ${Optional/fold-            Text-            x.user-            Text-            (λ(user : Text) → "${user}@${x.host}")-            x.host} ${merge+          ${merge+            { None = x.host, Some = λ(user : Text) → "${user}@${x.host}" }+            x.user} ${merge                       { Empty = "", NonEmpty = λ(result : Text) → result }                       ( List/fold                         Text
− dhall-lang/tests/normalization/success/simple/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-      )-}
− dhall-lang/tests/normalization/success/simple/optionalBuildB.dhall
@@ -1,9 +0,0 @@-{ example0 =-    Some 1-, example1 =-    Some +1-, example2 =-    λ(id : ∀(a : Type) → a → a) → id (Optional Bool) (Some True)-, example3 =-    λ(a : Type) → λ(x : a) → Some x-}
− dhall-lang/tests/normalization/success/simple/optionalBuildFoldA.dhall
@@ -1,1 +0,0 @@-Optional/build Text (Optional/fold Text (Some "foo"))
− dhall-lang/tests/normalization/success/simple/optionalBuildFoldB.dhall
@@ -1,1 +0,0 @@-Some "foo"
− dhall-lang/tests/normalization/success/simple/optionalFoldA.dhall
@@ -1,7 +0,0 @@-    let f =-            λ(o : Optional Text)-          → Optional/fold Text o Natural (λ(j : Text) → 1) 2--in  { example0 = f (Some "foo")-    , example1 = f (None Text)-    }
− dhall-lang/tests/normalization/success/simple/optionalFoldB.dhall
@@ -1,1 +0,0 @@-{ example0 = 1, example1 = 2 }
+ 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/OptionalBuildA.dhall
@@ -1,1 +0,0 @@-Optional/build
− dhall-lang/tests/normalization/success/unit/OptionalBuildB.dhall
@@ -1,1 +0,0 @@-Optional/build
− dhall-lang/tests/normalization/success/unit/OptionalBuildFoldFusionA.dhall
@@ -1,1 +0,0 @@-λ(T : Type) → λ(x : Optional T) → Optional/build T (Optional/fold T x)
− dhall-lang/tests/normalization/success/unit/OptionalBuildFoldFusionB.dhall
@@ -1,3 +0,0 @@-  λ(T : Type)-→ λ(x : Optional T)-→ Optional/fold T x (Optional T) (λ(a : T) → Some a) (None T)
− dhall-lang/tests/normalization/success/unit/OptionalBuildImplementationA.dhall
@@ -1,3 +0,0 @@-  λ(T : Type)-→ λ(f : ∀(optional : Type) → (T → optional) → optional → optional)-→ Optional/build T f
− dhall-lang/tests/normalization/success/unit/OptionalBuildImplementationB.dhall
@@ -1,3 +0,0 @@-  λ(T : Type)-→ λ(f : ∀(optional : Type) → (T → optional) → optional → optional)-→ f (Optional T) (λ(a : T) → Some a) (None T)
− dhall-lang/tests/normalization/success/unit/OptionalFoldA.dhall
@@ -1,1 +0,0 @@-Optional/fold
− dhall-lang/tests/normalization/success/unit/OptionalFoldB.dhall
@@ -1,1 +0,0 @@-Optional/fold
− dhall-lang/tests/normalization/success/unit/OptionalFoldNoneA.dhall
@@ -1,1 +0,0 @@-λ(T : Type) → λ(x : Bool) → Optional/fold T (None T) Bool (λ(_ : T) → False) x
− dhall-lang/tests/normalization/success/unit/OptionalFoldNoneB.dhall
@@ -1,1 +0,0 @@-λ(T : Type) → λ(x : Bool) → x
− dhall-lang/tests/normalization/success/unit/OptionalFoldSomeA.dhall
@@ -1,4 +0,0 @@-  λ(T : Type)-→ λ(x : T)-→ λ(y : Bool)-→ Optional/fold T (Some x) Bool (λ(_ : T) → False) y
− dhall-lang/tests/normalization/success/unit/OptionalFoldSomeB.dhall
@@ -1,1 +0,0 @@-λ(T : Type) → λ(x : T) → λ(y : Bool) → False
+ 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/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/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/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/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/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/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/parser/failure/boundBuiltins.dhall view
@@ -1,6 +1,6 @@ {-     Builtin names are disallowed in bound variables.-    The grammar doesn't explicitely disallow this, but the implementation should+    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/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/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/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/ListLitTwoCommas.dhall view
@@ -0,0 +1,1 @@+[ ,, ]
+ 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/RecordTwoCommas.dhall view
@@ -0,0 +1,1 @@+{ ,, }
− dhall-lang/tests/parser/failure/unit/RecordTypeTrailingComma.dhall
@@ -1,1 +0,0 @@-{ x: T, }
+ 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/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/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/builtinsA.dhall view
@@ -1,32 +1,40 @@-  λ ( 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-  , field20 = None-  }+[ 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

binary file changed (544 → 405 bytes)

+ 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/largeExpressionA.dhall view
@@ -97,12 +97,11 @@           }         )     → λ(y : Text)-    →     Optional/fold-          Text-          x.user-          Text-          (λ(user : Text) → user ++ "@" ++ x.host ++ "")-          x.host+    →     merge+            { None = x.host+            , Some = λ(user : Text) → user ++ "@" ++ x.host ++ ""+            }+            x.user       ++  " "       ++  ( merge             { Empty = "", NonEmpty = λ(result : Text) → result }
dhall-lang/tests/parser/success/largeExpressionB.dhallb view

binary file changed (3518 → 3507 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/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/quotedLabelA.dhall view
@@ -1,4 +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 (81 → 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/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/preserveCommentA.dhall view
@@ -1,8 +1,1 @@-{- A comment within the interior of a multi-line literal counts as part of the-   literal--}--''--- Hello-{- world -}-''+"-- $--$--{--}$"
dhall-lang/tests/parser/success/text/preserveCommentB.dhallb view
@@ -1,2 +1,1 @@-‚u-- Hello-{- world -}+‚n-- $--$--{--}$
+ 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/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/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/DoubleLitSecretelyIntA.dhall
@@ -1,5 +0,0 @@-{--    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/DoubleLitSecretelyIntB.dhallb

binary file changed (3 → absent bytes)

+ 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/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/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/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/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/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/RecordFieldAccessA.dhall
@@ -1,1 +0,0 @@-r.x
− dhall-lang/tests/parser/success/unit/RecordFieldAccessB.dhallb

binary file changed (8 → absent bytes)

+ 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/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/RecordProjectFieldsA.dhall
@@ -1,1 +0,0 @@-r.{ x, y, z }
− dhall-lang/tests/parser/success/unit/RecordProjectFieldsB.dhallb

binary file changed (12 → absent 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/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/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/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/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/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/WithA.dhall view
@@ -1,6 +1,1 @@-{-  The purpose of this test is to verify that an implementation correctly-    desugars the base case of a non-nested update.  Specifically, an-    implementation should not use an intermediate `let` when desugaring this-    base case.--} { a = 1 } with a = 2
dhall-lang/tests/parser/success/unit/WithB.dhallb view
@@ -1,1 +1,1 @@-„	‚¡aa‚‚¡aa‚+„‚¡aa‚aa‚
dhall-lang/tests/parser/success/unit/WithMultipleA.dhall view
@@ -1,8 +1,4 @@-{- This test ensures that `with` is purely syntactic sugar, meaning that it is-   desugared before encoding and therefore is encoded as the desugared expression-   in the CBOR encoding.--   This test also ensures that implementations desugar the code exactly as-   specified (e.g. using an intermediate `let` binding)+{- 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
@@ -1,1 +1,1 @@-„	„	‚¢aa‚¡ab‚ac‚¡ad‚‚¡aa„	ƒ	‚¢aa‚¡ab‚ac‚¡ad‚aa‚¡ab‚‚¡ac„	ƒ	„	‚¢aa‚¡ab‚ac‚¡ad‚‚¡aa„	ƒ	‚¢aa‚¡ab‚ac‚¡ad‚aa‚¡ab‚ac‚¡ae‚+„„‚¢aa‚¡ab‚ac‚¡ad‚‚aaab‚‚acae‚
dhall-lang/tests/parser/success/unit/WithPrecedence1B.dhallb view
@@ -1,1 +1,1 @@-„	„	‚¡aaƒö‚‚¡aaƒö‚‚¡aaƒö‚+„„‚¡aaƒö‚aaƒö‚aaƒö‚
dhall-lang/tests/parser/success/unit/WithPrecedence2B.dhallb view

binary file changed (25 → 23 bytes)

dhall-lang/tests/parser/success/unit/WithPrecedence3B.dhallb view

binary file changed (28 → 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/import/quotedPathsA.dhall view
@@ -1,3 +1,1 @@-{ example0 = /"foo"/bar/"baz qux"-, example1 = https://example.com/foo/"bar?baz"?qux-}+/"foo"/bar/"baz qux"
dhall-lang/tests/parser/success/unit/import/quotedPathsB.dhallb view

binary file changed (80 → 22 bytes)

− dhall-lang/tests/parser/success/unit/import/urls/quotedPathFakeUrlEncodeA.dhall
@@ -1,1 +0,0 @@-https://example.com/"a%20b"/c
− dhall-lang/tests/parser/success/unit/import/urls/quotedPathFakeUrlEncodeB.dhallb

binary file changed (30 → absent bytes)

+ 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/RecursiveRecordMergeA.dhall view
@@ -1,1 +1,1 @@-x //\\ y+x /\ y
dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocA.dhall view
@@ -1,1 +1,1 @@-w //\\ x //\\ y //\\ z+w /\ x /\ y /\ z
dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocB.dhallb view

binary file changed (25 → 25 bytes)

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

binary file changed (11 → 11 bytes)

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

binary file changed (25 → 25 bytes)

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

binary file changed (11 → 11 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/prelude/Bool/and/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and [ True, False, True ]+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and ([] : List Bool)+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0A.dhall view
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1A.dhall view
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True, False ]+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True ]+../../../../../../Prelude/Bool/even.dhall [ False, True ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False ]+../../../../../../Prelude/Bool/even.dhall [ False ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even ([] : List Bool)+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold True Natural 0 1+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold False Natural 0 1+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not True+../../../../../../Prelude/Bool/not.dhall True
dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not False+../../../../../../Prelude/Bool/not.dhall False
dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False ]+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True ]+../../../../../../Prelude/Bool/odd.dhall [ True ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or [ True, False, True ]+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or ([] : List Bool)+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show True+../../../../../../Prelude/Bool/show.dhall True
dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show False+../../../../../../Prelude/Bool/show.dhall False
dhall-lang/tests/semantic-hash/success/prelude/Double/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show -3.1+../../../../../../Prelude/Double/show.dhall -3.1
dhall-lang/tests/semantic-hash/success/prelude/Double/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show 0.4+../../../../../../Prelude/Double/show.dhall 0.4
dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show -3+../../../../../../Prelude/Integer/show.dhall -3
dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show +0+../../../../../../Prelude/Integer/show.dhall +0
dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble -3+../../../../../../Prelude/Integer/toDouble.dhall -3
dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble +2+../../../../../../Prelude/Integer/toDouble.dhall +2
dhall-lang/tests/semantic-hash/success/prelude/List/all/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/all/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/any/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/any/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
dhall-lang/tests/semantic-hash/success/prelude/List/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
dhall-lang/tests/semantic-hash/success/prelude/List/concat/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ]
dhall-lang/tests/semantic-hash/success/prelude/List/concat/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [] : List Natural , [] : List Natural , [] : List Natural
dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/filter/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/filter/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/fold/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/fold+../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
dhall-lang/tests/semantic-hash/success/prelude/List/fold/1A.dhall view
@@ -1,5 +1,5 @@   λ(nil : Natural)-→ ../../../../../../Prelude/List/fold+→ ../../../../../../Prelude/List/fold.dhall   Natural   [ 2, 3, 5 ]   Natural
dhall-lang/tests/semantic-hash/success/prelude/List/fold/2A.dhall view
@@ -1,4 +1,4 @@   λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
dhall-lang/tests/semantic-hash/success/prelude/List/generate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
dhall-lang/tests/semantic-hash/success/prelude/List/generate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
dhall-lang/tests/semantic-hash/success/prelude/List/head/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/List/head/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
dhall-lang/tests/semantic-hash/success/prelude/List/last/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/List/last/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/length/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/List/length/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/map/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/List/map/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/null/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/List/null/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 9 Natural 1+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 0 Natural 1+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/shifted+../../../../../../Prelude/List/shifted.dhall Bool [ [ { index = 0, value = True }   , { index = 1, value = True }
dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/unzip+../../../../../../Prelude/List/unzip.dhall Text Bool [ { _1 = "ABC", _2 = True }
dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 10+../../../../../../Prelude/Natural/enumerate.dhall 10
dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 0+../../../../../../Prelude/Natural/enumerate.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 3+../../../../../../Prelude/Natural/even.dhall 3
dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 0+../../../../../../Prelude/Natural/even.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1A.dhall view
@@ -1,1 +1,1 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2A.dhall view
@@ -1,4 +1,4 @@   λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 2+../../../../../../Prelude/Natural/isZero.dhall 2
dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 0+../../../../../../Prelude/Natural/isZero.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 3+../../../../../../Prelude/Natural/odd.dhall 3
dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 0+../../../../../../Prelude/Natural/odd.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product ([] : List Natural)+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 3+../../../../../../Prelude/Natural/show.dhall 3
dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 0+../../../../../../Prelude/Natural/show.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 3+../../../../../../Prelude/Natural/toDouble.dhall 3
dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 0+../../../../../../Prelude/Natural/toDouble.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 3+../../../../../../Prelude/Natural/toInteger.dhall 3
dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 0+../../../../../../Prelude/Natural/toInteger.dhall 0
dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (Some 2)+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (None Natural)+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (Some 2)+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (None Natural)+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat ([] : List Text)+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
dhall-lang/tests/semantic-hash/success/prelude/Text/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/show "ABC"+../../../../../../Prelude/Text/show.dhall "ABC"
dhall-lang/tests/semantic-hash/success/prelude/Text/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/show "\u0000 \$ \\ \n \u263a"+../../../../../../Prelude/Text/show.dhall "\u0000 \$ \\ \n \u263a"
dhall-lang/tests/semantic-hash/success/remoteSystemsA.dhall view
@@ -26,12 +26,11 @@           : Row           )       → let host =-              Optional/fold-              Text-              row.user-              Text-              (λ(user : Text) → "${user}@${row.host}")-              row.host+              merge+                { None = row.host+                , Some = λ(user : Text) → "${user}@${row.host}"+                }+                row.user                  let platforms = Text/concatSep "," row.platforms         
dhall-lang/tests/semantic-hash/success/remoteSystemsB.hash view
@@ -1,1 +1,1 @@-sha256:1591a538ac60355f6f988d01edb3b8622d2631b93177a90ad7172e0f88b67da5+sha256:573b0d8fbc28c09c155cf239963b6ba71941aace25e23806043017f7fe75098b
− dhall-lang/tests/semantic-hash/success/simple/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-      )-}
− dhall-lang/tests/semantic-hash/success/simple/optionalBuildB.hash
@@ -1,1 +0,0 @@-sha256:57937e066a166baf3d712e744d9aec91894f14d7b25138a6f60c7b7577cc986b
− dhall-lang/tests/semantic-hash/success/simple/optionalBuildFoldA.dhall
@@ -1,1 +0,0 @@-Optional/build Text (Optional/fold Text (Some "foo"))
− dhall-lang/tests/semantic-hash/success/simple/optionalBuildFoldB.hash
@@ -1,1 +0,0 @@-sha256:29dc3b0c8df03521d3bb92d3b7d996a70a5dbca8de8607ffaf9f888a2213e73b
− dhall-lang/tests/semantic-hash/success/simple/optionalFoldA.dhall
@@ -1,7 +0,0 @@-    let f =-            λ(o : Optional Text)-          → Optional/fold Text o Natural (λ(j : Text) → 1) 2--in  { example0 = f (Some "foo")-    , example1 = f (None Text)-    }
− dhall-lang/tests/semantic-hash/success/simple/optionalFoldB.hash
@@ -1,1 +0,0 @@-sha256:225b0c8ffa394c837aebfce636806e3f39511d87331b6ef734311689a2ec8a7e
+ 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/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/prelude/Bool/and/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and [ True, False, True ]+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
dhall-lang/tests/type-inference/success/prelude/Bool/and/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and ([] : List Bool)+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
dhall-lang/tests/type-inference/success/prelude/Bool/build/0A.dhall view
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
dhall-lang/tests/type-inference/success/prelude/Bool/build/1A.dhall view
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
dhall-lang/tests/type-inference/success/prelude/Bool/even/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True, False ]+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
dhall-lang/tests/type-inference/success/prelude/Bool/even/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True ]+../../../../../../Prelude/Bool/even.dhall [ False, True ]
dhall-lang/tests/type-inference/success/prelude/Bool/even/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False ]+../../../../../../Prelude/Bool/even.dhall [ False ]
dhall-lang/tests/type-inference/success/prelude/Bool/even/3A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even ([] : List Bool)+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
dhall-lang/tests/type-inference/success/prelude/Bool/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold True Natural 0 1+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
dhall-lang/tests/type-inference/success/prelude/Bool/fold/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold False Natural 0 1+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
dhall-lang/tests/type-inference/success/prelude/Bool/not/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not True+../../../../../../Prelude/Bool/not.dhall True
dhall-lang/tests/type-inference/success/prelude/Bool/not/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not False+../../../../../../Prelude/Bool/not.dhall False
dhall-lang/tests/type-inference/success/prelude/Bool/odd/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
dhall-lang/tests/type-inference/success/prelude/Bool/odd/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False ]+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
dhall-lang/tests/type-inference/success/prelude/Bool/odd/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True ]+../../../../../../Prelude/Bool/odd.dhall [ True ]
dhall-lang/tests/type-inference/success/prelude/Bool/odd/3A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
dhall-lang/tests/type-inference/success/prelude/Bool/or/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or [ True, False, True ]+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
dhall-lang/tests/type-inference/success/prelude/Bool/or/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or ([] : List Bool)+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
dhall-lang/tests/type-inference/success/prelude/Bool/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show True+../../../../../../Prelude/Bool/show.dhall True
dhall-lang/tests/type-inference/success/prelude/Bool/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show False+../../../../../../Prelude/Bool/show.dhall False
dhall-lang/tests/type-inference/success/prelude/Double/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show -3.1+../../../../../../Prelude/Double/show.dhall -3.1
dhall-lang/tests/type-inference/success/prelude/Double/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show 0.4+../../../../../../Prelude/Double/show.dhall 0.4
dhall-lang/tests/type-inference/success/prelude/Integer/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show -3+../../../../../../Prelude/Integer/show.dhall -3
dhall-lang/tests/type-inference/success/prelude/Integer/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show +0+../../../../../../Prelude/Integer/show.dhall +0
dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble -3+../../../../../../Prelude/Integer/toDouble.dhall -3
dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble +2+../../../../../../Prelude/Integer/toDouble.dhall +2
dhall-lang/tests/type-inference/success/prelude/List/all/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/all/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/any/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/any/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
dhall-lang/tests/type-inference/success/prelude/List/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
dhall-lang/tests/type-inference/success/prelude/List/concat/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ]
dhall-lang/tests/type-inference/success/prelude/List/concat/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [] : List Natural , [] : List Natural , [] : List Natural
dhall-lang/tests/type-inference/success/prelude/List/concatMap/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/concatMap/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/filter/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/filter/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/fold/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/fold+../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
dhall-lang/tests/type-inference/success/prelude/List/fold/1A.dhall view
@@ -1,5 +1,5 @@   λ(nil : Natural)-→ ../../../../../../Prelude/List/fold+→ ../../../../../../Prelude/List/fold.dhall   Natural   [ 2, 3, 5 ]   Natural
dhall-lang/tests/type-inference/success/prelude/List/fold/2A.dhall view
@@ -1,4 +1,4 @@   λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
dhall-lang/tests/type-inference/success/prelude/List/generate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
dhall-lang/tests/type-inference/success/prelude/List/generate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
dhall-lang/tests/type-inference/success/prelude/List/head/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/List/head/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/indexed/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
dhall-lang/tests/type-inference/success/prelude/List/indexed/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
dhall-lang/tests/type-inference/success/prelude/List/iterate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
dhall-lang/tests/type-inference/success/prelude/List/iterate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
dhall-lang/tests/type-inference/success/prelude/List/last/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/List/last/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/length/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/List/length/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/map/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/List/map/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/null/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/List/null/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/replicate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 9 Natural 1+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
dhall-lang/tests/type-inference/success/prelude/List/replicate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 0 Natural 1+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
dhall-lang/tests/type-inference/success/prelude/List/reverse/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/List/reverse/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/List/shifted/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/shifted+../../../../../../Prelude/List/shifted.dhall Bool [ [ { index = 0, value = True }   , { index = 1, value = True }
dhall-lang/tests/type-inference/success/prelude/List/shifted/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
dhall-lang/tests/type-inference/success/prelude/List/unzip/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/unzip+../../../../../../Prelude/List/unzip.dhall Text Bool [ { _1 = "ABC", _2 = True }
dhall-lang/tests/type-inference/success/prelude/List/unzip/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
dhall-lang/tests/type-inference/success/prelude/Natural/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
dhall-lang/tests/type-inference/success/prelude/Natural/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 10+../../../../../../Prelude/Natural/enumerate.dhall 10
dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 0+../../../../../../Prelude/Natural/enumerate.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/even/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 3+../../../../../../Prelude/Natural/even.dhall 3
dhall-lang/tests/type-inference/success/prelude/Natural/even/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 0+../../../../../../Prelude/Natural/even.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
dhall-lang/tests/type-inference/success/prelude/Natural/fold/1A.dhall view
@@ -1,1 +1,1 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
dhall-lang/tests/type-inference/success/prelude/Natural/fold/2A.dhall view
@@ -1,4 +1,4 @@   λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 2+../../../../../../Prelude/Natural/isZero.dhall 2
dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 0+../../../../../../Prelude/Natural/isZero.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/odd/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 3+../../../../../../Prelude/Natural/odd.dhall 3
dhall-lang/tests/type-inference/success/prelude/Natural/odd/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 0+../../../../../../Prelude/Natural/odd.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/product/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/Natural/product/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product ([] : List Natural)+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/Natural/show/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 3+../../../../../../Prelude/Natural/show.dhall 3
dhall-lang/tests/type-inference/success/prelude/Natural/show/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 0+../../../../../../Prelude/Natural/show.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/sum/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
dhall-lang/tests/type-inference/success/prelude/Natural/sum/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 3+../../../../../../Prelude/Natural/toDouble.dhall 3
dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 0+../../../../../../Prelude/Natural/toDouble.dhall 0
dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 3+../../../../../../Prelude/Natural/toInteger.dhall 3
dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 0+../../../../../../Prelude/Natural/toInteger.dhall 0
dhall-lang/tests/type-inference/success/prelude/Optional/all/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
dhall-lang/tests/type-inference/success/prelude/Optional/all/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/any/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
dhall-lang/tests/type-inference/success/prelude/Optional/any/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/build/0A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
dhall-lang/tests/type-inference/success/prelude/Optional/build/1A.dhall view
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
dhall-lang/tests/type-inference/success/prelude/Optional/concat/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
dhall-lang/tests/type-inference/success/prelude/Optional/concat/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
dhall-lang/tests/type-inference/success/prelude/Optional/concat/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
dhall-lang/tests/type-inference/success/prelude/Optional/filter/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
dhall-lang/tests/type-inference/success/prelude/Optional/filter/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
dhall-lang/tests/type-inference/success/prelude/Optional/fold/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
dhall-lang/tests/type-inference/success/prelude/Optional/fold/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
dhall-lang/tests/type-inference/success/prelude/Optional/head/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
dhall-lang/tests/type-inference/success/prelude/Optional/head/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
dhall-lang/tests/type-inference/success/prelude/Optional/head/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
dhall-lang/tests/type-inference/success/prelude/Optional/last/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
dhall-lang/tests/type-inference/success/prelude/Optional/last/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
dhall-lang/tests/type-inference/success/prelude/Optional/last/2A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
dhall-lang/tests/type-inference/success/prelude/Optional/length/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (Some 2)+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
dhall-lang/tests/type-inference/success/prelude/Optional/length/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (None Natural)+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/map/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
dhall-lang/tests/type-inference/success/prelude/Optional/map/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/null/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (Some 2)+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
dhall-lang/tests/type-inference/success/prelude/Optional/null/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (None Natural)+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/toList/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
dhall-lang/tests/type-inference/success/prelude/Optional/toList/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
dhall-lang/tests/type-inference/success/prelude/Text/concat/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
dhall-lang/tests/type-inference/success/prelude/Text/concat/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat ([] : List Text)+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1A.dhall view
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
dhall-lang/tests/type-inference/success/preludeB.dhall view
@@ -2,6 +2,7 @@     { 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@@ -10,16 +11,18 @@     , 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+        ∀(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 :@@ -47,250 +50,264 @@     , 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+        ∀ ( 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+        ∀(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+        ∀(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+        ∀(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 }+        ∀(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+        ∀(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+        ∀(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+        ∀(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+        ∀ ( 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+          ) →+        ∀(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+        ∀ ( 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+        ∀ ( 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+        ∀ ( 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+        ∀(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 > }+        ∀(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 > }+        ∀(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+        ∀(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@@ -298,13 +315,26 @@     , 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+        ∀(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@@ -313,30 +343,43 @@     , 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 }+        ∀(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 }+        ∀(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 }+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : List { _1 : a, _2 : b }) →+          { _1 : List a, _2 : List b }     , zip :-          ∀(a : Type)-        → ∀(xa : List a)-        → ∀(b : Type)-        → ∀(xb : List b)-        → List { _1 : a, _2 : b }+        ∀(a : Type) →+        ∀(xs : List a) →+        ∀(b : Type) →+        ∀(ys : List b) →+          List { _1 : a, _2 : b }     } , Location : { Type : Type } , Map :@@ -346,46 +389,58 @@     , keyText :         ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }     , keyValue :-          ∀(v : Type)-        → ∀(key : Text)-        → ∀(value : v)-        → { mapKey : Text, mapValue : v }+        ∀(v : Type) →+        ∀(key : Text) →+        ∀(value : v) →+          { mapKey : Text, mapValue : v }     , keys :-          ∀(k : Type)-        → ∀(v : Type)-        → ∀(xs : List { mapKey : k, mapValue : v })-        → List k+        ∀(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 }+        ∀(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+        ∀(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+        ( ∀(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+        Natural →+        ∀(natural : Type) →+        ∀(succ : natural → natural) →+        ∀(zero : natural) →+          natural     , greaterThan : ∀(x : Natural) → ∀(y : Natural) → Bool     , greaterThanEqual : ∀(x : Natural) → ∀(y : Natural) → Bool     , isZero : Natural → Bool@@ -404,147 +459,282 @@     , 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+        ∀(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+        ∀(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+        ∀(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 }+        ∀(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+        ∀(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-                            , text : Text → XML-                            }-                          )-                      → XML-                    )-              , name : Text-              }-            )-        → ∀(XML : Type)-        → ∀ ( xml-            : { element :-                    { attributes : List { mapKey : Text, mapValue : Text }-                    , content : List XML-                    , name : Text-                    }-                  → XML-              , text : Text → XML-              }-            )-        → XML+        ∀ ( 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-              , text : Text → XML-              }-            )-        → XML+        ∀ ( 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-                    , text : Text → XML-                    }-                  )-              → XML-            )-        → Text-    , text :-          ∀(d : Text)-        → ∀(XML : Type)-        → ∀ ( xml-            : { element :+        ∀ ( x+          : ∀(XML : Type) →+            ∀ ( xml+              : { element :                     { attributes : List { mapKey : Text, mapValue : Text }                     , content : List XML                     , name : Text-                    }-                  → XML-              , text : Text → XML-              }-            )-        → XML+                    } →+                      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/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/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/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/MergeOneWithAnnotation1A.dhall view
@@ -1,1 +1,1 @@-merge { x = λ(y : Bool) → y } < x >.x : (Bool → Bool)+merge { x = λ(y : Bool) → y } < x >.x : (∀(y : Bool) → Bool)
− dhall-lang/tests/type-inference/success/unit/OptionalBuildA.dhall
@@ -1,1 +0,0 @@-Optional/build
− dhall-lang/tests/type-inference/success/unit/OptionalBuildB.dhall
@@ -1,7 +0,0 @@-  ∀(a : Type)-→ (   ∀(optional : Type)-    → ∀(just : a → optional)-    → ∀(nothing : optional)-    → optional-  )-→ Optional a
− dhall-lang/tests/type-inference/success/unit/OptionalFoldA.dhall
@@ -1,1 +0,0 @@-Optional/fold
− dhall-lang/tests/type-inference/success/unit/OptionalFoldB.dhall
@@ -1,6 +0,0 @@-  ∀(a : Type)-→ Optional a-→ ∀(optional : Type)-→ ∀(just : a → optional)-→ ∀(nothing : optional)-→ optional
+ 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/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/ToMapInferTypeFromRecordA.dhall view
@@ -1,1 +1,1 @@-toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : Bool → Bool }+toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionA.dhall view
@@ -1,1 +1,1 @@-(λ(x : Bool) → x) : Bool → Bool+(λ(x : Bool) → x) : ∀(x : Bool) → Bool
+ 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/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.cabal view
@@ -1,13 +1,12 @@+Cabal-Version: 2.4 Name: dhall-Version: 1.32.0-Cabal-Version: >=1.10+Version: 1.42.3 Build-Type: Simple-Tested-With: GHC == 8.2.2, GHC == 8.4.3, GHC == 8.6.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,12 +21,13 @@     .     Read "Dhall.Tutorial" to learn how to use this library Category: Compiler-Extra-Source-Files:-    benchmark/deep-nested-large-record/*.dhall-    benchmark/examples/*.dhall-    benchmark/examples/normalize/*.dhall+Data-Files:     man/dhall.1+Extra-Source-Files:     CHANGELOG.md+    benchmark/**/*.dhall+    benchmark/**/*.dhallb+    dhall-lang/Prelude/**/*.dhall     dhall-lang/Prelude/Bool/and     dhall-lang/Prelude/Bool/build     dhall-lang/Prelude/Bool/even@@ -35,13 +35,10 @@     dhall-lang/Prelude/Bool/not     dhall-lang/Prelude/Bool/odd     dhall-lang/Prelude/Bool/or-    dhall-lang/Prelude/Bool/package.dhall     dhall-lang/Prelude/Bool/show-    dhall-lang/Prelude/Double/package.dhall     dhall-lang/Prelude/Double/show     dhall-lang/Prelude/Function/compose     dhall-lang/Prelude/Function/identity-    dhall-lang/Prelude/Function/package.dhall     dhall-lang/Prelude/Integer/abs     dhall-lang/Prelude/Integer/add     dhall-lang/Prelude/Integer/clamp@@ -55,7 +52,6 @@     dhall-lang/Prelude/Integer/negative     dhall-lang/Prelude/Integer/nonNegative     dhall-lang/Prelude/Integer/nonPositive-    dhall-lang/Prelude/Integer/package.dhall     dhall-lang/Prelude/Integer/positive     dhall-lang/Prelude/Integer/show     dhall-lang/Prelude/Integer/subtract@@ -67,7 +63,6 @@     dhall-lang/Prelude/JSON/Type     dhall-lang/Prelude/JSON/array     dhall-lang/Prelude/JSON/bool-    dhall-lang/Prelude/JSON/core.dhall     dhall-lang/Prelude/JSON/double     dhall-lang/Prelude/JSON/integer     dhall-lang/Prelude/JSON/keyText@@ -77,10 +72,8 @@     dhall-lang/Prelude/JSON/number     dhall-lang/Prelude/JSON/object     dhall-lang/Prelude/JSON/omitNullFields-    dhall-lang/Prelude/JSON/package.dhall     dhall-lang/Prelude/JSON/render     dhall-lang/Prelude/JSON/renderAs-    dhall-lang/Prelude/JSON/renderInteger.dhall     dhall-lang/Prelude/JSON/renderYAML     dhall-lang/Prelude/JSON/string     dhall-lang/Prelude/JSON/tagInline@@ -104,16 +97,15 @@     dhall-lang/Prelude/List/length     dhall-lang/Prelude/List/map     dhall-lang/Prelude/List/null-    dhall-lang/Prelude/List/package.dhall     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/Location/package.dhall     dhall-lang/Prelude/Map/Entry     dhall-lang/Prelude/Map/Type     dhall-lang/Prelude/Map/empty@@ -121,7 +113,6 @@     dhall-lang/Prelude/Map/keyValue     dhall-lang/Prelude/Map/keys     dhall-lang/Prelude/Map/map-    dhall-lang/Prelude/Map/package.dhall     dhall-lang/Prelude/Map/values     dhall-lang/Prelude/Monoid     dhall-lang/Prelude/Natural/build@@ -139,7 +130,6 @@     dhall-lang/Prelude/Natural/max     dhall-lang/Prelude/Natural/min     dhall-lang/Prelude/Natural/odd-    dhall-lang/Prelude/Natural/package.dhall     dhall-lang/Prelude/Natural/product     dhall-lang/Prelude/Natural/show     dhall-lang/Prelude/Natural/sort@@ -159,7 +149,6 @@     dhall-lang/Prelude/Optional/length     dhall-lang/Prelude/Optional/map     dhall-lang/Prelude/Optional/null-    dhall-lang/Prelude/Optional/package.dhall     dhall-lang/Prelude/Optional/toList     dhall-lang/Prelude/Optional/unzip     dhall-lang/Prelude/Text/concat@@ -168,7 +157,6 @@     dhall-lang/Prelude/Text/concatSep     dhall-lang/Prelude/Text/default     dhall-lang/Prelude/Text/defaultMap-    dhall-lang/Prelude/Text/package.dhall     dhall-lang/Prelude/Text/replicate     dhall-lang/Prelude/Text/show     dhall-lang/Prelude/Text/spaces@@ -177,257 +165,18 @@     dhall-lang/Prelude/XML/element     dhall-lang/Prelude/XML/emptyAttributes     dhall-lang/Prelude/XML/leaf-    dhall-lang/Prelude/XML/package.dhall     dhall-lang/Prelude/XML/render     dhall-lang/Prelude/XML/text-    dhall-lang/Prelude/package.dhall-    dhall-lang/tests/alpha-normalization/success/unit/*.dhall-    dhall-lang/tests/alpha-normalization/success/regression/*.dhall-    dhall-lang/tests/binary-decode/failure/unit/*.dhallb-    dhall-lang/tests/binary-decode/success/unit/*.dhall-    dhall-lang/tests/binary-decode/success/unit/*.dhallb-    dhall-lang/tests/binary-decode/success/unit/imports/*.dhall-    dhall-lang/tests/binary-decode/success/unit/imports/*.dhallb-    dhall-lang/tests/import/cache/dhall/1220efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd-    dhall-lang/tests/import/data/*.dhall-    dhall-lang/tests/import/data/*.txt-    dhall-lang/tests/import/failure/*.dhall-    dhall-lang/tests/import/failure/unit/*.dhall-    dhall-lang/tests/import/success/*.dhall-    dhall-lang/tests/import/success/unit/*.dhall-    dhall-lang/tests/import/success/unit/asLocation/*.dhall-    dhall-lang/tests/normalization/success/*.dhall-    dhall-lang/tests/normalization/success/haskell-tutorial/access/*.dhall-    dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/*.dhall-    dhall-lang/tests/normalization/success/haskell-tutorial/prefer/*.dhall-    dhall-lang/tests/normalization/success/haskell-tutorial/projection/*.dhall-    dhall-lang/tests/normalization/success/regression/*.dhall-    dhall-lang/tests/normalization/success/simple/*.dhall-    dhall-lang/tests/normalization/success/simplifications/*.dhall-    dhall-lang/tests/normalization/success/unit/*.dhall-    dhall-lang/tests/parser/failure/*.dhall-    dhall-lang/tests/parser/failure/spacing/*.dhall-    dhall-lang/tests/parser/failure/unit/*.dhall-    dhall-lang/tests/parser/success/*.dhall-    dhall-lang/tests/parser/success/*.dhallb-    dhall-lang/tests/parser/success/text/*.dhall-    dhall-lang/tests/parser/success/text/*.dhallb-    dhall-lang/tests/parser/success/unit/*.dhall-    dhall-lang/tests/parser/success/unit/*.dhallb-    dhall-lang/tests/parser/success/unit/operators/*.dhall-    dhall-lang/tests/parser/success/unit/operators/*.dhallb-    dhall-lang/tests/parser/success/unit/import/*.dhall-    dhall-lang/tests/parser/success/unit/import/*.dhallb-    dhall-lang/tests/parser/success/unit/import/urls/*.dhall-    dhall-lang/tests/parser/success/unit/import/urls/*.dhallb-    dhall-lang/tests/semantic-hash/success/*.dhall-    dhall-lang/tests/semantic-hash/success/*.hash-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.dhall-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.hash-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.dhall-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.hash-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.dhall-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.hash-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.dhall-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/all/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/all/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/any/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/any/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/build/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/build/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/head/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/head/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/last/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/last/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/length/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/length/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/map/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/map/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/null/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/null/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.hash-    dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.dhall-    dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.hash-    dhall-lang/tests/semantic-hash/success/simple/*.dhall-    dhall-lang/tests/semantic-hash/success/simple/*.hash-    dhall-lang/tests/semantic-hash/success/simplifications/*.dhall-    dhall-lang/tests/semantic-hash/success/simplifications/*.hash-    dhall-lang/tests/type-inference/failure/*.dhall-    dhall-lang/tests/type-inference/success/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/and/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Double/show/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/all/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/any/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/build/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/concat/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/filter/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/fold/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/generate/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/head/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/last/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/length/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/map/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/null/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/type-inference/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Monoid/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/type-inference/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/type-inference/success/regression/*.dhall-    dhall-lang/tests/type-inference/success/simple/*.dhall-    dhall-lang/tests/type-inference/success/simple/access/*.dhall-    dhall-lang/tests/type-inference/success/unit/*.dhall-    tests/diff/*.dhall-    tests/diff/*.txt-    tests/format/*.dhall-    tests/freeze/*.dhall-    tests/lint/success/*.dhall-    tests/recursive/*.dhall-    tests/regression/*.dhall-    tests/tags/*.dhall-    tests/tags/*.tags-    tests/th/*.dhall-    tests/tutorial/*.dhall+    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@@ -438,67 +187,96 @@   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 -Library-    Hs-Source-Dirs: src+Flag network-tests+  Description: Enable tests which depend on an internet connection+  Default:     True+  Manual:      True++Common common     Build-Depends:-        base                        >= 4.9.1.0  && < 5   ,-        aeson                       >= 1.0.0.0  && < 1.5 ,+        base                        >= 4.11.0.0 && < 5   ,+        aeson                       >= 1.0.0.0  && < 2.3 ,         aeson-pretty                               < 0.9 ,-        ansi-terminal               >= 0.6.3.1  && < 0.11,+        ansi-terminal               >= 0.6.3.1  && < 1.2 ,         atomic-write                >= 0.2.0.7  && < 0.3 ,-        bytestring                                 < 0.11,+        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.0.0  && < 0.7 ,+        containers                  >= 0.5.8.0  && < 0.9 ,         contravariant                              < 1.6 ,-        data-fix                                   < 0.3 ,-        deepseq                                    < 1.5 ,-        Diff                        >= 0.2      && < 0.5 ,+        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,-        filepath                    >= 1.4      && < 1.5 ,+        filepath                    >= 1.4      && < 1.6 ,         half                        >= 0.2.2.3  && < 0.4 ,         haskeline                   >= 0.7.2.1  && < 0.9 ,-        hashable                    >= 1.2      && < 1.4 ,-        lens-family-core            >= 1.0.0    && < 2.2 ,-        megaparsec                  >= 7        && < 8.1 ,-        memory                      >= 0.14     && < 0.16,-        mtl                         >= 2.2.1    && < 2.3 ,+        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.16,+        optparse-applicative        >= 0.14.0.0 && < 0.20,         parsers                     >= 0.12.4   && < 0.13,         parser-combinators                               ,-        prettyprinter               >= 1.5.1    && < 1.7 ,-        prettyprinter-ansi-terminal >= 1.1.1    && < 1.2 ,-        pretty-simple                              < 4   ,-        profunctors                 >= 3.1.2    && < 5.6 ,-        repline                     >= 0.2.1.0  && < 0.4 ,+        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 ,-        template-haskell            >= 2.11.1.0 && < 2.17,-        text                        >= 0.11.1.0 && < 1.3 ,-        text-manipulate             >= 0.2.0.1  && < 0.3 ,+        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 ,-        transformers                >= 0.2.0.0  && < 0.6 ,-        transformers-compat         >= 0.6.2    && < 0.7 ,+        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 ,-        uri-encode                                 < 1.6 ,-        vector                      >= 0.11.0.0 && < 0.13-    if !impl(ghc >= 8.0) && !impl(eta >= 0.8.4)-      Build-Depends: semigroups == 0.18.*-      Build-Depends: transformers == 0.4.2.*-      Build-Depends: fail == 4.9.*+        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:@@ -507,12 +285,14 @@     else       Hs-Source-Dirs: ghc-src       Build-Depends:-        cryptonite                  >= 0.23     && < 1.0+        cryptohash-sha256       if flag(with-http)         Build-Depends:           http-types                  >= 0.7.0    && < 0.13,-          http-client                 >= 0.4.30   && < 0.7 ,-          http-client-tls             >= 0.2.0    && < 0.4+          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@@ -555,13 +335,17 @@         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@@ -577,12 +361,39 @@         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         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:@@ -592,120 +403,95 @@         Dhall.Import.HTTP         Dhall.Import.Manager -    GHC-Options: -Wall -fwarn-incomplete-uni-patterns     Default-Language: Haskell2010  Executable dhall+    Import: common     Hs-Source-Dirs: dhall     Main-Is: Main.hs-    Build-Depends: base, dhall-    GHC-Options: -Wall -rtsopts+    Build-Depends: dhall+    GHC-Options: -rtsopts     Default-Language: Haskell2010  Test-Suite tasty+    Import: common     Type: exitcode-stdio-1.0     Hs-Source-Dirs: tests     Main-Is: Dhall/Test/Main.hs-    GHC-Options: -Wall     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.TH         Dhall.Test.Tutorial         Dhall.Test.TypeInference         Dhall.Test.Util+    if !flag(cross)+        Other-Modules:+            Dhall.Test.TH     Build-Depends:-        base                      >= 4        && < 5   ,-        bytestring                               < 0.11,-        cborg                     >= 0.2.0.0  && < 0.3 ,-        containers                                     ,-        data-fix                                       ,-        deepseq                   >= 1.2.0.1  && < 1.5 ,         dhall                                          ,-        directory                                      ,-        either                                         ,-        filepath                                       ,         foldl                                    < 1.5 ,-        generic-random            >= 1.3.0.0  && < 1.4 ,-        lens-family-core                               ,-        megaparsec                                     ,-        prettyprinter                                  ,-        QuickCheck                >= 2.10     && < 2.15,+        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 ,-        scientific                                     ,-        semigroups                                     ,-        serialise                                      ,         special-values                           < 0.2 ,         spoon                                    < 0.4 ,-        tasty                     >= 0.11.2   && < 1.3 ,-        tasty-expected-failure                   < 0.12,+        tasty                     >= 0.11.2   && < 1.6 ,+        tasty-expected-failure                   < 0.13,         tasty-hunit               >= 0.10     && < 0.11,-        tasty-quickcheck          >= 0.9.2    && < 0.11,-        template-haskell                               ,-        text                      >= 0.11.1.0 && < 1.3 ,-        transformers                                   ,-        turtle                                   < 1.6 ,-        unordered-containers                           ,-        vector                    >= 0.11.0.0 && < 0.13-    if flag(with-http)-      CPP-Options:-        -DWITH_HTTP+        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  Test-Suite doctest+    Import: common     Type: exitcode-stdio-1.0     Hs-Source-Dirs: doctest     Main-Is: Main.hs-    GHC-Options: -Wall     Build-Depends:-        base                          ,-        directory                     ,-        filepath                < 1.5 ,         mockery                 < 0.4 ,-        doctest   >= 0.7.0   && < 0.17-    Default-Language: Haskell2010-    -- `doctest` doesn't work with `MIN_VERSION` macros before GHC 8-    ---    --  See: https://ghc.haskell.org/trac/ghc/ticket/10970-    if impl(ghc < 8.0)+        doctest   >= 0.7.0+    if os(windows)+      -- https://github.com/dhall-lang/dhall-haskell/issues/2237       Buildable: False+    Default-Language: Haskell2010  Benchmark dhall-parser+    Import: common     Type: exitcode-stdio-1.0     Hs-Source-Dirs: benchmark/parser     Main-Is: Main.hs     Build-Depends:-        base                      >= 4        && < 5  ,-        bytestring                                    ,-        containers                >= 0.5.0.0  && < 0.7,         dhall                                         ,-        directory                                     ,-        gauge                     >= 0.2.3    && < 0.3,-        serialise                                     ,-        text                      >= 0.11.1.0 && < 1.3+        tasty-bench               >= 0.4      && < 0.5,     Default-Language: Haskell2010     Other-Extensions:         TypeApplications-    ghc-options: -rtsopts+    Ghc-Options: -rtsopts  Benchmark deep-nested-large-record+    Import: common     Type: exitcode-stdio-1.0     Hs-Source-Dirs: benchmark/deep-nested-large-record     Main-Is: Main.hs     Build-Depends:-        base                      >= 4        && < 5  ,-        containers                >= 0.5.0.0  && < 0.7,         dhall                                         ,-        gauge                     >= 0.2.3    && < 0.3+        tasty-bench               >= 0.4      && < 0.5,     Default-Language: Haskell2010
doctest/Main.hs view
@@ -1,23 +1,26 @@ {-# LANGUAGE CPP #-} -module Main where+module Main (main) where -import Data.Monoid ((<>)) import System.FilePath ((</>))  import qualified GHC.IO.Encoding import qualified System.Directory+import qualified System.Environment import qualified System.IO-import qualified Test.Mockery.Directory import qualified Test.DocTest+import qualified Test.Mockery.Directory  main :: IO () main = do-   -    GHC.IO.Encoding.setLocaleEncoding System.IO.utf8 -    pwd    <- System.Directory.getCurrentDirectory+    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"@@ -32,10 +35,12 @@           , "in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person"           ] -        Test.DocTest.doctest+        Test.DocTest.doctest $             [ "-DWITH_HTTP"+            , "-DUSE_HTTP_CLIENT_TLS"             , "--fast"-            , prefix </> "ghc-src"+            ] <> args <>+            [ prefix </> "ghc-src"              -- Unfortunately we cannot target the entire @src@ directory.             -- The reason is that src/Dhall/Version.hs depends on@@ -44,11 +49,11 @@             -- Instead, we target a selection of modules whose combined module             -- dependency tree covers all modules that contain doctests. -            -- , prefix </> "src"-            , "-i" <> (prefix </> "src")+            -- , src+            , "-i" <> src #if __GLASGOW_HASKELL__ >= 806-            , prefix </> "src/Dhall/Deriving.hs"+            , src </> "Dhall/Deriving.hs" #endif-            , prefix </> "src/Dhall/Tags.hs"-            , prefix </> "src/Dhall/Tutorial.hs"+            , src </> "Dhall/Tags.hs"+            , src </> "Dhall/Tutorial.hs"             ]
ghc-src/Dhall/Crypto.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}  {-| This module provides implementations of cryptographic utilities that only@@ -9,35 +10,38 @@       SHA256Digest(..)     , sha256DigestFromByteString     , sha256Hash+    , toString     ) where -import Control.DeepSeq (NFData)-import Crypto.Hash (SHA256)-import Data.ByteArray (ByteArrayAccess, convert)-import Data.ByteArray.Encoding (Base(Base16), convertToBase)-import Data.ByteString (ByteString)-import GHC.Generics (Generic)+import Control.DeepSeq         (NFData)+import Data.ByteString         (ByteString)+import Data.Data               (Data)+import GHC.Generics            (Generic) -import qualified Crypto.Hash-import qualified Data.ByteString.Char8 as ByteString.Char8+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 (Eq, Generic, Ord, NFData, ByteArrayAccess)+  deriving (Data, Eq, Generic, Ord, NFData)  instance Show SHA256Digest where-  show (SHA256Digest bytes) = ByteString.Char8.unpack $ convertToBase Base16 bytes+  show = toString  {-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning     `Nothing` if the conversion fails -} sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest-sha256DigestFromByteString bytes = SHA256Digest . convert <$> mh-  where-    mh = Crypto.Hash.digestFromByteString bytes :: Maybe (Crypto.Hash.Digest SHA256)+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 bytes = SHA256Digest $ convert h-  where-    h = Crypto.Hash.hash bytes :: Crypto.Hash.Digest SHA256+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
@@ -1,49 +1,50 @@-{-# LANGUAGE CPP               #-}+{-# 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.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.Semigroup ((<>))-+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-    ( Import(..)-    , ImportHashed(..)-    , ImportType(..)-    , Scheme(..)-    , URL(..)+    ( Expr (..)+    , Directory (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , Scheme (..)+    , URL (..)     )-import Dhall.URL (renderURL)+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 Dhall.Import.Types--import qualified Control.Exception-import qualified Data.List.NonEmpty               as NonEmpty-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Encoding--#if MIN_VERSION_http_client(0,5,0)-import Network.HTTP.Client-    (HttpException(..), HttpExceptionContent(..), Manager)-#else-import Network.HTTP.Client (HttpException(..), Manager)-#endif--import qualified Network.HTTP.Client                     as HTTP-import qualified Network.HTTP.Client.TLS                 as HTTP+import qualified Network.HTTP.Client              as HTTP import qualified Network.HTTP.Types  mkPrettyHttpException :: String -> HttpException -> PrettyHttpException@@ -51,7 +52,6 @@     PrettyHttpException (renderPrettyHttpException url ex) (toDyn ex)  renderPrettyHttpException :: String -> HttpException -> String-#if MIN_VERSION_http_client(0,5,0) renderPrettyHttpException _ (InvalidUrlException _ r) =       "\n"   <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"@@ -74,6 +74,11 @@       <>  "\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@@ -150,47 +155,24 @@                      prefixedText = Text.unlines prefixedLines -    e' -> "\n" <> show e' <> "\n"-#else-renderPrettyHttpException url e = case e of-    FailedConnectionException2 _ _ _ e' ->-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Wrong host:\n"-        <>  "\n"-        <>  "Host: " <> show e' <> "\n"-    InvalidDestinationHost host ->-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Invalid host name:\n"-        <>  "\n"-        <>  "Host: " <> show host <> "\n"-    ResponseTimeout ->-            "\ESC[1;31mError\ESC[0m: The host took too long to respond\n"-        <>  "\n"-        <>  "URL: " <> url <> "\n"-    e' ->   "\n"-        <>  show e' <> "\n"-#endif+    e' -> "\n"+      <>  "\ESC[1;31mError\ESC[0m: " <> show e'+      <>  "\n"+      <>  "URL: " <> url <> "\n"  newManager :: StateT Status IO Manager newManager = 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-     Status { _manager = oldManager, ..} <- State.get      case oldManager of         Nothing -> do-            manager <- liftIO (HTTP.newManager settings)+            manager <- liftIO _newManager              State.put (Status { _manager = Just manager , ..})              return manager -        Just manager -> do+        Just manager ->             return manager  data NotCORSCompliant = NotCORSCompliant@@ -268,20 +250,36 @@                 Control.Exception.throwIO (NotCORSCompliant {..}) corsCompliant _ _ _ = return () -type HTTPHeader = Network.HTTP.Types.Header+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 -fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text-fetchFromHttpUrl childURL mheaders = do+        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) -    request <- liftIO (HTTP.parseUrlThrow childURLString)+    baseRequest <- liftIO (HTTP.parseUrlThrow childURLString) -    let requestWithHeaders =-            case mheaders of-              Nothing      -> request-              Just headers -> request { HTTP.requestHeaders = headers }+    let requestWithHeaders = addHeaders originHeaders mheaders baseRequest      let io = HTTP.httpLbs requestWithHeaders manager @@ -293,14 +291,30 @@      Status {..} <- State.get -    let Chained parentImport = NonEmpty.head _stack+    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) -    let parentImportType = importType (importHashed parentImport)+            corsCompliant parentImportType childURL (HTTP.responseHeaders response)+        _ -> do+            return () -    corsCompliant parentImportType childURL (HTTP.responseHeaders response)+    return (ByteString.Lazy.toStrict (HTTP.responseBody response)) -    let bytes = HTTP.responseBody response+fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text+fetchFromHttpUrl childURL mheaders = do+    bytes <- fetchFromHttpUrlBytes childURL mheaders -    case Data.Text.Lazy.Encoding.decodeUtf8' bytes of+    case Data.Text.Encoding.decodeUtf8' bytes of         Left  err  -> liftIO (Control.Exception.throwIO err)-        Right text -> return (Data.Text.Lazy.toStrict text)+        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
@@ -1,14 +1,33 @@-{-| Both the GHC and GHCJS implementations of "Dhall.Import.Manager" export a-    `Manager` type suitable for use within the "Dhall.Import" module+{-# LANGUAGE CPP #-} -    For the GHC implementation the `Manager` type is a real `Manager` from the-    @http-client@ package.  For the GHCJS implementation the `Manager` type is-    a synonym for @`Data.Void.Void`@ since GHCJS does not use a `Manager` for-    HTTP requests.+{-| 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)+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
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE JavaScriptFFI #-}+{-# LANGUAGE JavaScriptFFI              #-}  {-| This module provides implementations of cryptographic utilities that only     work for GHCJS@@ -12,32 +13,32 @@     , sha256Hash     ) where -import Control.DeepSeq (NFData)-import Data.ByteArray (ByteArrayAccess)-import Data.ByteArray.Encoding (Base(Base16), convertToBase)-import Data.ByteString (ByteString)-import GHC.Generics (Generic)+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 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 (Eq, Generic, Ord, NFData, ByteArrayAccess)+  deriving (Data, Eq, Generic, Ord, NFData)  instance Show SHA256Digest where-  show (SHA256Digest bytes) = ByteString.Char8.unpack $ convertToBase Base16 bytes+  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+  | 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
ghcjs-src/Dhall/Import/HTTP.hs view
@@ -1,33 +1,24 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards   #-}  module Dhall.Import.HTTP     ( fetchFromHttpUrl-    , Manager+    , fetchFromHttpUrlBytes+    , originHeadersFileExpr     ) where -import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.IO.Class           (MonadIO (..)) import Control.Monad.Trans.State.Strict (StateT)-import Data.ByteString (ByteString)-import Data.CaseInsensitive (CI)-import Data.Semigroup ((<>))+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          as Text+import qualified Data.Text.Encoding as Text.Encoding import qualified JavaScript.XHR -import Data.Void (Void)-import Dhall.Core (URL(..))-import Dhall.URL (renderURL)-import Dhall.Import.Types--{-| The GHCJS implementation does not require a `Manager`--    The purpose of this synonym is so that "Dhall.Import.Types" can import a-    `Manager` type from "Dhall.Import.HTTP" that does the correct thing for-    both the GHC and GHCJS implementations--}-type Manager = Void- fetchFromHttpUrl     :: URL     -> Maybe [(CI ByteString, ByteString)]@@ -46,5 +37,16 @@         _   -> fail (childURLString <> " returned a non-200 status code: " <> show statusCode)      return body-fetchFromHttpUrl _ _ = do+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
@@ -1,17 +1,26 @@-{-| Both the GHC and GHCJS implementations of "Dhall.Import.Manager" export a-    `Manager` type suitable for use within the "Dhall.Import" module+{-| 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 `Manager` type is a real `Manager` from the-    @http-client@ package.  For the GHCJS implementation the `Manager` type is-    a synonym for @`Data.Void.Void`@ since GHCJS does not use a `Manager` for-    HTTP requests.+    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 -import Data.Void (Void)+{-| The GHCJS implementation does not require a `Network.HTTP.Client.Manager` --- | GHCJS does not use a `Manager`-type Manager = Void+    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
@@ -97,4 +97,4 @@ .SH BUGS .PP Please report any bugs you may come across to-https://github.com/dhall-language/dhall-haskell/issues.+https://github.com/dhall-lang/dhall-haskell/issues.
src/Dhall.hs view
@@ -1,2638 +1,579 @@-{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DefaultSignatures          #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiWayIf                 #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE PolyKinds                  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE RecordWildCards            #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE TypeOperators              #-}-{-# LANGUAGE TupleSections              #-}-{-# 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-    , rootDirectory-    , sourceName-    , startingContext-    , substitutions-    , normalizer-    , defaultInputSettings-    , InputSettings-    , defaultEvaluateSettings-    , EvaluateSettings-    , HasEvaluateSettings-    , detailed--    -- * Decoders-    , Decoder (..)-    , RecordDecoder(..)-    , UnionDecoder(..)-    , Encoder(..)-    , FromDhall(..)-    , Interpret-    , InvalidDecoder(..)-    , ExtractErrors(..)-    , ExtractError(..)-    , Extractor-    , MonadicExtractor-    , typeError-    , extractError-    , toMonadic-    , fromMonadic-    , auto-    , genericAuto-    , genericAutoWith-    , InterpretOptions(..)-    , InputNormalizer(..)-    , defaultInputNormalizer-    , SingletonConstructors(..)-    , defaultInterpretOptions-    , bool-    , natural-    , integer-    , scientific-    , double-    , lazyText-    , strictText-    , maybe-    , sequence-    , list-    , vector-    , function-    , functionWith-    , setFromDistinctList-    , setIgnoringDuplicates-    , hashSetFromDistinctList-    , hashSetIgnoringDuplicates-    , Dhall.map-    , hashMap-    , pairFromMapEntry-    , unit-    , void-    , string-    , pair-    , record-    , field-    , union-    , constructor-    , GenericFromDhall(..)-    , GenericToDhall(..)--    , ToDhall(..)-    , Inject-    , inject-    , genericToDhall-    , genericToDhallWith-    , RecordEncoder(..)-    , encodeFieldWith-    , encodeField-    , recordEncoder-    , UnionEncoder(..)-    , encodeConstructorWith-    , encodeConstructor-    , unionEncoder-    , (>|<)--    -- * 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 Control.Monad (guard)-import Data.Coerce (coerce)-import Data.Either.Validation (Validation(..), eitherToValidation, validationToEither)-import Data.Fix (Fix(..))-import Data.Functor.Contravariant (Contravariant(..), (>$<), Op(..))-import Data.Functor.Contravariant.Divisible (Divisible(..), divided)-import Data.Hashable (Hashable)-import Data.List.NonEmpty (NonEmpty (..))-import Data.HashMap.Strict (HashMap)-import Data.Map (Map)-import Data.Monoid ((<>))-import Data.Scientific (Scientific)-import Data.Semigroup (Semigroup)-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)-import Data.Typeable (Typeable)-import Data.Vector (Vector)-import Data.Void (Void)-import Data.Word (Word8, Word16, Word32, Word64)-import Dhall.Syntax (Expr(..), Chunks(..), DhallDouble(..), Var(..))-import Dhall.Import (Imported(..))-import Dhall.Parser (Src(..))-import Dhall.TypeCheck (DetailedTypeError(..), TypeError)-import GHC.Generics-import Lens.Family (LensLike', view)-import Numeric.Natural (Natural)-import Prelude hiding (maybe, sequence)-import System.FilePath (takeDirectory)--import qualified Control.Applicative-import qualified Control.Exception-import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.Foldable-import qualified Data.Functor.Compose-import qualified Data.Functor.Product-import qualified Data.HashMap.Strict as HashMap-import qualified Data.Map-import qualified Data.Maybe-import qualified Data.List-import qualified Data.List.NonEmpty-import qualified Data.Semigroup-import qualified Data.Scientific-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.HashSet-import qualified Data.Text-import qualified Data.Text.IO-import qualified Data.Text.Lazy-import qualified Data.Vector-import qualified Data.Void-import qualified Dhall.Context-import qualified Dhall.Core-import qualified Dhall.Import-import qualified Dhall.Map-import qualified Dhall.Parser-import qualified Dhall.Pretty.Internal-import qualified Dhall.Substitution-import qualified Dhall.TypeCheck-import qualified Dhall.Util-import qualified Lens.Family---- $setup--- >>> :set -XOverloadedStrings--- >>> :set -XRecordWildCards--- >>> import Data.Word (Word8, Word16, Word32, Word64)--- >>> import Dhall.Pretty.Internal (prettyExpr)--{-| Useful synonym for the `Validation` type used when marshalling Dhall-    expressions--}-type Extractor s a = Validation (ExtractErrors s a)--{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall-    code--}-type MonadicExtractor s a = Either (ExtractErrors s a)--{-| Generate a type error during extraction by specifying the expected type-    and the actual type--}-typeError :: Expr s a -> Expr s a -> Extractor s a b-typeError expected actual =-    Failure . ExtractErrors . pure . TypeMismatch $ InvalidDecoder expected actual---- | Turn a `Text` message into an extraction failure-extractError :: Text -> Extractor s a b-extractError = Failure . ExtractErrors . pure . ExtractError---- | 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--{-| One or more errors returned from extracting a Dhall expression to a-    Haskell expression--}-newtype ExtractErrors s a = ExtractErrors-   { getErrors :: NonEmpty (ExtractError s a)-   } deriving Semigroup--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where-    show (ExtractErrors (e :| [])) = show e-    show (ExtractErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)-      where-        prefix =-            "Multiple errors were encountered during extraction: \n\-            \                                                    \n"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractErrors s a)--{-| 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)-  | ExtractError Text--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where-  show (TypeMismatch e)  = show e-  show (ExtractError es) =-      _ERROR <> ": Failed extraction                                                   \n\-      \                                                                                \n\-      \The expression type-checked successfully but the transformation to the target   \n\-      \type failed with the following error:                                           \n\-      \                                                                                \n\-      \" <> Data.Text.unpack es <> "\n\-      \                                                                                \n"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)--{-| Every `Decoder` must obey the contract that if an expression's type matches the-    the `expected` type then the `extract` function must not fail with a type error.-    If not, then this value is returned.--    This value indicates that an invalid `Decoder` was provided to the `input`-    function--}-data InvalidDecoder s a = InvalidDecoder-  { invalidDecoderExpected   :: Expr s a-  , invalidDecoderExpression :: Expr s a-  }-  deriving (Typeable)--instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where-    show InvalidDecoder { .. } =-        _ERROR <> ": Invalid Dhall.Decoder                                               \n\-        \                                                                                \n\-        \Every Decoder must provide an extract function that succeeds if an expression   \n\-        \matches the expected type.  You provided a Decoder that disobeys this contract  \n\-        \                                                                                \n\-        \The Decoder provided has the expected dhall type:                               \n\-        \                                                                                \n\-        \" <> show txt0 <> "\n\-        \                                                                                \n\-        \and it couldn't extract a value from the well-typed expression:                 \n\-        \                                                                                \n\-        \" <> show txt1 <> "\n\-        \                                                                                \n"-        where-          txt0 = Dhall.Util.insert invalidDecoderExpected-          txt1 = Dhall.Util.insert invalidDecoderExpression---- | @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-  :: (Functor f)-  => LensLike' f InputSettings FilePath-rootDirectory k s =-  fmap (\x -> s { _rootDirectory = x }) (k (_rootDirectory s))---- | 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-  :: (Functor f)-  => LensLike' f InputSettings FilePath-sourceName k s =-  fmap (\x -> s { _sourceName = x}) (k (_sourceName s))---- | @since 1.16-data EvaluateSettings = EvaluateSettings-  { _substitutions   :: Dhall.Substitution.Substitutions Src Void-  , _startingContext :: Dhall.Context.Context (Expr Src Void)-  , _normalizer      :: Maybe (Dhall.Core.ReifiedNormalizer Void)-  }---- | 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-  }---- | Access the starting context used for evaluation and type-checking.------ @since 1.16-startingContext-  :: (Functor f, HasEvaluateSettings s)-  => LensLike' f s (Dhall.Context.Context (Expr Src Void))-startingContext = evaluateSettings . l-  where-    l :: (Functor f)-      => LensLike' f EvaluateSettings (Dhall.Context.Context (Expr Src Void))-    l k s = fmap (\x -> s { _startingContext = x}) (k (_startingContext s))---- | Access the custom substitutions.------ @since 1.30-substitutions-  :: (Functor f, HasEvaluateSettings s)-  => LensLike' f s (Dhall.Substitution.Substitutions Src Void)-substitutions = evaluateSettings . l-  where-    l :: (Functor f)-      => LensLike' f EvaluateSettings (Dhall.Substitution.Substitutions Src Void)-    l k s = fmap (\x -> s { _substitutions = x }) (k (_substitutions s))---- | Access the custom normalizer.------ @since 1.16-normalizer-  :: (Functor f, HasEvaluateSettings s)-  => LensLike' f s (Maybe (Dhall.Core.ReifiedNormalizer Void))-normalizer = evaluateSettings . l-  where-    l :: (Functor f)-      => LensLike' f EvaluateSettings (Maybe (Dhall.Core.ReifiedNormalizer Void))-    l k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s))---- | @since 1.16-class HasEvaluateSettings s where-  evaluateSettings-    :: (Functor f)-    => LensLike' f s EvaluateSettings--instance HasEvaluateSettings InputSettings where-  evaluateSettings k s =-    fmap (\x -> s { _evaluateSettings = x }) (k (_evaluateSettings s))--instance HasEvaluateSettings EvaluateSettings where-  evaluateSettings = id--{-| 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 {..}) txt = do-    let suffix = Dhall.Pretty.Internal.prettyToStrictText expected-    let annotate substituted = case substituted of-            Note (Src begin end bytes) _ ->-                Note (Src begin end bytes') (Annot substituted expected)-              where-                bytes' = bytes <> " : " <> suffix-            _ ->-                Annot substituted expected--    normExpr <- inputHelper annotate settings txt--    case extract normExpr  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 = inputHelper id--{-| Helper function for the input* function family--@since 1.30--}-inputHelper-    :: (Expr Src Void -> Expr Src Void)-    -> InputSettings-    -> Text-    -- ^ The Dhall program-    -> IO (Expr Src Void)-    -- ^ The fully normalized AST-inputHelper annotate settings txt = do-    expr  <- Dhall.Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)--    let InputSettings {..} = settings--    let EvaluateSettings {..} = _evaluateSettings--    let transform =-               Lens.Family.set Dhall.Import.substitutions   _substitutions-            .  Lens.Family.set Dhall.Import.normalizer      _normalizer-            .  Lens.Family.set Dhall.Import.startingContext _startingContext--    let status = transform (Dhall.Import.emptyStatus _rootDirectory)--    expr' <- State.evalStateT (Dhall.Import.loadWith expr) status--    let substituted = Dhall.Substitution.substitute expr' $ view substitutions settings-    let annot = annotate substituted-    _ <- Dhall.Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot)-    pure (Dhall.Core.normalizeWith (view normalizer settings) substituted)---- | 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-    => 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 = do-    case extract (Dhall.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)--{-| 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 `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 :: Expr Src Void-    -- ^ Dhall type of the Haskell value-    }-    deriving (Functor)--{-| Decode a `Bool`-->>> input bool "True"-True--}-bool :: Decoder Bool-bool = Decoder {..}-  where-    extract (BoolLit b) = pure b-    extract expr        = typeError expected expr--    expected = Bool--{-| Decode a `Natural`-->>> input natural "42"-42--}-natural :: Decoder Natural-natural = Decoder {..}-  where-    extract (NaturalLit n) = pure n-    extract  expr             = typeError Natural expr--    expected = Natural--{-| Decode an `Integer`-->>> input integer "+42"-42--}-integer :: Decoder Integer-integer = Decoder {..}-  where-    extract (IntegerLit n) = pure n-    extract  expr          = typeError Integer expr--    expected = Integer--{-| Decode a `Scientific`-->>> input scientific "1e100"-1.0e100--}-scientific :: Decoder Scientific-scientific = fmap Data.Scientific.fromFloatDigits double--{-| Decode a `Double`-->>> input double "42.0"-42.0--}-double :: Decoder Double-double = Decoder {..}-  where-    extract (DoubleLit (DhallDouble n)) = pure n-    extract  expr                       = typeError Double expr--    expected = Double--{-| Decode lazy `Text`-->>> input lazyText "\"Test\""-"Test"--}-lazyText :: Decoder Data.Text.Lazy.Text-lazyText = fmap Data.Text.Lazy.fromStrict strictText--{-| Decode strict `Text`-->>> input strictText "\"Test\""-"Test"--}-strictText :: Decoder Text-strictText = Decoder {..}-  where-    extract (TextLit (Chunks [] t)) = pure t-    extract  expr = typeError Text expr--    expected = Text-{-| 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 (Dhall.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 "_" declared expectedIn--{-| Decode a `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 `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 `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 `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 Data.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@-->>> input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }"-fromList [("a",True),("b",False)]->>> input (Dhall.hashMap 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.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 <- Dhall.Map.lookup "mapKey" kvs-        , Just value <- Dhall.Map.lookup "mapValue" kvs-            = liftA2 (,) (extract k key) (extract v value)-    extractOut expr = typeError expectedOut expr--    expectedOut = Record (Dhall.Map.fromList [("mapKey", expected k), ("mapValue", expected v)])--{-| Decode @()@ from an empty record.-->>> input unit "{=}"  -- GHC doesn't print the result if it is ()---}-unit :: Decoder ()-unit = Decoder extractOut expectedOut-  where-    extractOut (RecordLit fields)-        | Data.Foldable.null fields = pure ()-    extractOut expr = typeError (Record mempty) expr--    expectedOut = Record mempty--{-| Decode 'Void' from an empty union.--Since @<>@ is uninhabited, @'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) $ Dhall.Map.lookup "_1" fields)-          <*> ( Data.Maybe.maybe (typeError expectedOut expr) (extract r) $ Dhall.Map.lookup "_2" fields)-    extractOut expr = typeError expectedOut expr--    expectedOut =-        Record-            (Dhall.Map.fromList-                [ ("_1", expected l)-                , ("_2", expected r)-                ]-            )--{-| Any value that implements `FromDhall` can be automatically decoded based on-    the inferred return type of `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' 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 (Rep a)) => InputNormalizer -> Decoder a-    autoWith _ = genericAuto--{-| A compatibility alias for `FromDhall`--This will eventually be removed.--}-type Interpret = FromDhall--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 Integer where-    autoWith _ = integer--instance FromDhall Scientific where-    autoWith _ = scientific--instance FromDhall Double where-    autoWith _ = double--instance {-# OVERLAPS #-} FromDhall [Char] where-    autoWith _ = string--instance FromDhall Data.Text.Lazy.Text where-    autoWith _ = lazyText--instance FromDhall Text where-    autoWith _ = strictText--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)--{-| 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.map (autoWith inputNormalizer) (autoWith inputNormalizer)--instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where-    autoWith inputNormalizer = Dhall.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)--{-| Use the default input normalizer for interpreting a configuration file--> auto = autoWith defaultInputNormalizer--}-auto :: FromDhall a => Decoder a-auto = autoWith defaultInputNormalizer--{-| This type is exactly the same as `Data.Fix.Fix` except with a different-    `FromDhall` instance.  This intermediate type simplifies the implementation-    of the inner loop for the `FromDhall` instance for `Fix`--}-newtype Result f = Result { _unResult :: f (Result f) }--resultToFix :: Functor f => Result f -> Fix f-resultToFix (Result x) = Fix (fmap resultToFix x)--instance FromDhall (f (Result f)) => FromDhall (Result f) where-    autoWith inputNormalizer = Decoder { expected = expected_, extract = extract_ }-      where-        expected_ = "result"--        extract_ (App _ expression) = do-            fmap Result (extract (autoWith inputNormalizer) expression)-        extract_ expression = do-            typeError expression expected_---- | 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.cata 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 { expected = expected_, extract = extract_ }-      where-        expected_ =-            Pi "result" (Const Dhall.Core.Type)-                (Pi "Make" (Pi "_" (expected (autoWith inputNormalizer :: Decoder (f (Result f)))) "result")-                    "result"-                )--        extract_ expression0 = extract0 expression0-          where-            die = typeError expected_ expression0--            extract0 (Lam x _ expression) = extract1 (rename x "result" expression)-            extract0  _                   = die--            extract1 (Lam y _ expression) = extract2 (rename y "Make" expression)-            extract1  _                   = die--            extract2 expression = fmap resultToFix (extract (autoWith inputNormalizer) expression)--            rename a b expression-                | a /= b    = Dhall.Core.subst (V a 0) (Var (V b 0)) (Dhall.Core.shift 1 (V b 0) expression)-                | otherwise = expression--{-| `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 (Rep a)) => Decoder a-genericAuto = genericAutoWith defaultInterpretOptions--{-| `genericAutoWith` is a configurable version of `genericAuto`.--}-genericAutoWith :: (Generic a, GenericFromDhall (Rep a)) => InterpretOptions -> Decoder a-genericAutoWith options = fmap to (evalState (genericAutoWithNormalizer defaultInputNormalizer options) 1)---{-| Use these options to tweak how Dhall derives a generic implementation of-    `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 `FromDhall` instance for functions in order---   to normalize the function input before marshaling the input into a---   Dhall expression-newtype InputNormalizer = InputNormalizer-  { getInputNormalizer :: Dhall.Core.ReifiedNormalizer Void }---- | Default normalization-related settings (no custom normalization)-defaultInputNormalizer :: InputNormalizer-defaultInputNormalizer = InputNormalizer- { getInputNormalizer = Dhall.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-    }--{-| This is the underlying class that powers the `FromDhall` class's support-    for automatically deriving a generic implementation--}-class GenericFromDhall f where-    genericAutoWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))--instance GenericFromDhall f => GenericFromDhall (M1 D d f) where-    genericAutoWithNormalizer inputNormalizer options = do-        res <- genericAutoWithNormalizer inputNormalizer options-        pure (fmap M1 res)--instance GenericFromDhall V1 where-    genericAutoWithNormalizer _ _ = pure Decoder {..}-      where-        extract expr = typeError expected expr--        expected = Union mempty--unsafeExpectUnion-    :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))-unsafeExpectUnion _ (Union kts) =-    kts-unsafeExpectUnion name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)--unsafeExpectRecord-    :: Text -> Expr Src Void -> Dhall.Map.Map Text (Expr Src Void)-unsafeExpectRecord _ (Record kts) =-    kts-unsafeExpectRecord name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)--unsafeExpectUnionLit-    :: Text-    -> Expr Src Void-    -> (Text, Maybe (Expr Src Void))-unsafeExpectUnionLit _ (Field (Union _) k) =-    (k, Nothing)-unsafeExpectUnionLit _ (App (Field (Union _) k) v) =-    (k, Just v)-unsafeExpectUnionLit name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)--unsafeExpectRecordLit-    :: Text -> Expr Src Void -> Dhall.Map.Map Text (Expr Src Void)-unsafeExpectRecordLit _ (RecordLit kvs) =-    kvs-unsafeExpectRecordLit name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.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-extractUnionConstructor-    :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))-extractUnionConstructor (App (Field (Union kts) fld) e) =-  return (fld, e, Dhall.Map.delete fld kts)-extractUnionConstructor (Field (Union kts) fld) =-  return (fld, RecordLit mempty, Dhall.Map.delete fld kts)-extractUnionConstructor _ =-  empty--class GenericFromDhallUnion f where-    genericUnionAutoWithNormalizer :: InputNormalizer -> InterpretOptions -> UnionDecoder (f a)--instance (GenericFromDhallUnion f1, GenericFromDhallUnion f2) => GenericFromDhallUnion (f1 :+: f2) where-  genericUnionAutoWithNormalizer inputNormalizer options =-    (<>)-      (L1 <$> genericUnionAutoWithNormalizer inputNormalizer options)-      (R1 <$> genericUnionAutoWithNormalizer inputNormalizer options)--instance (Constructor c1, GenericFromDhall f1) => GenericFromDhallUnion (M1 C c1 f1) where-  genericUnionAutoWithNormalizer inputNormalizer options@(InterpretOptions {..}) =-    constructor name (evalState (genericAutoWithNormalizer inputNormalizer options) 1)-    where-      n :: M1 C c1 f1 a-      n = undefined--      name = constructorModifier (Data.Text.pack (conName n))--instance GenericFromDhallUnion (f :+: g) => GenericFromDhall (f :+: g) where-  genericAutoWithNormalizer inputNormalizer options =-    pure (union (genericUnionAutoWithNormalizer inputNormalizer options))--instance GenericFromDhall f => GenericFromDhall (M1 C c f) where-    genericAutoWithNormalizer inputNormalizer options = do-        res <- genericAutoWithNormalizer inputNormalizer options-        pure (fmap M1 res)--instance GenericFromDhall U1 where-    genericAutoWithNormalizer _ _ = pure (Decoder {..})-      where-        extract _ = pure U1--        expected = Record (Dhall.Map.fromList [])--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)--instance (GenericFromDhall (f :*: g), GenericFromDhall (h :*: i)) => GenericFromDhall ((f :*: g) :*: (h :*: i)) where-    genericAutoWithNormalizer inputNormalizer options = do-        Decoder extractL expectedL <- genericAutoWithNormalizer inputNormalizer options-        Decoder extractR expectedR <- genericAutoWithNormalizer 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 (f :*: g), Selector s, FromDhall a) => GenericFromDhall ((f :*: g) :*: M1 S s (K1 i a)) where-    genericAutoWithNormalizer inputNormalizer options@InterpretOptions{..} = do-        let nR :: M1 S s (K1 i a) r-            nR = undefined--        nameR <- fmap fieldModifier (getSelName nR)--        Decoder extractL expectedL <- genericAutoWithNormalizer inputNormalizer options--        let Decoder extractR expectedR = autoWith inputNormalizer--        let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" expectedL--        let expected = Record (Dhall.Map.insert nameR expectedR ktsL)--        let extract expression = do-                let die = typeError expected expression--                case expression of-                    RecordLit kvs ->-                        case 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 (f :*: g)) => GenericFromDhall (M1 S s (K1 i a) :*: (f :*: g)) where-    genericAutoWithNormalizer 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 inputNormalizer options--        let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" expectedR--        let expected = Record (Dhall.Map.insert nameL expectedL ktsR)--        let extract expression = do-                let die = typeError expected expression--                case expression of-                    RecordLit kvs ->-                        case Dhall.Map.lookup nameL kvs of-                            Just expressionL ->-                                liftA2 (:*:)-                                    (fmap (M1 . K1) (extractL expressionL))-                                    (extractR expression)-                            _ -> die-                    _ -> die--        return (Decoder {..})--instance (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall (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 =-                Record-                    (Dhall.Map.fromList-                        [ (nameL, expectedL)-                        , (nameR, expectedR)-                        ]-                    )--        let extract expression = do-                let die = typeError expected expression--                case expression of-                    RecordLit kvs -> do-                        case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of-                            Just (expressionL, expressionR) ->-                                liftA2 (:*:)-                                    (fmap (M1 . K1) (extractL expressionL))-                                    (fmap (M1 . K1) (extractR expressionR))-                            Nothing -> die-                    _ -> die--        return (Decoder {..})--instance (Selector s, FromDhall a) => GenericFromDhall (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 expected')--        let extract0 expression = fmap (M1 . K1) (extract' expression)--        let extract1 expression = do-                let die = typeError expected expression--                case expression of-                    RecordLit kvs -> do-                        case Dhall.Map.lookup name kvs of-                            Just subExpression ->-                                fmap (M1 . K1) (extract' subExpression)-                            Nothing ->-                                die-                    _ -> do-                        die---        let extract =-                case singletonConstructors of-                    Bare                    -> extract0-                    Smart | selName n == "" -> extract0-                    _                       -> extract1--        return (Decoder {..})--{-| 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 `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' 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`--This will eventually be removed.--}-type Inject = ToDhall--{-| Use the default input normalizer for injecting a value--> inject = injectWith defaultInputNormalizer--}-inject :: ToDhall a => Encoder a-inject = injectWith defaultInputNormalizer--{-| 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-    = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer defaultInputNormalizer options) 1)--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.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--{-|-->>> embed inject (12 :: Word)-NaturalLit 12--}--instance ToDhall Word where-    injectWith _ = Encoder {..}-      where-        embed = NaturalLit . fromIntegral--        declared = Natural--{-|-->>> embed inject (12 :: Word8)-NaturalLit 12--}--instance ToDhall Word8 where-    injectWith _ = Encoder {..}-      where-        embed = NaturalLit . fromIntegral--        declared = Natural--{-|-->>> embed inject (12 :: Word16)-NaturalLit 12--}--instance ToDhall Word16 where-    injectWith _ = Encoder {..}-      where-        embed = NaturalLit . fromIntegral--        declared = Natural--{-|-->>> embed inject (12 :: Word32)-NaturalLit 12--}--instance ToDhall Word32 where-    injectWith _ = Encoder {..}-      where-        embed = NaturalLit . fromIntegral--        declared = 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--{-| 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-->>> let x = Data.HashSet.fromList ["hi", "mom" :: Text]->>> prettyExpr $ embed inject x-[ "mom", "hi" ]---}-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", declaredK), ("mapValue", declaredV)]))--        mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList-        recordPair (k, v) = RecordLit (Dhall.Map.fromList-                                [("mapKey", embedK k), ("mapValue", 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", declaredK), ("mapValue", declaredV)]))--        mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList-        recordPair (k, v) = RecordLit (Dhall.Map.fromList-                                [("mapKey", embedK k), ("mapValue", embedV v)])--        Encoder embedK declaredK = injectWith inputNormalizer-        Encoder embedV declaredV = injectWith inputNormalizer--{-| This is the underlying class that powers the `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 (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 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 keyL-                Just valL ->-                    App (Field declared keyL) valL--        embed (R1 (M1 r)) =-            case notEmptyRecordLit (embedR r) of-                Nothing ->-                    Field declared keyR-                Just valR ->-                    App (Field declared 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 keyL-                Just valL -> App (Field declared keyL) valL-          where-            (keyL, maybeValL) =-              unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)-        embed (R1 (M1 r)) =-            case notEmptyRecordLit (embedR r) of-                Nothing   -> Field declared keyR-                Just valR -> App (Field declared 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 keyL-                Just valL -> App (Field declared keyL) valL-        embed (R1 r) =-            case maybeValR of-                Nothing   -> Field declared keyR-                Just valR -> App (Field declared 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 keyL-                Just valL -> App (Field declared keyL) valL-          where-            (keyL, maybeValL) =-                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)-        embed (R1 r) =-            case maybeValR of-                Nothing   -> Field declared keyR-                Just valR -> App (Field declared 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 (embedR r) mapL)-              where-                mapL =-                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)--        let declared = Record (Dhall.Map.insert nameR 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 (embedL l) mapR)-              where-                mapR =-                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)--        let declared = Record (Dhall.Map.insert nameL 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, embedL l), (nameR, embedR r) ]-                    )--        let declared =-                Record-                    (Dhall.Map.fromList-                        [ (nameL, declaredL), (nameR, declaredR) ]-                    )--        return (Encoder {..})--instance GenericToDhall U1 where-    genericToDhallWithNormalizer _ _ = pure (Encoder {..})-      where-        embed _ = RecordLit mempty--        declared = Record mempty--{-| 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-                ( 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.Decoder a-record ( RecordDecoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Data.Functor.Compose.Compose extractF ) ) ) =-  Decoder-    { extract =-        extractF-    , expected =-        Record fields-    }----- | Parse a single field of a record.-field :: Text -> Decoder a -> RecordDecoder a-field key valueDecoder@(Decoder extract expected) =-  let-    extractBody expr@(RecordLit fields) = case Dhall.Map.lookup key fields of-      Just v -> extract v-      _ -> typeError expected expr-    extractBody expr = typeError expected expr-  in-    RecordDecoder-      ( Data.Functor.Product.Pair-          ( Control.Applicative.Const-              ( Dhall.Map.singleton-                  key-                  ( Dhall.expected valueDecoder )-              )-          )-          ( Data.Functor.Compose.Compose extractBody )-      )--{-| 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 Data.Semigroup.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))-    mappend = (Data.Semigroup.<>)---- | Run a 'UnionDecoder' to build a 'Decoder'.-union :: UnionDecoder a -> Decoder a-union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder-    { extract  = extractF-    , expected = Union expect-    }-  where-    expect = (notEmptyRecord . Dhall.expected) <$> mp--    extractF e0 =-      let result = do-            (fld, e1, rest) <- extractUnionConstructor e0--            t <- Dhall.Map.lookup fld mp--            guard $ Dhall.Core.Union rest `Dhall.Core.judgmentallyEqual`-                      Dhall.Core.Union (Dhall.Map.delete fld expect)-            pure (t, e1)-      in Data.Maybe.maybe (typeError (Union expect) e0) (uncurry extract) result---- | 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) )--{-| 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))-:}---}---- | Infix 'divided'-(>*<) :: Divisible f => f a -> f b -> f (a, b)-(>*<) = divided--infixr 5 >*<---- | Intermediate type used for building a `ToDhall` instance for a record-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--{-| 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--{-| 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---- | Convert a `RecordEncoder` into the equivalent `Encoder`-recordEncoder :: RecordEncoder a -> Encoder a-recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType-  where-    recordType = Record $ declared <$> encodeTypeRecord-    makeRecordLit x = RecordLit $ (($ x) . embed) <$> encodeTypeRecord--{-| '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)---- | 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 >|<---- | 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') name-                  Just val -> App (Field (Union fields') name) val-      , declared =-          Union fields'-      }-  where-    fields' = fmap notEmptyRecord fields--{-| 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 )-      )--{-| 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+{-# 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
@@ -1,8 +1,9 @@-{-# LANGUAGE BangPatterns       #-}-{-# LANGUAGE FlexibleContexts   #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}  {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -12,95 +13,66 @@ -}  module Dhall.Binary-    ( -- * Standard versions-      StandardVersion(..)-    , renderStandardVersion--    -- * Encoding and decoding-    , encodeExpression+    ( -- * Encoding and decoding+      encodeExpression     , decodeExpression -    -- * Exceptions+      -- * Exceptions     , DecodingFailure(..)     ) where -import Codec.CBOR.Decoding (Decoder, TokenType(..))-import Codec.CBOR.Encoding (Encoding)-import Codec.Serialise (Serialise(encode, decode))-import Control.Applicative (empty, (<|>))-import Control.Exception (Exception)+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(..)-    , Directory(..)-    , DhallDouble(..)-    , Expr(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , MultiLet(..)-    , PreferAnnotation(..)-    , Scheme(..)-    , URL(..)-    , Var(..)+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , FunctionBinding (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , MultiLet (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Scheme (..)+    , URL (..)+    , Var (..)+    , WithComponent (..)     ) -import Data.Foldable (toList, foldl')-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Void (Void, absurd)-import GHC.Float (double2Float, float2Double)-import Numeric.Half (fromHalf, toHalf)+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.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 Control.Monad        as Monad-import qualified Data.ByteArray+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.Text            as Text+import qualified Data.Time             as Time import qualified Dhall.Crypto import qualified Dhall.Map-import qualified Dhall.Set-import qualified Dhall.Syntax         as Syntax-import qualified Text.Printf          as Printf--{-| Supported version strings--    This exists primarily for backwards compatibility for expressions encoded-    before Dhall removed version tags from the binary encoding--}-data StandardVersion-    = NoVersion-    -- ^ No version string-    | V_5_0_0-    -- ^ Version "5.0.0"-    | V_4_0_0-    -- ^ Version "4.0.0"-    | V_3_0_0-    -- ^ Version "3.0.0"-    | V_2_0_0-    -- ^ Version "2.0.0"-    | V_1_0_0-    -- ^ Version "1.0.0"-    deriving (Enum, Bounded)---- | Render a `StandardVersion` as `Text`-renderStandardVersion :: StandardVersion -> Text-renderStandardVersion NoVersion = "none"-renderStandardVersion V_1_0_0   = "1.0.0"-renderStandardVersion V_2_0_0   = "2.0.0"-renderStandardVersion V_3_0_0   = "3.0.0"-renderStandardVersion V_4_0_0   = "4.0.0"-renderStandardVersion V_5_0_0   = "5.0.0"+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@@ -128,24 +100,24 @@          case tokenType₀ of             TypeUInt -> do-                !n <- Decoding.decodeWord+                !n <- fromIntegral <$> Decoding.decodeWord -                return (Var (V "_" (fromIntegral n)))+                return (Var (V "_" n))              TypeUInt64 -> do-                !n <- Decoding.decodeWord64+                !n <- fromIntegral <$> Decoding.decodeWord64 -                return (Var (V "_" (fromIntegral n)))+                return (Var (V "_" n))              TypeFloat16 -> do-                !n <- Decoding.decodeFloat+                !n <- float2Double <$> Decoding.decodeFloat -                return (DoubleLit (DhallDouble (float2Double n)))+                return (DoubleLit (DhallDouble n))              TypeFloat32 -> do-                !n <- Decoding.decodeFloat+                !n <- float2Double <$> Decoding.decodeFloat -                return (DoubleLit (DhallDouble (float2Double n)))+                return (DoubleLit (DhallDouble n))              TypeFloat64 -> do                 !n <- Decoding.decodeDouble@@ -158,45 +130,53 @@                 return (BoolLit b)              TypeString -> do-                s <- Decoding.decodeString+                !ba <- Decoding.decodeUtf8ByteArray -                case s of-                    "Natural/build"     -> return NaturalBuild-                    "Natural/fold"      -> return NaturalFold-                    "Natural/isZero"    -> return NaturalIsZero-                    "Natural/even"      -> return NaturalEven-                    "Natural/odd"       -> return NaturalOdd-                    "Natural/toInteger" -> return NaturalToInteger-                    "Natural/show"      -> return NaturalShow-                    "Natural/subtract"  -> return NaturalSubtract-                    "Integer/toDouble"  -> return IntegerToDouble-                    "Integer/clamp"     -> return IntegerClamp-                    "Integer/negate"    -> return IntegerNegate-                    "Integer/show"      -> return IntegerShow-                    "Double/show"       -> return DoubleShow-                    "List/build"        -> return ListBuild-                    "List/fold"         -> return ListFold-                    "List/length"       -> return ListLength-                    "List/head"         -> return ListHead-                    "List/last"         -> return ListLast-                    "List/indexed"      -> return ListIndexed-                    "List/reverse"      -> return ListReverse-                    "Optional/fold"     -> return OptionalFold-                    "Optional/build"    -> return OptionalBuild-                    "Bool"              -> return Bool-                    "Optional"          -> return Optional-                    "None"              -> return None-                    "Natural"           -> return Natural-                    "Integer"           -> return Integer-                    "Double"            -> return Double-                    "Text"              -> return Text-                    "Text/show"         -> return TextShow-                    "List"              -> return List-                    "Type"              -> return (Const Type)-                    "Kind"              -> return (Const Kind)-                    "Sort"              -> return (Const Sort)-                    _                   -> die ("Unrecognized built-in: " <> Text.unpack s)+                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 @@ -218,16 +198,16 @@                          case tokenType₂ of                             TypeUInt -> do-                                !n <- Decoding.decodeWord+                                !n <- fromIntegral <$> Decoding.decodeWord -                                return (Var (V x (fromIntegral n)))+                                return (Var (V x n))                              TypeUInt64 -> do-                                !n <- Decoding.decodeWord64+                                !n <- fromIntegral <$> Decoding.decodeWord64 -                                return (Var (V x (fromIntegral n)))+                                return (Var (V x n)) -                            _ -> do+                            _ ->                                 die ("Unexpected token type for variable index: " <> show tokenType₂)                      TypeUInt -> do@@ -235,24 +215,28 @@                          case tag of                             0 -> do-                                f <- go+                                !f <- go -                                xs <- Monad.replicateM (len - 2) go+                                let loop n !acc+                                        | n <= 0    = return acc+                                        | otherwise = do+                                              !x <- go+                                              loop (n - 1) (App acc x) -                                if null xs-                                    then die "Non-standard encoding of a function with no arguments"-                                    else return ()+                                let nArgs = len - 2 -                                return (foldl' App f xs)+                                if nArgs <= 0+                                    then die "Non-standard encoding of a function with no arguments"+                                    else loop nArgs f -                            1 -> do+                            1 ->                                 case len of                                     3 -> do                                         _A <- go                                          b <- go -                                        return (Lam "_" _A b)+                                        return (Lam mempty (Syntax.makeFunctionBinding "_" _A) b)                                      4 -> do                                         x <- Decoding.decodeString@@ -265,19 +249,19 @@                                          b <- go -                                        return (Lam x _A b)+                                        return (Lam mempty (Syntax.makeFunctionBinding x _A) b) -                                    _ -> do+                                    _ ->                                         die ("Incorrect number of tokens used to encode a λ expression: " <> show len) -                            2 -> do+                            2 ->                                 case len of                                     3 -> do                                         _A <- go                                          _B <- go -                                        return (Pi "_" _A _B)+                                        return (Pi mempty "_" _A _B)                                      4 -> do                                         x <- Decoding.decodeString@@ -290,9 +274,9 @@                                          _B <- go -                                        return (Pi x _A _B)+                                        return (Pi mempty x _A _B) -                                    _ -> do+                                    _ ->                                         die ("Incorrect number of tokens used to encode a ∀ expression: " <> show len)                              3 -> do@@ -307,11 +291,11 @@                                     5  -> return NaturalTimes                                     6  -> return TextAppend                                     7  -> return ListAppend-                                    8  -> return (Combine Nothing)-                                    9  -> return (Prefer PreferFromSource)-                                    10 -> return CombineTypes+                                    8  -> return (Combine mempty Nothing)+                                    9  -> return (Prefer mempty PreferFromSource)+                                    10 -> return (CombineTypes mempty)                                     11 -> return ImportAlt-                                    12 -> return Equivalent+                                    12 -> return (Equivalent mempty)                                     13 -> return RecordCompletion                                     _  -> die ("Unrecognized operator code: " <> show opcode) @@ -321,7 +305,7 @@                                  return (op l r) -                            4 -> do+                            4 ->                                 case len of                                     2 -> do                                         _T <- go@@ -331,8 +315,8 @@                                     _ -> do                                         Decoding.decodeNull -                                        xs <- Monad.replicateM (len - 2) go-                                        return (ListLit Nothing (Data.Sequence.fromList xs))+                                        xs <- Data.Sequence.replicateA (len - 2) go+                                        return (ListLit Nothing xs)                              5 -> do                                 Decoding.decodeNull@@ -347,7 +331,7 @@                                 u <- go                                  case len of-                                    3 -> do+                                    3 ->                                         return (Merge t u Nothing)                                      4 -> do@@ -355,30 +339,30 @@                                          return (Merge t u (Just _T)) -                                    _ -> do+                                    _ ->                                         die ("Incorrect number of tokens used to encode a `merge` expression: " <> show len)                              7 -> do                                 mapLength <- Decoding.decodeMapLen -                                xTs <- Monad.replicateM mapLength $ do+                                xTs <- replicateDecoder mapLength $ do                                     x <- Decoding.decodeString                                      _T <- go -                                    return (x, _T)+                                    return (x, Syntax.makeRecordField _T)                                  return (Record (Dhall.Map.fromList xTs))                              8 -> do                                 mapLength <- Decoding.decodeMapLen -                                xts <- Monad.replicateM mapLength $ do+                                xts <- replicateDecoder mapLength $ do                                     x <- Decoding.decodeString                                      t <- go -                                    return (x, t)+                                    return (x, Syntax.makeRecordField t)                                  return (RecordLit (Dhall.Map.fromList xts)) @@ -387,7 +371,7 @@                                  x <- Decoding.decodeString -                                return (Field t x)+                                return (Field t (Syntax.makeFieldSelection x))                              10 -> do                                 t <- go@@ -406,22 +390,22 @@                                              TypeString -> do                                                 x <- Decoding.decodeString-                                                return (Left (Dhall.Set.fromList [x]))+                                                return (Left [x]) -                                            _ -> do+                                            _ ->                                                 die ("Unexpected token type for projection: " <> show tokenType₂)                                      _ -> do-                                        xs <- Monad.replicateM (len - 2) Decoding.decodeString+                                        xs <- replicateDecoder (len - 2) Decoding.decodeString -                                        return (Left (Dhall.Set.fromList xs))+                                        return (Left xs)                                  return (Project t xs)                              11 -> do                                 mapLength <- Decoding.decodeMapLen -                                xTs <- Monad.replicateM mapLength $ do+                                xTs <- replicateDecoder mapLength $ do                                     x <- Decoding.decodeString                                      tokenType₂ <- Decoding.peekTokenType@@ -455,20 +439,20 @@                                  case tokenType₂ of                                     TypeUInt -> do-                                        n <- Decoding.decodeWord+                                        !n <- fromIntegral <$> Decoding.decodeWord -                                        return (NaturalLit (fromIntegral n))+                                        return (NaturalLit n)                                      TypeUInt64 -> do-                                        n <- Decoding.decodeWord64+                                        !n <- fromIntegral <$> Decoding.decodeWord64 -                                        return (NaturalLit (fromIntegral n))+                                        return (NaturalLit n)                                      TypeInteger -> do-                                        n <- Decoding.decodeInteger-                                        return (NaturalLit (fromIntegral n))+                                        !n <- fromIntegral <$> Decoding.decodeInteger+                                        return (NaturalLit n) -                                    _ -> do+                                    _ ->                                         die ("Unexpected token type for Natural literal: " <> show tokenType₂)                              16 -> do@@ -476,33 +460,33 @@                                  case tokenType₂ of                                     TypeUInt -> do-                                        n <- Decoding.decodeWord+                                        !n <- fromIntegral <$> Decoding.decodeWord -                                        return (IntegerLit (fromIntegral n))+                                        return (IntegerLit n)                                      TypeUInt64 -> do-                                        n <- Decoding.decodeWord64+                                        !n <- fromIntegral <$> Decoding.decodeWord64 -                                        return (IntegerLit (fromIntegral n))+                                        return (IntegerLit n)                                      TypeNInt -> do-                                        n <- Decoding.decodeNegWord+                                        !n <- fromIntegral <$> Decoding.decodeNegWord -                                        return (IntegerLit (-1 - fromIntegral n))+                                        return (IntegerLit $! (-1 - n))                                      TypeNInt64 -> do-                                        n <- Decoding.decodeNegWord64+                                        !n <- fromIntegral <$> Decoding.decodeNegWord64 -                                        return (IntegerLit (-1 - fromIntegral n))+                                        return (IntegerLit $! (-1 - n))                                     TypeInteger -> do                                         n <- Decoding.decodeInteger                                         return (IntegerLit n) -                                    _ -> do+                                    _ ->                                         die ("Unexpected token type for Integer literal: " <> show tokenType₂)                              18 -> do-                                xys <- Monad.replicateM ((len - 2) `quot` 2) $ do+                                xys <- replicateDecoder ((len - 2) `quot` 2) $ do                                     x <- Decoding.decodeString                                      y <- go@@ -518,11 +502,11 @@                                  return (Assert t) -                            24 -> do+                            24 ->                                 fmap Embed (decodeEmbed len)                              25 -> do-                                bindings <- Monad.replicateM ((len - 2) `quot` 3) $ do+                                bindings <- replicateDecoder ((len - 2) `quot` 3) $ do                                     x <- Decoding.decodeString                                      tokenType₂ <- Decoding.peekTokenType@@ -557,7 +541,7 @@                                 t <- go                                  mT <- case len of-                                    2 -> do+                                    2 ->                                         return Nothing                                      3 -> do@@ -565,7 +549,7 @@                                          return (Just _T) -                                    _ -> do+                                    _ ->                                         die ("Incorrect number of tokens used to encode a type annotation: " <> show len)                                  return (ToMap t mT)@@ -575,13 +559,117 @@                                  return (ListLit (Just _T) empty) -                            _ -> do+                            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) -                    _ -> do+                    _ ->                         die ("Unexpected tag type: " <> show tokenType₁) -            _ -> do+            _ ->                 die ("Unexpected initial token: " <> show tokenType₀)  encodeExpressionInternal :: (a -> Encoding) -> Expr Void a -> Encoding@@ -597,106 +685,124 @@             <>  Encoding.encodeInt n          NaturalBuild ->-            Encoding.encodeString "Natural/build"+            Encoding.encodeUtf8ByteArray "Natural/build"          NaturalFold ->-            Encoding.encodeString "Natural/fold"+            Encoding.encodeUtf8ByteArray "Natural/fold"          NaturalIsZero ->-            Encoding.encodeString "Natural/isZero"+            Encoding.encodeUtf8ByteArray "Natural/isZero"          NaturalEven ->-            Encoding.encodeString "Natural/even"+            Encoding.encodeUtf8ByteArray "Natural/even"          NaturalOdd ->-            Encoding.encodeString "Natural/odd"+            Encoding.encodeUtf8ByteArray "Natural/odd"          NaturalToInteger ->-            Encoding.encodeString "Natural/toInteger"+            Encoding.encodeUtf8ByteArray "Natural/toInteger"          NaturalShow ->-            Encoding.encodeString "Natural/show"+            Encoding.encodeUtf8ByteArray "Natural/show"          NaturalSubtract ->-            Encoding.encodeString "Natural/subtract"+            Encoding.encodeUtf8ByteArray "Natural/subtract"          IntegerToDouble ->-            Encoding.encodeString "Integer/toDouble"+            Encoding.encodeUtf8ByteArray "Integer/toDouble"          IntegerClamp ->-            Encoding.encodeString "Integer/clamp"+            Encoding.encodeUtf8ByteArray "Integer/clamp"          IntegerNegate ->-            Encoding.encodeString "Integer/negate"+            Encoding.encodeUtf8ByteArray "Integer/negate"          IntegerShow ->-            Encoding.encodeString "Integer/show"+            Encoding.encodeUtf8ByteArray "Integer/show"          DoubleShow ->-            Encoding.encodeString "Double/show"+            Encoding.encodeUtf8ByteArray "Double/show"          ListBuild ->-            Encoding.encodeString "List/build"+            Encoding.encodeUtf8ByteArray "List/build"          ListFold ->-            Encoding.encodeString "List/fold"+            Encoding.encodeUtf8ByteArray "List/fold"          ListLength ->-            Encoding.encodeString "List/length"+            Encoding.encodeUtf8ByteArray "List/length"          ListHead ->-            Encoding.encodeString "List/head"+            Encoding.encodeUtf8ByteArray "List/head"          ListLast ->-            Encoding.encodeString "List/last"+            Encoding.encodeUtf8ByteArray "List/last"          ListIndexed ->-            Encoding.encodeString "List/indexed"+            Encoding.encodeUtf8ByteArray "List/indexed"          ListReverse ->-            Encoding.encodeString "List/reverse"--        OptionalFold ->-            Encoding.encodeString "Optional/fold"--        OptionalBuild ->-            Encoding.encodeString "Optional/build"+            Encoding.encodeUtf8ByteArray "List/reverse"          Bool ->-            Encoding.encodeString "Bool"+            Encoding.encodeUtf8ByteArray "Bool" +        Bytes ->+            Encoding.encodeUtf8ByteArray "Bytes"+         Optional ->-            Encoding.encodeString "Optional"+            Encoding.encodeUtf8ByteArray "Optional"          None ->-            Encoding.encodeString "None"+            Encoding.encodeUtf8ByteArray "None"          Natural ->-            Encoding.encodeString "Natural"+            Encoding.encodeUtf8ByteArray "Natural"          Integer ->-            Encoding.encodeString "Integer"+            Encoding.encodeUtf8ByteArray "Integer"          Double ->-            Encoding.encodeString "Double"+            Encoding.encodeUtf8ByteArray "Double"          Text ->-            Encoding.encodeString "Text"+            Encoding.encodeUtf8ByteArray "Text" +        TextReplace ->+            Encoding.encodeUtf8ByteArray "Text/replace"+         TextShow ->-            Encoding.encodeString "Text/show"+            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.encodeString "List"+            Encoding.encodeUtf8ByteArray "List"          Const Type ->-            Encoding.encodeString "Type"+            Encoding.encodeUtf8ByteArray "Type"          Const Kind ->-            Encoding.encodeString "Kind"+            Encoding.encodeUtf8ByteArray "Kind"          Const Sort ->-            Encoding.encodeString "Sort"+            Encoding.encodeUtf8ByteArray "Sort"          a@App{} ->             encodeListN@@ -708,26 +814,26 @@           where             (function, arguments) = unApply a -        Lam "_" _A b ->+        Lam _ (FunctionBinding { functionBindingVariable = "_", functionBindingAnnotation = _A }) b ->             encodeList3                 (Encoding.encodeInt 1)                 (go _A)                 (go b) -        Lam x _A b ->+        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->             encodeList4                 (Encoding.encodeInt 1)                 (Encoding.encodeString x)                 (go _A)                 (go b) -        Pi "_" _A _B ->+        Pi _ "_" _A _B ->             encodeList3                 (Encoding.encodeInt 2)                 (go _A)                 (go _B) -        Pi x _A _B ->+        Pi _ x _A _B ->             encodeList4                 (Encoding.encodeInt 2)                 (Encoding.encodeString x)@@ -746,6 +852,11 @@         BoolNE l r ->             encodeOperator 3 l r +        BytesLit b ->+            encodeList2+                (Encoding.encodeInt 33)+                (Encoding.encodeBytes b)+         NaturalPlus l r ->             encodeOperator 4 l r @@ -758,19 +869,19 @@         ListAppend l r ->             encodeOperator 7 l r -        Combine _ l r ->+        Combine _ _ l r ->             encodeOperator 8 l r -        Prefer _ l r ->+        Prefer _ _ l r ->             encodeOperator 9 l r -        CombineTypes l r ->+        CombineTypes _ l r ->             encodeOperator 10 l r          ImportAlt l r ->             encodeOperator 11 l r -        Equivalent l r ->+        Equivalent _ l r ->             encodeOperator 12 l r          RecordCompletion l r ->@@ -814,14 +925,14 @@         Record xTs ->             encodeList2                 (Encoding.encodeInt 7)-                (encodeMapWith go xTs)+                (encodeMapWith (go . recordFieldValue) xTs)          RecordLit xts ->             encodeList2                 (Encoding.encodeInt 8)-                (encodeMapWith go xts)+                (encodeMapWith (go. recordFieldValue) xts) -        Field t x ->+        Field t (Syntax.fieldSelectionLabel -> x) ->             encodeList3                 (Encoding.encodeInt 9)                 (go t)@@ -829,10 +940,10 @@          Project t (Left xs) ->             encodeListN-                (2 + Dhall.Set.size xs)+                (2 + length xs)                 ( Encoding.encodeInt 10                 : go t-                : map Encoding.encodeString (Dhall.Set.toList xs)+                : map Encoding.encodeString xs                 )          Project t (Right _T) ->@@ -941,9 +1052,64 @@                 (go t)                 (go _T) -        a@With{} ->-            go (Syntax.desugarWith a)+        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 @@ -976,11 +1142,12 @@ encodeList4 a b c d = Encoding.encodeListLen 4 <> a <> b <> c <> d {-# INLINE encodeList4 #-} -encodeListN :: Int -> [ Encoding ] -> Encoding-encodeListN len xs = Encoding.encodeListLen (fromIntegral len) <> mconcat xs+encodeListN :: Foldable f => Int -> f Encoding -> Encoding+encodeListN len xs =+    Encoding.encodeListLen (fromIntegral len) <> Foldable.fold xs {-# INLINE encodeListN #-} -encodeList :: [ Encoding ] -> Encoding+encodeList :: Foldable f => f Encoding -> Encoding encodeList xs = encodeListN (length xs) xs {-# INLINE encodeList #-} @@ -1008,7 +1175,7 @@                 Nothing     -> die ("Invalid sha256 digest: " <> show bytes)                 Just digest -> return (Just digest) -        _ -> do+        _ ->             die ("Unexpected hash token: " <> show tokenType₀)      m <- Decoding.decodeWord@@ -1017,6 +1184,7 @@         0 -> return Code         1 -> return RawText         2 -> return Location+        3 -> return RawBytes         _ -> die ("Unexpected code for import mode: " <> show m)      let remote scheme = do@@ -1034,7 +1202,7 @@              authority <- Decoding.decodeString -            paths <- Monad.replicateM (len - 8) Decoding.decodeString+            paths <- replicateDecoder (len - 8) Decoding.decodeString              file <- Decoding.decodeString @@ -1044,7 +1212,7 @@                 TypeNull -> do                     Decoding.decodeNull                     return Nothing-                _ -> do+                _ ->                     fmap Just Decoding.decodeString              let components = reverse paths@@ -1054,7 +1222,7 @@             return (Remote (URL {..}))      let local prefix = do-            paths <- Monad.replicateM (len - 5) Decoding.decodeString+            paths <- replicateDecoder (len - 5) Decoding.decodeString              file <- Decoding.decodeString @@ -1153,9 +1321,13 @@                 Encoding.encodeNull              Just digest ->-                Encoding.encodeBytes ("\x12\x20" <> Data.ByteArray.convert digest)+                Encoding.encodeBytes ("\x12\x20" <> Dhall.Crypto.unSHA256Digest digest) -        m = Encoding.encodeInt (case importMode of Code -> 0; RawText -> 1; Location -> 2;)+        m = Encoding.encodeInt (case importMode of+            Code -> 0+            RawText -> 1+            Location -> 2+            RawBytes -> 3 )      Import{..} = import_ @@ -1178,10 +1350,10 @@     decode = decodeExpressionInternal decodeImport  -- | Encode a Dhall expression as a CBOR-encoded `ByteString`-encodeExpression :: Expr Void Import -> ByteString+encodeExpression :: Serialise (Expr Void a) => Expr Void a -> ByteString encodeExpression = Serialise.serialise --- | Decode a Dhall expression from a CBOR `Term`+-- | Decode a Dhall expression from a CBOR `Codec.CBOR.Term.Term` decodeExpression     :: Serialise (Expr s a) => ByteString -> Either DecodingFailure (Expr s a) decodeExpression bytes =@@ -1228,7 +1400,7 @@                 else return ()              decoder-        _ -> do+        _ ->             decoder  {-| This indicates that a given CBOR-encoded `ByteString` did not correspond to@@ -1251,3 +1423,15 @@         <>  "↳ 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
@@ -13,10 +13,10 @@     ) where  import Data.Text (Text)-import Prelude hiding (lookup)+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)@ 
src/Dhall/Core.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE RankNTypes         #-}-{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE RecordWildCards #-}  {-| This module contains the core calculus for the Dhall language. @@ -25,6 +25,13 @@     , makeBinding     , Chunks(..)     , PreferAnnotation(..)+    , RecordField(..)+    , makeRecordField+    , FunctionBinding(..)+    , makeFunctionBinding+    , FieldSelection (..)+    , makeFieldSelection+    , WithComponent (..)     , Expr(..)      -- * Normalization@@ -50,8 +57,11 @@      -- * Optics     , subExpressions+    , subExpressionsWith     , chunkExprs     , bindingExprs+    , recordFieldExprs+    , functionBindingExprs      -- * Let-blocks     , multiLet@@ -67,32 +77,29 @@     , Eval.textShow     , censorExpression     , censorText-    , Syntax.desugarWith     ) where -import Control.Exception (Exception)-import Control.Monad.IO.Class (MonadIO(..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)+import Control.Exception      (Exception)+import Control.Monad.IO.Class (MonadIO (..))+import Data.Text              (Text) import Dhall.Normalize-import Dhall.Src (Src(..))-import Dhall.Syntax import Dhall.Pretty.Internal-import Instances.TH.Lift ()-import Lens.Family (over)-import Prelude hiding (succ)+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-import qualified Dhall.Syntax      as Syntax  -- | Pretty-print a value pretty :: Pretty a => a -> Text pretty = pretty_ {-# INLINE pretty #-} -{-| Escape a `Text` literal using Dhall's escaping rules+{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules      Note that the result does not include surrounding quotes -}@@ -104,7 +111,7 @@ {-| Utility used to implement the @--censor@ flag, by:      * Replacing all `Src` text with spaces-    * Replacing all `Text` literals inside type errors 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)@@ -118,7 +125,9 @@      xys' = [ (censorText x, censorExpression y) | (x, y) <- xys ] --- | Utility used to censor `Text` by replacing all characters with a space+{-| Utility used to censor `Data.Text.Text` by replacing all characters with a+    space+-} censorText :: Text -> Text censorText = Data.Text.map (\_ -> ' ') @@ -133,6 +142,7 @@ 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
src/Dhall/Deriving.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes  #-} {-# LANGUAGE DataKinds            #-} {-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE KindSignatures       #-} {-# LANGUAGE PolyKinds            #-} {-# LANGUAGE ScopedTypeVariables  #-} {-# LANGUAGE TypeApplications     #-}@@ -58,7 +57,7 @@   , TrainCase      -- * Type-level versions of SingletonConstructors-  , ToSingletonConstructors+  , ToSingletonConstructors(..)   , Bare   , Wrapped   , Smart@@ -77,12 +76,12 @@    ) where -import Data.Proxy (Proxy (..))+import Data.Proxy   (Proxy (..)) import Dhall import GHC.Generics (Generic (Rep))-import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)+import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) -import qualified Data.Text as Text+import qualified Data.Text            as Text import qualified Data.Text.Manipulate as Case  -- | Intended for use on @deriving via@ clauses for types with a@@ -91,7 +90,7 @@ --   to 'genericAutoWith'. newtype Codec tag a = Codec { unCodec :: a } -instance (Generic a, GenericFromDhall (Rep a), ModifyOptions tag) => FromDhall (Codec tag a) where+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@@ -219,8 +218,8 @@ --   matches @prefix@, or the entire @text@ otherwise dropPrefix :: Text -> (Text -> Text) dropPrefix prefix text = case Text.stripPrefix prefix text of-  Just stripped -> stripped-  Nothing       -> text+  Nothing -> text+  Just e -> e  -- * InterpretOptions setters @@ -378,7 +377,7 @@                  | + `Times New Roman` : …                  | …                  >-, name : - { … : … }+, name : - { … : … } (a record type)          + Text } ...@@ -402,7 +401,7 @@  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-'Text', which is why 'input' above was expecting a record.+'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.
src/Dhall/Diff.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE ViewPatterns      #-}  {-| This module provides functionality for concisely displaying the difference     between two expressions@@ -16,31 +17,40 @@     , diff     ) where -import Data.Foldable (fold, toList)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid (Any(..))-import Data.Semigroup hiding (diff)-import Data.Sequence (Seq)-import Data.String (IsString(..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Void (Void)-import Dhall.Syntax (Binding(..), Chunks (..), Const(..), DhallDouble(..), Expr(..), Var(..))-import Dhall.Map (Map)-import Dhall.Set (Set)+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 Numeric.Natural (Natural)+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.Algorithm.Diff   as Algo.Diff import qualified Data.List.NonEmpty import qualified Data.Set import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc as Pretty+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.Set-import qualified Dhall.Syntax              as Syntax+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@@ -51,7 +61,7 @@         , doc  :: Doc Ann         } -instance Data.Semigroup.Semigroup Diff where+instance Semigroup Diff where     Diff sameL docL <> Diff sameR docR = Diff (sameL && sameR) (docL <> docR)  instance Monoid (Diff) where@@ -61,10 +71,6 @@          doc = mempty -#if !(MIN_VERSION_base(4,11,0))-    mappend = (<>)-#endif- instance IsString (Diff) where     fromString string = Diff {..}       where@@ -119,8 +125,8 @@ equals :: Diff equals = token Internal.equals -forall :: Diff-forall = token (Internal.forall Internal.Unicode)+forall_ :: Diff+forall_ = token (Internal.forall_ Internal.Unicode)  lambda :: Diff lambda = token (Internal.lambda Internal.Unicode)@@ -170,20 +176,21 @@ diffLabel :: Text -> Text -> Diff diffLabel = diffPrimitive (token . Internal.prettyLabel) -diffLabels :: Set Text -> Set Text -> Diff+diffLabels :: [Text] -> [Text] -> Diff diffLabels ksL ksR =     braced (diffFieldNames <> (if anyEqual then [ ignore ] else []))   where-    extraL = Dhall.Set.difference ksL ksR-    extraR = Dhall.Set.difference ksR ksL+    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-                                   (Dhall.Set.toSet ksL)-                                   (Dhall.Set.toSet ksR)))+    anyEqual = not (Data.Set.null (Data.Set.intersection setL setR))  diffNatural :: Natural -> Natural -> Diff diffNatural = diffPrimitive (token . Internal.prettyNatural)@@ -191,6 +198,22 @@ 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) @@ -253,10 +276,12 @@ diffKeyVals     :: (Eq a, Pretty a)     => Diff-    -> Map Text (Expr Void a)-    -> Map Text (Expr Void a)+    -> Map Text (RecordField Void a)+    -> Map Text (RecordField Void a)     -> [Diff]-diffKeyVals assign = diffKeysWith assign diff+diffKeyVals assign kvsL kvsR = diffKeysWith assign diff+    (recordFieldValue <$> kvsL)+    (recordFieldValue <$> kvsR)  diffKeysWith     :: Diff@@ -351,7 +376,7 @@      diffTextSkeleton = difference textSkeleton textSkeleton -    chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR) +    chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR)      chunkDiff a b =       case (a, b) of@@ -359,6 +384,10 @@         (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@@ -395,12 +424,12 @@  diffRecord     :: (Eq a, Pretty a)-    => Map Text (Expr Void a) -> Map Text (Expr Void a) -> Diff+    => 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 (Expr Void a) -> Map Text (Expr Void a) -> Diff+    => Map Text (RecordField Void a) -> Map Text (RecordField Void a) -> Diff diffRecordLit kvsL kvsR = braced (diffKeyVals equals kvsL kvsR)  diffUnion@@ -430,12 +459,14 @@     <>  rarrow     <>  " "     <>  ignore+    <> " (a function)" skeleton (Pi {}) =         ignore     <>  " "     <>  rarrow     <>  " "     <>  ignore+    <> " (a function type)" skeleton (App Optional _) =         "Optional "     <>  ignore@@ -506,6 +537,10 @@     <>  keyword "else"     <>  " "     <>  ignore+skeleton (BytesLit {}) =+        "0x\""+    <>  ignore+    <>  "\"" skeleton (NaturalPlus {}) =         ignore     <>  " "@@ -556,6 +591,7 @@     <>  ignore     <>  " "     <>  rbrace+    <>  " (a record type)" skeleton (RecordLit {}) =         lbrace     <>  " "@@ -566,6 +602,7 @@     <>  ignore     <>  " "     <>  rbrace+    <> " (a record)" skeleton (Union {}) =         langle     <>  " "@@ -576,6 +613,7 @@     <>  ignore     <>  " "     <>  rangle+    <> " (a union type)" skeleton (Combine {}) =         ignore     <>  " "@@ -608,6 +646,10 @@         keyword "toMap"     <>  " "     <>  ignore+skeleton (ShowConstructor {}) =+        keyword "showConstructor"+    <>  " "+    <>  ignore skeleton (Field {}) =         ignore     <>  dot@@ -636,7 +678,9 @@ diff l@(Lam {}) r@(Lam {}) =     enclosed' "  " (rarrow <> " ") (docs l r)   where-    docs (Lam aL bL cL) (Lam aR bR cR) =+    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@@ -695,14 +739,14 @@ diff l@(Pi {}) r@(Pi {}) =     enclosed' "  " (rarrow <> " ") (docs l r)   where-    docs (Pi aL bL cL) (Pi aR bR cR) =+    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+                    forall_                 <>  lparen                 <>  format " " docA                 <>  colon@@ -753,6 +797,15 @@     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)@@ -889,7 +942,7 @@ diffCombineExpression l@(Combine {}) r@(Combine {}) =     enclosed' "  " (operator "∧" <> " ") (docs l r)   where-    docs (Combine _ aL bL) (Combine _ aR bR) =+    docs (Combine _ _ aL bL) (Combine _ _ aR bR) =         Data.List.NonEmpty.cons (diffPreferExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffPreferExpression aL aR)@@ -904,7 +957,7 @@ diffPreferExpression l@(Prefer {}) r@(Prefer {}) =     enclosed' "  " (operator "⫽" <> " ") (docs l r)   where-    docs (Prefer _ aL bL) (Prefer _ aR bR) =+    docs (Prefer _ _ aL bL) (Prefer _ _ aR bR) =         Data.List.NonEmpty.cons (diffCombineTypesExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffCombineTypesExpression aL aR)@@ -919,7 +972,7 @@ diffCombineTypesExpression l@(CombineTypes {}) r@(CombineTypes {}) =     enclosed' "  " (operator "*" <> " ") (docs l r)   where-    docs (CombineTypes aL bL) (CombineTypes aR bR) =+    docs (CombineTypes _ aL bL) (CombineTypes _ aR bR) =         Data.List.NonEmpty.cons (diffTimesExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffTimesExpression aL aR)@@ -980,7 +1033,7 @@ diffEquivalentExpression l@(Equivalent {}) r@(Equivalent {}) =     enclosed' "  " (operator "≡" <> " ") (docs l r)   where-    docs (Equivalent aL bL) (Equivalent aR bR) =+    docs (Equivalent _ aL bL) (Equivalent _ aR bR) =         Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffApplicationExpression aL aR)@@ -1019,8 +1072,32 @@     diffWithExpression l r  diffWithExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff-diffWithExpression l@With{} r@With{} =-    diffWithExpression (Syntax.desugarWith l) (Syntax.desugarWith r)+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 =@@ -1052,7 +1129,7 @@ diffSelectorExpression l@(Field {}) r@(Field {}) =     enclosed' "  " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r))   where-    docs (Field aL bL) (Field aR bR) =+    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)@@ -1067,7 +1144,7 @@ diffSelectorExpression l@(Project {}) r@(Project {}) =     enclosed' "  " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r))   where-    docs (Field aL bL) (Field aR bR) =+    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)@@ -1101,6 +1178,18 @@     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 =@@ -1203,12 +1292,54 @@     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 =@@ -1272,18 +1403,6 @@     mismatch l r diffPrimitiveExpression l r@None =     mismatch l r-diffPrimitiveExpression OptionalFold OptionalFold =-    "…"-diffPrimitiveExpression l@OptionalFold r =-    mismatch l r-diffPrimitiveExpression l r@OptionalFold =-    mismatch l r-diffPrimitiveExpression OptionalBuild OptionalBuild =-    "…"-diffPrimitiveExpression l@OptionalBuild r =-    mismatch l r-diffPrimitiveExpression l r@OptionalBuild =-    mismatch l r diffPrimitiveExpression (BoolLit aL) (BoolLit aR) =     diffBool aL aR diffPrimitiveExpression l@(BoolLit {}) r =@@ -1313,6 +1432,24 @@ 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
src/Dhall/DirectoryTree.hs view
@@ -1,31 +1,67 @@+{-# 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 Data.Monoid ((<>))-import Data.Void (Void)-import Dhall.Syntax (Chunks(..), Expr(..))-import System.FilePath ((</>))+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.Foldable                           as Foldable-import qualified Data.Text                               as Text-import qualified Data.Text.IO                            as Text.IO-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Dhall.Map                               as Map+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.Util                              as Util-import qualified System.Directory                        as Directory-import qualified System.FilePath                         as FilePath+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: @@ -37,6 +73,9 @@      * @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" }@@ -59,8 +98,7 @@     > 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:+    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@@ -81,120 +119,397 @@     > ! "bar": null     > ! "foo": "Hello" -    This utility does not take care of type-checking and normalizing the-    provided expression.  This will raise a `FilesystemError` exception upon-    encountering an expression that cannot be converted as-is.+    /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 :: FilePath -> Expr Void Void -> IO ()-toDirectoryTree path expression = case expression of-    RecordLit keyValues -> do-        Map.unorderedTraverseWithKey_ process keyValues+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 (Record [ ("mapKey", Text), ("mapValue", _) ])) [] -> do-        return ()+    ListLit (Just (App List (Record [ ("mapKey", recordFieldValue -> Text), ("mapValue", _) ]))) [] ->+        Directory.createDirectoryIfMissing allowSeparators path      ListLit _ records         | not (null records)-        , Just keyValues <- extract (Foldable.toList records) -> do+        , Just keyValues <- extract (Foldable.toList records) ->             Foldable.traverse_ (uncurry process) keyValues -    TextLit (Chunks [] text) -> do+    TextLit (Chunks [] text) ->         Text.IO.writeFile path text -    Some value -> do-        toDirectoryTree path value+    Some value ->+        toDirectoryTree allowSeparators path value      App (Field (Union _) _) value -> do-        toDirectoryTree path value+        toDirectoryTree allowSeparators path value -    App None _ -> do+    App None _ ->         return () -    _ -> do+    -- 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 [] = do+    extract [] =         return [] -    extract (RecordLit [("mapKey", TextLit (Chunks [] key)), ("mapValue", value)]:records) = do+    extract (RecordLit [ ("mapKey", recordFieldValue -> TextLit (Chunks [] key))+                       , ("mapValue", recordFieldValue -> value)] : records) =         fmap ((key, value) :) (extract records) -    extract _ = do+    extract _ =         empty      process key value = do-        if Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key-            then die-            else return ()+        when (not allowSeparators && Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key) $+            die -        Directory.createDirectoryIfMissing False path+        Directory.createDirectoryIfMissing allowSeparators path -        toDirectoryTree (path </> Text.unpack key) value+        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-     `directoryTree` function.  The Dhall expression could not be translated to-     a directory tree.+     `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.  No other type of value can be translated to a   \n\-          \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"+          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" -instance Exception FilesystemError+{- | 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
@@ -1,18 +1,14 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE PatternSynonyms     #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TupleSections       #-}-{-# LANGUAGE ViewPatterns        #-}+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE PatternSynonyms      #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE StandaloneDeriving   #-} {-# LANGUAGE UndecidableInstances #-}--{-# OPTIONS_GHC -O #-}+{-# LANGUAGE ViewPatterns         #-}  {-| Eval-apply environment machine with conversion checking and quoting to     normal forms. Fairly similar to GHCI's STG machine algorithmically, but much@@ -50,36 +46,46 @@   , Val(..)   , (~>)   , textShow+  , dateShow+  , timeShow+  , timezoneShow   ) where -import Data.Foldable (foldr', toList)-import Data.Semigroup (Semigroup(..))-import Data.Sequence (Seq, ViewL(..), ViewR(..))-import Data.Text (Text)-import Data.Void (Void)-import Dhall.Map (Map)-import Dhall.Set (Set)-import GHC.Natural (Natural)-import Prelude hiding (succ)+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(..)-  , Expr(..)-  , Chunks(..)-  , Const(..)-  , DhallDouble(..)-  , PreferAnnotation(..)-  , Var(..)-  )+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Expr (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )  import qualified Data.Char-import qualified Data.Sequence   as Sequence+import qualified Data.Sequence as Sequence import qualified Data.Set-import qualified Data.Text       as Text-import qualified Dhall.Syntax    as Syntax-import qualified Dhall.Map       as Map+import qualified Data.Text     as Text+import qualified Data.Time     as Time+import qualified Dhall.Map     as Map import qualified Dhall.Set-import qualified Text.Printf+import qualified Dhall.Syntax  as Syntax+import qualified Text.Printf   as Printf  data Environment a     = Empty@@ -119,10 +125,6 @@ instance Monoid (VChunks a) where   mempty = VChunks [] mempty -#if !(MIN_VERSION_base(4,11,0))-  mappend = (<>)-#endif- {-| 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`@@ -137,6 +139,10 @@   -- ^ 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) @@ -147,6 +153,7 @@ 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@@ -168,6 +175,9 @@     | 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)@@ -196,7 +206,18 @@     | 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)@@ -211,8 +232,6 @@     | VOptional (Val a)     | VSome (Val a)     | VNone (Val a)-    | VOptionalFold (Val a) !(Val a) (Val a) !(Val a) !(Val a)-    | VOptionalBuild (Val a) !(Val a)     | VRecord !(Map Text (Val a))     | VRecordLit !(Map Text (Val a))     | VUnion !(Map Text (Maybe (Val a)))@@ -221,11 +240,13 @@     | 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".@@ -263,7 +284,7 @@         | otherwise =             go env i     go Empty i =-        VVar x (0 - i - 1)+        VVar x (negate i - 1)  vApp :: Eq a => Val a -> Val a -> Val a vApp !t !u =@@ -367,6 +388,24 @@     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@@ -390,6 +429,21 @@             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@@ -397,9 +451,9 @@             VConst k         Var v ->             vVar env v-        Lam x a t ->+        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = a }) t ->             VLam (eval env a) (Closure x env t)-        Pi x a b ->+        Pi _ x a b ->             VPi (eval env a) (Closure x env b)         App t u ->             vApp (eval env t) (eval env u)@@ -447,6 +501,10 @@                 (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 ->@@ -469,9 +527,12 @@                                 -- following issue:                                 --                                 -- https://github.com/ghcjs/ghcjs/issues/782-                                let go !acc 0 = acc-                                    go  acc m = go (vApp succ acc) (m - 1)-                                in  go zero (fromIntegral n' :: Integer)+                                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@@ -573,6 +634,69 @@             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 ->@@ -671,46 +795,23 @@             VSome (eval env t)         None ->             VPrim $ \ ~a -> VNone a-        OptionalFold ->-            VPrim $ \ ~a ->-            VPrim $ \case-                VNone _ ->-                    VHLam (Typed "optional" (VConst Type)) $ \optional ->-                    VHLam (Typed "some" (a ~> optional)) $ \_some ->-                    VHLam (Typed "none" optional) $ \none ->-                    none-                VSome t ->-                    VHLam (Typed "optional" (VConst Type)) $ \optional ->-                    VHLam (Typed "some" (a ~> optional)) $ \some ->-                    VHLam (Typed "none" optional) $ \_none ->-                    some `vApp` t-                opt ->-                    VPrim $ \o ->-                    VPrim $ \s ->-                    VPrim $ \n ->-                    VOptionalFold a opt o s n-        OptionalBuild ->-            VPrim $ \ ~a ->-            VPrim $ \case-                VPrimVar -> VOptionalBuild a VPrimVar-                t ->       t-                    `vApp` VOptional a-                    `vApp` VHLam (Typed "a" a) VSome-                    `vApp` VNone a         Record kts ->-            VRecord (Map.sort (fmap (eval env) kts))+            VRecord (Map.sort (eval env . recordFieldValue <$> kts))         RecordLit kts ->-            VRecordLit (Map.sort (fmap (eval env) kts))+            VRecordLit (Map.sort (eval env . recordFieldValue <$> kts))         Union kts ->             VUnion (Map.sort (fmap (fmap (eval env)) kts))-        Combine mk t u ->+        Combine _ mk t u ->             vCombine mk (eval env t) (eval env u)-        CombineTypes t u ->+        CombineTypes _ t u ->             vCombineTypes (eval env t) (eval env u)-        Prefer _ t u ->+        Prefer _ _ t u ->             vPrefer env (eval env t) (eval env u)         RecordCompletion t u ->-            eval env (Annot (Prefer PreferFromCompletion (Field t "default") u) (Field t "Type"))+            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, _)@@ -741,22 +842,30 @@                     in  VListLit Nothing s                 (x', ma') ->                     VToMap x' ma'-        Field t k ->+        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 ks)+            vProjectByFields env (eval env t) (Dhall.Set.sort (Dhall.Set.fromList ks))         Project t (Right e) ->             case eval env e of                 VRecord kts ->-                    eval env (Project t (Left (Dhall.Set.fromSet (Map.keysSet 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 ->+        Equivalent _ t u ->             VEquivalent (eval env t) (eval env u)-        e@With{} ->-            eval env (Syntax.desugarWith e)+        With e₀ ks v ->+            vWith (eval env e₀) ks (eval env v)         Note _ e ->             eval env e         ImportAlt t _ ->@@ -811,9 +920,32 @@     f '\r' = "\\r"     f '\t' = "\\t"     f '\f' = "\\f"-    f c | c <= '\x1F' = Text.pack (Text.Printf.printf "\\u%04x" (Data.Char.ord c))+    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@@ -861,6 +993,10 @@             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') ->@@ -911,6 +1047,26 @@             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') ->@@ -937,8 +1093,6 @@             conv env t t'         (VNone _, VNone _) ->             True-        (VOptionalBuild _ t, VOptionalBuild _ t') ->-            conv env t t'         (VRecord m, VRecord m') ->             eqMapsBy (conv env) m m'         (VRecordLit m, VRecordLit m') ->@@ -955,6 +1109,8 @@             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')) ->@@ -969,8 +1125,6 @@             eqMapsBy (eqMaybeBy (conv env)) m m' && k == k' && eqMaybeBy (conv env) mt mt'         (VEmbed a, VEmbed a') ->             a == a'-        (VOptionalFold a t _ u v, VOptionalFold a' t' _ u' v') ->-            conv env a a' && conv env t t' && conv env u u' && conv env v v'         (_, _) ->             False   where@@ -994,6 +1148,7 @@ 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@@ -1022,17 +1177,30 @@         VApp t u ->             quote env t `qApp` u         VLam a (freshClosure -> (x, v, t)) ->-            Lam x (quote env a) (quoteBind x (instantiate t v))+            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 x (quote env a) (quoteBind x (t v))-                Prim                      -> quote env (t VPrimVar)-                NaturalSubtractZero       -> App NaturalSubtract (NaturalLit 0)+                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 x (quote env a) (quoteBind x (instantiate b v))+            Pi mempty x (quote env a) (quoteBind x (instantiate b v))         VHPi (fresh -> (x, v)) a b ->-            Pi x (quote env a) (quoteBind x (b v))+            Pi mempty x (quote env a) (quoteBind x (b v))         VBool ->             Bool         VBoolLit b ->@@ -1047,6 +1215,10 @@             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 ->@@ -1097,6 +1269,26 @@             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 ->@@ -1123,38 +1315,38 @@             Some (quote env t)         VNone t ->             None `qApp` t-        VOptionalFold a o t u v ->-            OptionalFold `qApp` a `qApp` o `qApp` t `qApp` u `qApp` v-        VOptionalBuild a t ->-            OptionalBuild `qApp` a `qApp` t         VRecord m ->-            Record (fmap (quote env) m)+            Record (fmap quoteRecordField m)         VRecordLit m ->-            RecordLit (fmap (quote env) m)+            RecordLit (fmap quoteRecordField m)         VUnion m ->             Union (fmap (fmap (quote env)) m)         VCombine mk t u ->-            Combine mk (quote env t) (quote env u)+            Combine mempty mk (quote env t) (quote env u)         VCombineTypes t u ->-            CombineTypes (quote env t) (quote env u)+            CombineTypes mempty (quote env t) (quote env u)         VPrefer t u ->-            Prefer PreferFromSource (quote env t) (quote env 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) k+            Field (quote env t) $ Syntax.makeFieldSelection k         VProject t p ->-            Project (quote env t) (fmap (quote env) p)+            Project (quote env t) (first Dhall.Set.toList (fmap (quote env) p))         VAssert t ->             Assert (quote env t)         VEquivalent t u ->-            Equivalent (quote env t) (quote env 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)) k+            Field (Union (fmap (fmap (quote env)) m)) $ Syntax.makeFieldSelection k         VInject m k (Just t) ->-            Field (Union (fmap (fmap (quote env)) m)) k `qApp` t+            Field (Union (fmap (fmap (quote env)) m)) (Syntax.makeFieldSelection k) `qApp` t         VEmbed a ->             Embed a         VPrimVar ->@@ -1177,6 +1369,10 @@     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@@ -1184,6 +1380,7 @@  normalize :: Eq a => Expr s a -> Expr t a normalize = nf Empty+{-# INLINABLE normalize #-}  alphaNormalize :: Expr s a -> Expr s a alphaNormalize = goEnv EmptyNames@@ -1203,10 +1400,10 @@                 Const k             Var (V x i) ->                 goVar e0 x i-            Lam x t u ->-                Lam "_" (go t) (goBind x u)-            Pi x a b ->-                Pi "_" (go a) (goBind x b)+            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 ->@@ -1227,6 +1424,10 @@                 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 ->@@ -1277,6 +1478,26 @@                 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 ->@@ -1303,36 +1524,34 @@                 Some (go t)             None ->                 None-            OptionalFold ->-                OptionalFold-            OptionalBuild ->-                OptionalBuild             Record kts ->-                Record (fmap go kts)+                Record (goRecordField <$> kts)             RecordLit kts ->-                RecordLit (fmap go kts)+                RecordLit (goRecordField <$> kts)             Union kts ->                 Union (fmap (fmap go) kts)-            Combine m t u ->-                Combine m (go t) (go u)-            CombineTypes t u ->-                CombineTypes (go t) (go u)-            Prefer b t u ->-                Prefer b (go t) (go u)+            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 t u ->-                Equivalent (go t) (go u)+            Equivalent cs t u ->+                Equivalent cs (go t) (go u)             With e k v ->                 With (go e) k (go v)             Note s e ->@@ -1345,3 +1564,4 @@         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
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveAnyClass    #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-} @@ -10,87 +9,114 @@     , format     ) where -import Data.Monoid ((<>))-import Dhall.Pretty (CharacterSet(..), annToAnsiStyle)-+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(..)+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed     ) -import qualified Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal-import qualified Data.Text.Prettyprint.Doc.Render.Text     as Pretty.Text-import qualified Control.Exception import qualified Data.Text.IO+import qualified Dhall.Import import qualified Dhall.Pretty import qualified Dhall.Util-import qualified System.AtomicWrite.Writer.LazyText        as AtomicWrite.LazyText+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-    { characterSet :: CharacterSet-    , censor       :: Censor-    , input        :: Input-    , outputMode   :: OutputMode+    { chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor+    , transitivity       :: Transitivity+    , inputs             :: NonEmpty Input+    , outputMode         :: OutputMode     }  -- | Implementation of the @dhall format@ subcommand format :: Format -> IO ()-format (Format {..}) = do-    let layoutHeaderAndExpr (Header header, expr) =-            Dhall.Pretty.layout-                (   Pretty.pretty header-                <>  Dhall.Pretty.prettyCharacterSet characterSet expr -                <>  "\n")+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 layoutInput = do-            headerAndExpr <- Dhall.Util.getExpressionAndHeader censor input+        let status = Dhall.Import.emptyStatus directory -            return (layoutHeaderAndExpr headerAndExpr)+        let layoutHeaderAndExpr (Header header, expr) =+                let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet+                in+                Dhall.Pretty.layout+                    (   Pretty.pretty header+                    <>  Dhall.Pretty.prettyCharacterSet characterSet expr+                    <>  "\n") -    case outputMode of-        Write -> do-            docStream <- layoutInput+        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Data.Text.IO.readFile file -            case input of-                InputFile file -> do-                    AtomicWrite.LazyText.atomicWriteFile-                        file-                        (Pretty.Text.renderLazy docStream)+                return (file, text, transitivity0)+            StandardInput -> do+                text <- Data.Text.IO.getContents -                StandardInput -> do-                    supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout+                return ("(input)", text, NonTransitive) -                    Pretty.Terminal.renderIO-                        System.IO.stdout-                        (if supportsANSI-                            then (fmap annToAnsiStyle docStream)-                            else (Pretty.unAnnotateS docStream)) -        Check -> do-            originalText <- case input of-                InputFile file -> Data.Text.IO.readFile file-                StandardInput  -> Data.Text.IO.getContents+        headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText -            docStream <- case input of-                InputFile _    -> layoutInput-                StandardInput  -> do-                    headerAndExpr <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText-                    return (layoutHeaderAndExpr headerAndExpr)+        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_ -            let formattedText = Pretty.Text.renderStrict docStream+                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath) -            if originalText == formattedText-                then return ()-                else do-                    let command = "format"+            NonTransitive ->+                return () -                    let modified = "formatted"+        let docStream = layoutHeaderAndExpr headerAndExpr -                    Control.Exception.throwIO CheckFailed{..}+        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
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-} {-# LANGUAGE RecordWildCards   #-} {-# LANGUAGE ViewPatterns      #-} @@ -11,50 +12,177 @@     , freezeImport     , freezeRemoteImport +      -- * Freeze with custom evaluation settings+    , freezeWithSettings+    , freezeExpressionWithSettings+    , freezeImportWithSettings+    , freezeRemoteImportWithSettings+       -- * Types     , Scope(..)     , Intent(..)++      -- * Deprecated functions+    , freezeWithManager+    , freezeExpressionWithManager+    , freezeImportWithManager+    , freezeRemoteImportWithManager     ) where -import Data.Bifunctor (first)-import Data.Monoid ((<>))-import Data.Text-import Dhall.Parser (Src)-import Dhall.Pretty (CharacterSet)-import Dhall.Syntax (Expr(..), Import(..), ImportHashed(..), ImportType(..))+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(..)+    , 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 Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text     as Pretty.Text-import qualified Dhall.Core                                as Core+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.Optics-import qualified Dhall.Parser                              as Parser import qualified Dhall.Pretty import qualified Dhall.TypeCheck-import qualified Dhall.Util                                as Util-import qualified System.AtomicWrite.Writer.LazyText        as AtomicWrite.LazyText+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 directory import_ = do+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 =@@ -63,15 +191,15 @@                         }                 } -    let status = Dhall.Import.emptyStatus directory+    let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory      expression <- State.evalStateT (Dhall.Import.loadWith (Embed unprotectedImport)) status -    case Dhall.TypeCheck.typeOf expression of+    case Dhall.TypeCheck.typeWith (view Dhall.startingContext settings) expression of         Left  exception -> Exception.throwIO exception         Right _         -> return () -    let normalizedExpression = Core.alphaNormalize (Core.normalize expression)+    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)@@ -84,134 +212,131 @@      return newImport --- | Freeze an import only if the import is a `Remote` import-freezeRemoteImport-    :: FilePath-    -- ^ Current working directory+-- | See 'freezeRemoteImport'.+freezeRemoteImportWithSettings+    :: EvaluateSettings+    -> FilePath     -> Import     -> IO Import-freezeRemoteImport directory import_ = do+freezeRemoteImportWithSettings settings directory import_ =     case importType (importHashed import_) of-        Remote {} -> freezeImport directory import_+        Remote {} -> freezeImportWithSettings settings directory import_         _         -> return import_ -writeExpr :: Input -> (Text, Expr Src Import) -> CharacterSet -> IO ()-writeExpr input (header, expr) characterSet = do-    let doc =  Pretty.pretty header-            <> Dhall.Pretty.prettyCharacterSet characterSet expr-            <> "\n"--    let stream = Dhall.Pretty.layout doc--    let unAnnotated = Pretty.unAnnotateS stream--    case input of-        InputFile file ->-            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---- | 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.+-- | See 'freezeRemoteImport'.+freezeNonMissingImportWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Import+    -> IO Import+freezeNonMissingImportWithSettings settings directory import_ =+    case importType (importHashed import_) of+        Missing -> return import_+        _ -> freezeImportWithSettings settings directory import_ --- | Implementation of the @dhall freeze@ subcommand-freeze-    :: OutputMode-    -> Input+-- | See 'freeze'.+freezeWithSettings+    :: EvaluateSettings+    -> OutputMode+    -> Transitivity+    -> NonEmpty Input     -> Scope     -> Intent-    -> CharacterSet+    -> Maybe CharacterSet     -> Censor     -> IO ()-freeze outputMode input scope intent characterSet censor = do-    let directory = case input of-            StandardInput  -> "."-            InputFile file -> System.FilePath.takeDirectory file+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 rewrite = freezeExpression directory scope intent+        let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory -    case outputMode of-        Write -> do-            (Header header, parsedExpression) <- do-                Util.getExpressionAndHeader censor input+        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Text.IO.readFile file -            frozenExpression <- rewrite parsedExpression+                return (file, text, transitivity0) -            writeExpr input (header, frozenExpression) characterSet+            StandardInput -> do+                text <- Text.IO.getContents -        Check -> do-            originalText <- case input of-                InputFile file -> Text.IO.readFile file-                StandardInput  -> Text.IO.getContents+                return ("(input)", text, NonTransitive) -            let name = case input of-                    InputFile file -> file-                    StandardInput  -> "(input)"+        (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText -            (Header header, parsedExpression) <- do-                Core.throws (first Parser.censor (Parser.exprAndHeaderFromText name originalText))+        let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet -            frozenExpression <- rewrite parsedExpression+        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_ -            let doc =  Pretty.pretty header-                    <> Dhall.Pretty.prettyCharacterSet characterSet frozenExpression-                    <> "\n"+                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath) -            let stream = Dhall.Pretty.layout doc+            NonTransitive ->+                return () -            let modifiedText = Pretty.Text.renderStrict stream+        frozenExpression <- freezeExpressionWithSettings settings directory scope intent parsedExpression -            if originalText == modifiedText-                then return ()-                else do-                    let command = "freeze"+        let doc =  Pretty.pretty header+                <> Dhall.Pretty.prettyCharacterSet characterSet frozenExpression+                <> "\n" -                    let modified = "frozen"+        let stream = Dhall.Pretty.layout doc -                    Exception.throwIO CheckFailed{..}+        let modifiedText = Pretty.Text.renderStrict stream -{-| Slightly more pure version of the `freeze` function+        case outputMode of+            Write -> do+                let unAnnotated = Pretty.unAnnotateS stream -    This still requires `IO` to freeze the import, but now the input and output-    expression are passed in explicitly--}-freezeExpression-    :: FilePath-    -- ^ Starting directory+                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)-freezeExpression directory scope intent expression = do+freezeExpressionWithSettings settings directory scope intent expression = do     let freezeScope =             case scope of-                AllImports        -> freezeImport-                OnlyRemoteImports -> freezeRemoteImport+                AllImports        -> freezeNonMissingImportWithSettings+                OnlyRemoteImports -> freezeRemoteImportWithSettings -    let freezeFunction = freezeScope directory+    let freezeFunction = freezeScope settings directory      let cache             -- This case is necessary because `transformOf` is a bottom-up@@ -245,7 +370,7 @@                         Import{ importHashed = ImportHashed{ hash = Nothing } }                     )                 )-            ) = do+            ) =                 {- 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@@ -259,17 +384,21 @@             (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 frozenImport) (Embed 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@@ -279,12 +408,38 @@                             }                         } -                return (ImportAlt (Embed frozenImport) (Embed thawedImport))-        cache expression_ = do+                return (ImportAlt (Embed frozenMissing) (Embed thawedImport))+        cache expression_ =             return expression_ -    case intent of+    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 expression+            traverse freezeFunction (transformOf Core.subExpressions uncache expression)         Cache  ->-            Dhall.Optics.transformMOf Core.subExpressions cache expression+            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,11 +1,15 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE CPP                 #-} {-# LANGUAGE DeriveAnyClass      #-} {-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE NamedFieldPuns      #-} {-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+ {-# OPTIONS_GHC -Wall #-}  {-| Dhall lets you import external expressions located either in local files or@@ -101,14 +105,18 @@ module Dhall.Import (     -- * Import       load+    , loadWithManager     , loadRelativeTo+    , loadWithStatus     , loadWith     , localToPath     , hashExpression     , hashExpressionToCode     , writeExpressionToSemanticCache-    , warnAboutMissingCaches     , assertNoImports+    , Manager+    , defaultNewManager+    , CacheWarning(..)     , Status(..)     , SemanticCacheMode(..)     , Chained@@ -116,6 +124,12 @@     , chainedFromLocalHere     , chainedChangeMode     , emptyStatus+    , emptyStatusWithManager+    , envOriginHeaders+    , makeEmptyStatus+    , remoteStatus+    , remoteStatusWithManager+    , fetchRemote     , stack     , cache     , Depends(..)@@ -126,7 +140,9 @@     , normalizer     , startingContext     , chainImport+    , dependencyToFile     , ImportSemantics+    , HTTPHeader     , Cycle(..)     , ReferentiallyOpaque(..)     , Imported(..)@@ -138,58 +154,78 @@     , HashMismatch(..)     ) where -import Control.Applicative (Alternative(..), liftA2)-import Control.Exception (Exception, SomeException, IOException, toException)-import Control.Monad (when)-import Control.Monad.Catch (throwM, MonadCatch(catch), handle)-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.State.Strict (StateT)-import Data.ByteString (ByteString)-import Data.CaseInsensitive (CI)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-import Data.Void (Void, absurd)-import Data.Typeable (Typeable)-import System.FilePath ((</>))-import Dhall.Binary (StandardVersion(..))+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-    ( Expr(..)-    , Chunks(..)-    , Directory(..)-    , File(..)-    , FilePrefix(..)-    , ImportHashed(..)-    , ImportType(..)-    , ImportMode(..)-    , Import(..)-    , URL(..)+    ( 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 (Parser(..), ParseError(..), Src(..), SourcedException(..))-import Lens.Family.State.Strict (zoom)+import Dhall.Parser+    ( ParseError (..)+    , Parser (..)+    , SourcedException (..)+    , Src (..)+    )+import Lens.Micro.Mtl (zoom) -import qualified Codec.CBOR.Encoding                         as Encoding 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 Control.Monad.Trans.State.Strict            as State import qualified Data.ByteString import qualified Data.ByteString.Lazy-import qualified Data.CaseInsensitive-import qualified Data.Foldable import qualified Data.List.NonEmpty                          as NonEmpty-import qualified Data.Text.Encoding+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+import qualified Dhall.Core                                  as Core import qualified Dhall.Crypto import qualified Dhall.Map import qualified Dhall.Parser@@ -198,15 +234,20 @@ 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 System.Directory                            as Directory-import qualified System.FilePath                             as FilePath 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@@ -253,7 +294,7 @@  instance Show ReferentiallyOpaque where     show (ReferentiallyOpaque import_) =-        "\nReferentially opaque import: " ++ Dhall.Pretty.Internal.prettyToString 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@@ -279,7 +320,7 @@         toDisplay = drop 1 (reverse canonical)  -- | Exception thrown when an imported file is missing-data MissingFile = MissingFile FilePath+newtype MissingFile = MissingFile FilePath     deriving (Typeable)  instance Exception MissingFile@@ -297,7 +338,7 @@ instance Exception MissingEnvironmentVariable  instance Show MissingEnvironmentVariable where-    show (MissingEnvironmentVariable {..}) =+    show MissingEnvironmentVariable{..} =             "\n"         <>  "\ESC[1;31mError\ESC[0m: Missing environment variable\n"         <>  "\n"@@ -322,8 +363,6 @@ throwMissingImport :: (MonadCatch m, Exception e) => e -> m a throwMissingImport e = throwM (MissingImports [toException e]) -type HTTPHeader = (CI ByteString, ByteString)- -- | Exception thrown when a HTTP url is imported but dhall was built without -- the @with-http@ Cabal flag. data CannotImportHTTPURL =@@ -410,9 +449,13 @@ instance Exception HashMismatch  instance Show HashMismatch where-    show (HashMismatch {..}) =+    show HashMismatch{..} =             "\n"-        <>  "\ESC[1;31mError\ESC[0m: Import integrity check failed\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"@@ -431,16 +474,16 @@     let Directory {..} = directory      prefixPath <- case prefix of-        Home -> do+        Home ->             Directory.getHomeDirectory -        Absolute -> do+        Absolute ->             return "/" -        Parent -> do+        Parent ->             return ".." -        Here -> do+        Here ->             return "."      let cs = map Text.unpack (file : components)@@ -463,7 +506,7 @@ -- | 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' <- normalizeHeaders url+    url' <- normalizeHeadersIn url     let child' = child { importHashed = importHashed { importType = Remote url' } }     return (Chained (canonicalize (parent <> child'))) @@ -471,9 +514,9 @@     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.+--   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@@ -486,56 +529,77 @@             return importSemantics  -- | Load an import from the 'semantic cache'. Defers to---   `loadImportWithSemisemanticCache` for imports that aren't frozen (and+--   @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 _) _)) = do+  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 -> liftIO $ fetchFromSemanticCache semanticHash-            IgnoreSemanticCache -> pure Nothing+            UseSemanticCache ->+                zoom cacheWarning (fetchFromSemanticCache semanticHash)+            IgnoreSemanticCache ->+                pure Nothing      case mCached of         Just bytesStrict -> do             let actualHash = Dhall.Crypto.sha256Hash bytesStrict              if semanticHash == actualHash-                then return ()+                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-                    Status { _stack } <- State.get-                    throwMissingImport (Imported _stack (HashMismatch {expectedHash = semanticHash, ..}))+                    printWarning $+                        makeHashMismatchMessage semanticHash actualHash+                        <> "\n"+                        <> "The interpreter will attempt to fix the cached import\n"+                    fetch -            let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict -            importSemantics <- case Dhall.Binary.decodeExpression bytesLazy of-                Left  err -> throwMissingImport (Imported _stack err)-                Right e   -> return e+        Nothing -> fetch+    where+        fetch = do+            ImportSemantics{ importSemantics } <- loadImportWithSemisemanticCache import_ -            return (ImportSemantics {..})+            let bytes = encodeExpression (Core.alphaNormalize importSemantics) -        Nothing -> do-            ImportSemantics { importSemantics } <- loadImportWithSemisemanticCache import_+            let actualHash = Dhall.Crypto.sha256Hash bytes -            let variants = map (\version -> encodeExpression version (Dhall.Core.alphaNormalize importSemantics))-                                [ minBound .. maxBound ]-            case Data.Foldable.find ((== semanticHash). Dhall.Crypto.sha256Hash) variants of-                Just bytes -> liftIO $ writeToSemanticCache semanticHash bytes-                Nothing -> do-                    let expectedHash = semanticHash-                    Status { _stack } <- State.get-                    let actualHash = hashExpression (Dhall.Core.alphaNormalize importSemantics)-                    throwMissingImport (Imported _stack (HashMismatch {..}))+            let expectedHash = semanticHash -            return (ImportSemantics {..})+            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 :: Dhall.Crypto.SHA256Digest -> IO (Maybe Data.ByteString.ByteString)+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)@@ -544,12 +608,20 @@ -- | 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 = writeToSemanticCache hash bytes+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 NoVersion expression+    bytes = encodeExpression expression+     hash = Dhall.Crypto.sha256Hash bytes -writeToSemanticCache :: Dhall.Crypto.SHA256Digest -> Data.ByteString.ByteString -> IO ()+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@@ -570,7 +642,7 @@             absolutePath <- Directory.makeAbsolute path             return absolutePath         Remote url -> do-            let urlText = Dhall.Core.pretty (url { headers = Nothing })+            let urlText = Core.pretty (url { headers = Nothing })             return (Text.unpack urlText)         Env env -> return $ Text.unpack env         Missing -> throwM (MissingImports [])@@ -582,7 +654,7 @@             return r      parsedImport <- case Text.Megaparsec.parse parser path text of-        Left  errInfo -> do+        Left  errInfo ->             throwMissingImport (Imported _stack (ParseError errInfo text))         Right expr    -> return expr @@ -591,42 +663,62 @@     -- 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 (Dhall.Core.denote resolvedExpr)-    mCached <- lift $ fetchFromSemisemanticCache semisemanticHash+    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)+                Left err  -> throwMissingImport (Imported _stack err)                 Right sem -> return sem              return importSemantics          Nothing -> do-            betaNormal <- do-                let substitutedExpr = Dhall.Substitution.substitute resolvedExpr _substitutions-                case Dhall.TypeCheck.typeWith _startingContext substitutedExpr of-                    Left  err -> throwMissingImport (Imported _stack err)-                    Right _ -> return (Dhall.Core.normalizeWith _normalizer resolvedExpr)+            let substitutedExpr =+                  Dhall.Substitution.substitute resolvedExpr _substitutions -            let bytes = encodeExpression NoVersion betaNormal-            lift $ writeToSemisemanticCache semisemanticHash bytes+            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) -            return betaNormal+                _ -> 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` imports aren't cached since they are well-typed and normal by--- construction+-- `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@@ -639,16 +731,16 @@      -- importSemantics is alpha-beta-normal by construction!     let importSemantics = case importType of-            Missing -> Field locationType "Missing"+            Missing -> Field locationType $ Core.makeFieldSelection  "Missing"             local@(Local _ _) ->-                App (Field locationType "Local")-                  (TextLit (Chunks [] (Dhall.Core.pretty local)))+                App (Field locationType $ Core.makeFieldSelection "Local")+                  (TextLit (Chunks [] (Core.pretty local)))             remote_@(Remote _) ->-                App (Field locationType "Remote")-                  (TextLit (Chunks [] (Dhall.Core.pretty remote_)))+                App (Field locationType $ Core.makeFieldSelection "Remote")+                  (TextLit (Chunks [] (Core.pretty remote_)))             Env env ->-                App (Field locationType "Environment")-                  (TextLit (Chunks [] (Dhall.Core.pretty env)))+                App (Field locationType $ Core.makeFieldSelection "Environment")+                  (TextLit (Chunks [] (Core.pretty env)))      return (ImportSemantics {..}) @@ -660,20 +752,27 @@ computeSemisemanticHash resolvedExpr = hashExpression resolvedExpr  -- Fetch encoded normal form from "semi-semantic cache"-fetchFromSemisemanticCache :: Dhall.Crypto.SHA256Digest -> IO (Maybe Data.ByteString.ByteString)+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 :: Dhall.Crypto.SHA256Digest -> Data.ByteString.ByteString -> IO ()+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+-- | Fetch source code directly from disk/network fetchFresh :: ImportType -> StateT Status IO Text fetchFresh (Local prefix file) = do     Status { _stack } <- State.get@@ -691,19 +790,43 @@     Status { _stack } <- State.get     x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)     case x of-        Just string -> do+        Just string ->             return (Text.pack string)-        Nothing -> do+        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 (Dhall.Core.pretty url)+    let urlString = Text.unpack (Core.pretty url)     Status { _stack } <- State.get     throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders)) #else@@ -717,52 +840,48 @@         fetchFromHttpUrl url' maybeHeaders #endif --- | 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)+-- | 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-      maybeHeaders = mapM toHeader hs-toHeaders _ = []--toHeader :: Expr s a -> Maybe HTTPHeader-toHeader (RecordLit m) = do-    (TextLit (Chunks [] keyText), 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 _ = do-    empty+    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, MonadIO m) => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath getCacheFile cacheName hash = do-    cacheDirectory <- getOrCreateCacheDirectory False cacheName+    cacheDirectory <- getOrCreateCacheDirectory cacheName      let cacheFile = cacheDirectory </> ("1220" <> show hash)      return cacheFile --- | Warn if no cache directory is available-warnAboutMissingCaches :: (MonadCatch m, Alternative m, MonadIO m) => m ()-warnAboutMissingCaches = warn <|> return ()-    where warn = Data.Foldable.traverse_ (getOrCreateCacheDirectory True) ["dhall", "dhall-haskell"]--getOrCreateCacheDirectory :: (MonadCatch m, Alternative m, MonadIO m) => Bool -> FilePath -> m FilePath-getOrCreateCacheDirectory showWarning cacheName = do+getOrCreateCacheDirectory+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> m FilePath+getOrCreateCacheDirectory cacheName = do     let warn message = do-            let warning =-                     "\n"-                  <> "\ESC[1;33mWarning\ESC[0m: "-                  <> message+            cacheWarningStatus <- State.get -            when showWarning (liftIO (System.IO.hPutStrLn System.IO.stderr warning))+            case cacheWarningStatus of+                CacheWarned    -> printWarning message+                CacheNotWarned -> return () +            State.put CacheWarned+             empty      let handler action dir (ioex :: IOException) = do@@ -774,7 +893,7 @@                   <> "... the following exception was thrown:\n"                   <> "\n"                   <> "↳ " <> show ioex <> "\n"-        +             warn ioExMsg      let setPermissions dir = do@@ -803,14 +922,19 @@                 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"-                          <> show permissions <> "\n"+                          <> "\n"+                          <> "• " <> render Directory.readable <> " readable\n"+                          <> "• " <> render Directory.writable <> " writable\n"+                          <> "• " <> render Directory.searchable <> " searchable\n"                      warn message @@ -830,7 +954,7 @@             existsDir <- existsDirectory dir              if existsDir-                then do+                then                     assertPermissions dir                  else do@@ -853,9 +977,9 @@                             createDirectory dir                              setPermissions dir-    -    cacheBaseDirectory <- getCacheBaseDirectory showWarning +    cacheBaseDirectory <- getCacheBaseDirectory+     let directory = cacheBaseDirectory </> cacheName      let message =@@ -872,11 +996,12 @@      return directory -getCacheBaseDirectory :: (Alternative m, MonadIO m) => Bool -> m FilePath-getCacheBaseDirectory showWarning = alternative₀ <|> alternative₁ <|> alternative₂+getCacheBaseDirectory+    :: (MonadState CacheWarning m, Alternative m, MonadIO m) => m FilePath+getCacheBaseDirectory = alternative₀ <|> alternative₁ <|> alternative₂   where     alternative₀ = do-        maybeXDGCacheHome <- do+        maybeXDGCacheHome <-           liftIO (System.Environment.lookupEnv "XDG_CACHE_HOME")          case maybeXDGCacheHome of@@ -903,6 +1028,8 @@         where isWindows = System.Info.os == "mingw32"      alternative₂ = do+        cacheWarningStatus <- State.get+         let message =                 "\n"              <> "\ESC[1;33mWarning\ESC[0m: "@@ -911,63 +1038,156 @@              <> "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" -        when showWarning (liftIO (System.IO.hPutStrLn System.IO.stderr message))+        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.-normalizeHeaders :: URL -> StateT Status IO URL-normalizeHeaders url@URL { headers = Just headersExpression } = do+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) } -    let go key₀ key₁ = do-            let expected :: Expr Src Void-                expected =-                    App List-                        ( Record-                            ( Dhall.Map.fromList-                                [ (key₀, Text), (key₁, Text) ]-                            )-                        )+normalizeHeadersIn url = return url -            let suffix_ = Dhall.Pretty.Internal.prettyToStrictText expected-            let annot = case loadedExpr of-                    Note (Src begin end bytes) _ ->-                        Note (Src begin end bytes') (Annot loadedExpr expected)-                      where-                        bytes' = bytes <> " : " <> suffix_-                    _ ->-                        Annot loadedExpr expected+-- | 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 -            _ <- case (Dhall.TypeCheck.typeOf annot) of-                Left err -> throwMissingImport (Imported _stack err)-                Right _ -> return ()+-- | 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]" -            return (Dhall.Core.normalize loadedExpr)+-- | Load headers only from the environment (used in tests)+envOriginHeaders :: Expr Src Import+envOriginHeaders = Note headersSrc (Embed (Import (ImportHashed Nothing (Env "DHALL_HEADERS")) Code)) -    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) =-                    throwMissingImport (Imported _stack e)+-- | 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 -            handle handler₁ (go "header" "value")+-- | Given a headers expression, return an origin headers loader+originHeadersLoader :: IO (Expr Src Import) -> StateT Status IO OriginHeaders+originHeadersLoader headersExpr = do -    headersExpression' <--        handle handler₀ (go "mapKey" "mapValue")+    -- Load the headers using the parent stack, which should always be a local+    -- import (we only load headers for the first remote import) -    return url { headers = Just (fmap absurd headersExpression') }+    status <- State.get -normalizeHeaders url = return url+    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 = emptyStatusWith fetchRemote+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@@ -1009,15 +1229,33 @@     ImportSemantics {..} <- loadImport child     zoom stack (State.put _stack) -    return (Dhall.Core.renote importSemantics)+    return (Core.renote importSemantics)    ImportAlt a b -> loadWith a `catch` handler₀     where-      handler₀ (SourcedException (Src begin _ text₀) (MissingImports es₀)) =-          loadWith b `catch` handler₁+      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₁ (SourcedException (Src _ end text₁) (MissingImports es₁)) =-              throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁)))+          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₁ @@ -1026,47 +1264,53 @@        (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 = loadRelativeTo "." UseSemanticCache+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 rootDirectory semanticCacheMode expression =+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)-        (emptyStatus rootDirectory) { _semanticCacheMode = semanticCacheMode }+        status { _semanticCacheMode = semanticCacheMode } -encodeExpression-    :: StandardVersion-    -- ^ `NoVersion` means to encode without the version tag-    -> Expr Void Void-    -> Data.ByteString.ByteString-encodeExpression _standardVersion expression = bytesStrict+encodeExpression :: Expr Void Void -> Data.ByteString.ByteString+encodeExpression expression = bytesStrict   where     intermediateExpression :: Expr Void Import     intermediateExpression = fmap absurd expression -    encoding =-        case _standardVersion of-            NoVersion ->-                Codec.Serialise.encode intermediateExpression-            s ->-                    Encoding.encodeListLen 2-                <>  Encoding.encodeString v-                <>  Codec.Serialise.encode intermediateExpression-              where-                v = Dhall.Binary.renderStandardVersion s+    encoding = Codec.Serialise.encode intermediateExpression      bytesStrict = Write.toStrictByteString encoding  -- | Hash a fully resolved expression hashExpression :: Expr Void Void -> Dhall.Crypto.SHA256Digest-hashExpression expression =-    Dhall.Crypto.sha256Hash (encodeExpression NoVersion expression)+hashExpression = Dhall.Crypto.sha256Hash . encodeExpression  {-| Convenience utility to hash a fully resolved expression and return the     base-16 encoded hash with the @sha256:@ prefix@@ -1087,4 +1331,71 @@ -- | Assert than an expression is import-free assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void) assertNoImports expression =-    Dhall.Core.throws (traverse (\_ -> Left ImportResolutionDisabled) 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
@@ -6,41 +6,37 @@  module Dhall.Import.Types where -import Control.Exception (Exception)+import Control.Exception                (Exception) import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI) import Data.Dynamic-import Data.List.NonEmpty (NonEmpty)-import Dhall.Map (Map)-import Data.Semigroup ((<>))-import Data.Text.Prettyprint.Doc (Pretty(..))-import Data.Void (Void)-import Dhall.Context (Context)+import Data.HashMap.Strict              (HashMap)+import Data.List.NonEmpty               (NonEmpty)+import Data.Void                        (Void)+import Dhall.Context                    (Context) import Dhall.Core-  ( Directory (..)-  , Expr-  , File (..)-  , FilePrefix (..)-  , Import (..)-  , ImportHashed (..)-  , ImportMode (..)-  , ImportType (..)-  , ReifiedNormalizer(..)-  , URL-  )+    ( Expr+    , Import (..)+    , ReifiedNormalizer (..)+    , URL+    )+import Dhall.Map                        (Map)+import Dhall.Parser                     (Src)+import Lens.Micro                       (Lens', lens)+import Prettyprinter                    (Pretty (..))+ #ifdef WITH_HTTP-import Dhall.Import.Manager (Manager)+import qualified Dhall.Import.Manager #endif-import Dhall.Parser (Src)-import Lens.Family (LensLike')-import System.FilePath (isRelative, splitDirectories) +import qualified Data.Text import qualified Dhall.Context-import qualified Dhall.Map     as Map+import qualified Dhall.Map          as Map import qualified Dhall.Substitution-import qualified Data.Text --- | 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+-- | 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@.@@ -54,7 +50,7 @@     pretty (Chained import_) = pretty import_  -- | An import that has been fully interpeted-data ImportSemantics = ImportSemantics+newtype ImportSemantics = ImportSemantics     { importSemantics :: Expr Void Void     -- ^ The fully resolved import, typechecked and beta-normal.     }@@ -67,6 +63,34 @@ -} 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@@ -81,16 +105,21 @@     -- ^ Cache of imported expressions with their node id in order to avoid     --   importing the same expression twice with different values -#ifdef WITH_HTTP+    , _newManager :: IO Manager     , _manager :: Maybe Manager-#else-    , _manager :: Maybe Void-#endif-    -- ^ Used to cache the `Manager` when making multiple requests+    -- ^ 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)@@ -98,12 +127,23 @@     , _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 remote resolver, importing---   relative to the given directory.-emptyStatusWith :: (URL -> StateT Status IO Data.Text.Text) -> FilePath -> Status-emptyStatusWith _remote rootDirectory = Status {..}+-- | 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) @@ -121,61 +161,49 @@      _semanticCacheMode = UseSemanticCache -    prefix = if isRelative rootDirectory-      then Here-      else Absolute-    pathComponents =-        fmap Data.Text.pack (reverse (splitDirectories rootDirectory))--    dirAsFile = File (Directory pathComponents) "."--    -- Fake import to set the directory we're relative to.-    rootImport = Import-      { importHashed = ImportHashed-        { hash = Nothing-        , importType = Local prefix dirAsFile-        }-      , importMode = Code-      }+    _cacheWarning = CacheNotWarned  -- | Lens from a `Status` to its `_stack` field-stack :: Functor f => LensLike' f Status (NonEmpty Chained)-stack k s = fmap (\x -> s { _stack = x }) (k (_stack s))+stack :: Lens' Status (NonEmpty Chained)+stack = lens _stack (\s x -> s { _stack = x })  -- | Lens from a `Status` to its `_graph` field-graph :: Functor f => LensLike' f Status [Depends]-graph k s = fmap (\x -> s { _graph = x }) (k (_graph s))+graph :: Lens' Status [Depends]+graph = lens _graph (\s x -> s { _graph = x })  -- | Lens from a `Status` to its `_cache` field-cache :: Functor f => LensLike' f Status (Map Chained ImportSemantics)-cache k s = fmap (\x -> s { _cache = x }) (k (_cache s))+cache :: Lens' Status (Map Chained ImportSemantics)+cache = lens _cache (\s x -> s { _cache = x })  -- | Lens from a `Status` to its `_remote` field-remote-    :: Functor f => LensLike' f Status (URL -> StateT Status IO Data.Text.Text)-remote k s = fmap (\x -> s { _remote = x }) (k (_remote s))+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 :: Functor f => LensLike' f Status (Dhall.Substitution.Substitutions Src Void)-substitutions k s =-    fmap (\x -> s { _substitutions = x }) (k (_substitutions s))+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 :: Functor f => LensLike' f Status (Maybe (ReifiedNormalizer Void))-normalizer k s = fmap (\x -> s {_normalizer = x}) (k (_normalizer s))+normalizer :: Lens' Status (Maybe (ReifiedNormalizer Void))+normalizer = lens _normalizer (\s x -> s {_normalizer = x})  -- | Lens from a `Status` to its `_startingContext` field-startingContext :: Functor f => LensLike' f Status (Context (Expr Src Void))-startingContext k s =-    fmap (\x -> s { _startingContext = x }) (k (_startingContext s))+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-    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+    This exception indicates that an invalid `Dhall.Syntax.Type` was provided to+    the `Dhall.input` function -} data InternalError = InternalError deriving (Typeable) @@ -202,11 +230,12 @@  instance Exception InternalError --- | Wrapper around `HttpException`s with a prettier `Show` instance.+-- | 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--- 'HttpExcepion' is stored in a 'Dynamic'+-- 'Network.HTTP.Client.HttpException' is stored in a 'Dynamic' data PrettyHttpException = PrettyHttpException String Dynamic     deriving (Typeable) 
src/Dhall/Lint.hs view
@@ -13,35 +13,34 @@     , removeUnusedBindings     , fixAssert     , fixParentPath+    , addPreludeExtensions     , removeLetInLet-    , replaceOptionalBuildFold-    , replaceSaturatedOptionalFold     , useToMap     ) where  import Control.Applicative ((<|>))  import Dhall.Syntax-    ( Binding(..)-    , Chunks(..)-    , Const(..)-    , Directory(..)-    , Expr(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportType(..)-    , Var(..)+    ( 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          as Map-import qualified Dhall.Optics-import qualified Lens.Family+import qualified Dhall.Map+import qualified Lens.Micro         as Lens  {-| Automatically improve a Dhall expression @@ -51,20 +50,16 @@     * 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@-    * Replaces deprecated @Optional\/fold@ and @Optional\/build@ built-ins -}-lint :: Expr s Import -> Expr s Import-lint =  Dhall.Optics.rewriteOf subExpressions lowerPriorityRewrite-    .   Dhall.Optics.rewriteOf subExpressions higherPriorityRewrite+lint :: Eq s => Expr s Import -> Expr s Import+lint =  Lens.rewriteOf subExpressions rewrite   where-    lowerPriorityRewrite e =+    rewrite e =             fixAssert                e         <|> removeUnusedBindings     e         <|> fixParentPath            e         <|> removeLetInLet           e-        <|> replaceOptionalBuildFold e--    higherPriorityRewrite = replaceSaturatedOptionalFold+        <|> addPreludeExtensions     e  -- | Remove unused `Let` bindings. removeUnusedBindings :: Eq a => Expr s a -> Maybe (Expr s a)@@ -76,7 +71,7 @@         Just (Core.shift (-1) (V a 0) d) removeUnusedBindings _ = Nothing --- | Fix `Let` bindings  that the user probably meant to be `assert`s+-- | 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)@@ -112,9 +107,43 @@             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.Family.anyOf subExpressions isOrContainsAssert e+isOrContainsAssert e = Lens.anyOf subExpressions isOrContainsAssert e  -- | The difference between --@@ -132,68 +161,6 @@ removeLetInLet (Let binding (Note _ l@Let{})) = Just (Let binding l) removeLetInLet _ = Nothing --- | This replaces @Optional/fold@ and @Optional/build@, both of which can be--- implemented within the language-replaceOptionalBuildFold :: Expr s a -> Maybe (Expr s a)-replaceOptionalBuildFold OptionalBuild =-    Just-        (Lam "a" (Const Type)-            (Lam "build"-                (Pi "optional" (Const Type)-                    (Pi "some" (Pi "_" "a" "optional")-                        (Pi "none" "optional" "optional")-                    )-                )-                (App (App (App "build" (App Optional "a")) (Lam "x" "a" (Some "x"))) (App None "a"))-            )-        )-replaceOptionalBuildFold OptionalFold =-    Just-        (Lam "a" (Const Type)-            (Lam "o" (App Optional "a")-                (Lam "optional" (Const Type)-                    (Lam "some" (Pi "_" "a" "optional")-                        (Lam "none" "optional"-                            (Merge-                                (RecordLit-                                    [ ("Some", "some")-                                    , ("None", "none")-                                    ]-                                )-                                "o"-                                Nothing-                            )-                        )-                    )-                )-            )-        )-replaceOptionalBuildFold _ =-    Nothing---- | This replaces a saturated @Optional/fold@ with the equivalent @merge@--- expression-replaceSaturatedOptionalFold :: Expr s a -> Maybe (Expr s a)-replaceSaturatedOptionalFold-    (App-        (Core.shallowDenote -> App-            (Core.shallowDenote -> App-                (Core.shallowDenote -> App-                    (Core.shallowDenote -> App-                        (Core.shallowDenote -> OptionalFold)-                        _-                    )-                    o-                )-                _-            )-            some-        )-        none-    ) = Just (Merge (RecordLit [ ("Some", some), ("None", none) ]) o Nothing)-replaceSaturatedOptionalFold _ =-    Nothing- -- | This replaces a record of key-value pairs with the equivalent use of --   @toMap@ --@@ -208,8 +175,8 @@             (Core.shallowDenote -> App                 (Core.shallowDenote -> List)                 (Core.shallowDenote -> Record-                    (Map.sort ->-                        [ ("mapKey", Core.shallowDenote -> Text)+                    (Dhall.Map.sort ->+                        [ ("mapKey", Core.shallowDenote . Core.recordFieldValue -> Text)                         , ("mapValue", _)                         ]                     )@@ -224,15 +191,15 @@     , Just keyValues' <- traverse convert keyValues =         Just             (ToMap-                (RecordLit (Map.fromList (Foldable.toList keyValues')))+                (RecordLit (Dhall.Map.fromList (Foldable.toList keyValues')))                 Nothing             )   where     convert keyValue =         case Core.shallowDenote keyValue of             RecordLit-                (Map.sort ->-                    [ ("mapKey"  , (Core.shallowDenote -> TextLit (Chunks [] key)))+                (Dhall.Map.sort ->+                    [ ("mapKey"  , Core.shallowDenote . Core.recordFieldValue -> TextLit (Chunks [] key))                     , ("mapValue", value)                     ]                 ) ->
src/Dhall/Main.hs view
@@ -2,7 +2,7 @@     @dhall@ executable -} -{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE ApplicativeDo     #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-}@@ -12,6 +12,7 @@     ( -- * Options       Options(..)     , Mode(..)+    , ResolveMode(..)     , parseOptions     , parserInfoOptions @@ -21,47 +22,63 @@     ) where  import Control.Applicative (optional, (<|>))-import Control.Exception (Handler(..), SomeException)-import Control.Monad (when)-import Data.Bifunctor (first)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Void (Void)-import Dhall.Freeze (Intent(..), Scope(..))-import Dhall.Import (Imported(..), Depends(..), SemanticCacheMode(..), _semanticCacheMode)-import Dhall.Parser (Src)-import Dhall.Pretty (Ann, CharacterSet(..), annToAnsiStyle)-import Dhall.TypeCheck (Censored(..), DetailedTypeError(..), TypeError)-import Dhall.Version (dhallVersionString)+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 System.Exit (ExitCode, exitFailure)-import System.IO (Handle)-import Text.Dot ((.->.))+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(..)+    ( Expr (Annot)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    , URL (..)     , pretty     ) import Dhall.Util-    ( Censor(..)-    , CheckFailed(..)+    ( Censor (..)+    , CheckFailed (..)     , Header (..)-    , Input(..)-    , OutputMode(..)-    , Output(..)+    , 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 Control.Monad.Trans.State.Strict   as State import qualified Data.Aeson import qualified Data.Aeson.Encode.Pretty import qualified Data.ByteString.Lazy@@ -69,51 +86,46 @@ import qualified Data.Map import qualified Data.Text import qualified Data.Text.IO-import qualified Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text     as Pretty.Text import qualified Dhall import qualified Dhall.Binary import qualified Dhall.Core import qualified Dhall.Diff-import qualified Dhall.DirectoryTree                       as DirectoryTree+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.Parser                              as Parser import qualified Dhall.Map-import qualified Dhall.Tags+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 System.AtomicWrite.Writer.LazyText        as AtomicWrite.LazyText+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.IO+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-    , ascii   :: Bool-    , censor  :: Censor+    { mode               :: Mode+    , explain            :: Bool+    , plain              :: Bool+    , chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor     } -ignoreSemanticCache :: Mode -> Bool-ignoreSemanticCache Default {..} = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache Resolve {..} = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache Type {..}    = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache _            = False- -- | The subcommands for the @dhall@ executable data Mode     = Default@@ -137,11 +149,11 @@           }     | Normalize { file :: Input , alpha :: Bool }     | Repl-    | Format { input :: Input, outputMode :: OutputMode }-    | Freeze { input :: Input, all_ :: Bool, cache :: Bool, outputMode :: OutputMode }-    | Hash { file :: Input }+    | 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 { input :: Input, outputMode :: OutputMode }+    | Lint { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }     | Tags           { input :: Input           , output :: Output@@ -149,15 +161,24 @@           , followSymlinks :: Bool           }     | Encode { file :: Input, json :: Bool }-    | Decode { file :: Input, json :: Bool }-    | Text { file :: Input }-    | DirectoryTree { file :: Input, path :: FilePath }-    | SyntaxTree { file :: Input }+    | 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@@ -184,7 +205,7 @@     <$> parseMode     <*> switch "explain" "Explain error messages in more detail"     <*> switch "plain" "Disable syntax highlighting"-    <*> switch "ascii" "Format code using only ASCII syntax"+    <*> parseCharacterSet     <*> parseCensor   where     switch name description =@@ -198,6 +219,19 @@         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@@ -218,27 +252,32 @@             Manipulate             "format"             "Standard code formatter for the Dhall language"-            (Format <$> parseInplace <*> parseCheck "formatted")+            (Format <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "formatted" <*> parseFiles)     <|> subcommand             Manipulate             "freeze"             "Add integrity checks to remote import statements of an expression"-            (Freeze <$> parseInplace <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen")+            (Freeze <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen" <*> parseFiles)     <|> subcommand             Manipulate             "lint"             "Improve Dhall code by using newer language features and removing dead code"-            (Lint <$> parseInplace <*> parseCheck "linted")+            (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)+            (Text <$> parseFile <*> parseOutput)     <|> subcommand             Generate             "to-directory-tree"             "Convert nested records of Text literals into a directory tree"-            (DirectoryTree <$> parseFile <*> parseDirectoryTreeOutput)+            (DirectoryTree <$> parseDirectoryTreeAllowSeparators <*> parseFile <*> parseDirectoryTreeOutput)     <|> subcommand             Interpret             "resolve"@@ -263,7 +302,7 @@             Convert             "decode"             "Decode a Dhall expression from binary"-            (Decode <$> parseFile <*> parseJSONFlag)+            (Decode <$> parseFile <*> parseJSONFlag <*> parseQuiet)     <|> subcommand             Miscellaneous             "repl"@@ -278,9 +317,14 @@             Miscellaneous             "hash"             "Compute semantic hashes for Dhall expressions"-            (Hash <$> parseFile)+            (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)@@ -293,7 +337,7 @@             Debugging             "haskell-syntax-tree"             "Output the parsed syntax tree (for debugging)"-            (SyntaxTree <$> parseFile)+            (SyntaxTree <$> parseFile <*> parseNoted)     <|> (   Default         <$> parseFile         <*> parseOutput@@ -303,6 +347,12 @@         <*> 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@@ -317,8 +367,24 @@                 (   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@@ -328,6 +394,7 @@                 (   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 =@@ -380,20 +447,26 @@     parseQuiet =         Options.Applicative.switch             (   Options.Applicative.long "quiet"-            <>  Options.Applicative.help "Don't print the inferred type"+            <>  Options.Applicative.help "Don't print the result"             ) -    parseInplace = fmap f (optional p)-      where-        f  Nothing    = StandardInput-        f (Just file) = InputFile file--        p = Options.Applicative.strOption+    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@@ -403,6 +476,8 @@             (   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)@@ -414,6 +489,7 @@             (   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)@@ -443,7 +519,7 @@     parseAllFlag =         Options.Applicative.switch         (   Options.Applicative.long "all"-        <>  Options.Applicative.help "Add integrity checks to all imports (not just remote imports)"+        <>  Options.Applicative.help "Add integrity checks to all imports (not just remote imports) except for missing imports"         )      parseCacheFlag =@@ -463,13 +539,66 @@             <>  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 =@@ -489,10 +618,6 @@ -- | Run the command specified by the `Options` type command :: Options -> IO () command (Options {..}) = do-    let characterSet = case ascii of-            True  -> ASCII-            False -> Unicode-     GHC.IO.Encoding.setLocaleEncoding System.IO.utf8      let rootDirectory = \case@@ -501,9 +626,18 @@      let toStatus = Dhall.Import.emptyStatus . rootDirectory -    let getExpression          = Dhall.Util.getExpression          censor-    let getExpressionAndHeader = Dhall.Util.getExpressionAndHeader censor+    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@@ -544,7 +678,7 @@                         Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"                         Control.Exception.throwIO (Imported ps e) -            handleExitCode e = do+            handleExitCode e =                 Control.Exception.throwIO (e :: ExitCode)      let renderDoc :: Handle -> Doc Ann -> IO ()@@ -560,8 +694,8 @@             Pretty.renderIO h ansiStream             Data.Text.IO.hPutStrLn h "" -    let render :: Pretty a => Handle -> Expr Src a -> IO ()-        render h expression = do+    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@@ -572,10 +706,8 @@              AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy stream) -    when (not $ ignoreSemanticCache mode) Dhall.Import.warnAboutMissingCaches-     handle $ case mode of-        Version -> do+        Version ->             putStrLn dhallVersionString          Default {..} -> do@@ -585,7 +717,7 @@                     Exit.exitSuccess                 else return () -            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file              resolvedExpression <-                 Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression@@ -605,7 +737,7 @@                         else alphaNormalizedExpression              case output of-                StandardOutput -> render System.IO.stdout annotatedExpression+                StandardOutput -> render System.IO.stdout characterSet annotatedExpression                  OutputFile file_ ->                     writeDocToFile@@ -664,15 +796,15 @@                  $   _cache          Resolve { resolveMode = Nothing, ..} -> do-            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file              resolvedExpression <-                 Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression -            render System.IO.stdout resolvedExpression+            render System.IO.stdout characterSet resolvedExpression          Normalize {..} -> do-            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file              resolvedExpression <- Dhall.Import.assertNoImports expression @@ -685,10 +817,10 @@                     then Dhall.Core.alphaNormalize normalizedExpression                     else normalizedExpression -            render System.IO.stdout alphaNormalizedExpression+            render System.IO.stdout characterSet alphaNormalizedExpression          Type {..} -> do-            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file              resolvedExpression <-                 Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression@@ -697,10 +829,12 @@              if quiet                 then return ()-                else render System.IO.stdout inferredType+                else render System.IO.stdout characterSet inferredType -        Repl -> do-            Dhall.Repl.repl characterSet explain+        Repl ->+            Dhall.Repl.repl+                (fromMaybe Unicode chosenCharacterSet) -- Default to Unicode if no characterSet specified+                explain          Diff {..} -> do             expression1 <- Dhall.inputExpr expr1@@ -716,14 +850,20 @@                 else Exit.exitFailure          Format {..} -> do-            Dhall.Format.format (Dhall.Format.Format {..})+            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 input scope intent characterSet censor+            Dhall.Freeze.freeze outputMode transitivity inputs scope intent chosenCharacterSet censor          Hash {..} -> do             expression <- getExpression file@@ -736,52 +876,79 @@             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 {..} -> do-            case outputMode of-                Write -> do-                    (Header header, expression) <- do-                        getExpressionAndHeader input+        Lint { transitivity = transitivity0, ..} -> do+            when deprecatedInPlace $+                System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated" -                    let lintedExpression = Dhall.Lint.lint expression+            handleMultipleChecksFailed "lint" "linted" go inputs+          where+            go input = do+                let directory = case input of+                        StandardInput  -> "."+                        InputFile file -> System.FilePath.takeDirectory file -                    let doc =   Pretty.pretty header-                            <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression+                let status = Dhall.Import.emptyStatus directory -                    case input of-                        InputFile file -> writeDocToFile file doc+                (inputName, originalText, transitivity) <- case input of+                    InputFile file -> do+                        text <- Data.Text.IO.readFile file -                        StandardInput -> renderDoc System.IO.stdout doc+                        return (file, text, transitivity0)+                    StandardInput -> do+                        text <- Data.Text.IO.getContents -                Check -> do-                    originalText <- case input of-                        InputFile file -> Data.Text.IO.readFile file-                        StandardInput  -> Data.Text.IO.getContents+                        return ("(input)", text, NonTransitive) -                    let name = case input of-                            InputFile file -> file-                            StandardInput  -> "(input)"+                (Header header, parsedExpression) <-+                    Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText -                    (Header header, expression) <- do-                        Dhall.Core.throws (first Parser.censor (Parser.exprAndHeaderFromText name originalText))+                let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet -                    let lintedExpression = Dhall.Lint.lint expression+                case transitivity of+                    Transitive ->+                        for_ parsedExpression $ \import_ -> do+                            maybeFilepath <- Dhall.Import.dependencyToFile status import_ -                    let doc =   Pretty.pretty header-                            <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression+                            for_ maybeFilepath $ \filepath ->+                                go (InputFile filepath) -                    let stream = Dhall.Pretty.layout doc+                    NonTransitive ->+                        return () -                    let modifiedText = Pretty.Text.renderStrict stream <> "\n"+                let lintedExpression = Dhall.Lint.lint parsedExpression -                    if originalText == modifiedText-                        then return ()-                        else do-                            let modified = "linted"+                let doc =   Pretty.pretty header+                        <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression -                            Control.Exception.throwIO CheckFailed{ command = "lint", ..}+                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 @@ -797,16 +964,16 @@                      Data.ByteString.Lazy.Char8.putStrLn jsonBytes -                else do+                else                     Data.ByteString.Lazy.putStr bytes          Decode {..} -> do-            bytes <- do+            bytes <-                 case file of                     InputFile f   -> Data.ByteString.Lazy.readFile f                     StandardInput -> Data.ByteString.Lazy.getContents -            expression <- do+            expression <-                 if json                     then do                         value <- case Data.Aeson.eitherDecode' bytes of@@ -818,13 +985,19 @@                         let cborgBytes = Codec.CBOR.Write.toLazyByteString encoding                          Dhall.Core.throws (Dhall.Binary.decodeExpression cborgBytes)-                    else do+                    else                         Dhall.Core.throws (Dhall.Binary.decodeExpression bytes)  -            let doc = Dhall.Pretty.prettyCharacterSet characterSet (Dhall.Core.renote expression :: Expr Src Import)+            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+                    renderDoc System.IO.stdout doc          Text {..} -> do             expression <- getExpression file@@ -837,8 +1010,11 @@             let normalizedExpression = Dhall.Core.normalize resolvedExpression              case normalizedExpression of-                Dhall.Core.TextLit (Dhall.Core.Chunks [] text) -> do-                    Data.Text.IO.putStr text+                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@@ -867,15 +1043,27 @@              let normalizedExpression = Dhall.Core.normalize resolvedExpression -            DirectoryTree.toDirectoryTree path normalizedExpression+            DirectoryTree.toDirectoryTree allowSeparators path normalizedExpression +        Dhall.Main.Schemas{..} ->+            Dhall.Schemas.schemasCommand Dhall.Schemas.Schemas{ input = file, ..}+         SyntaxTree {..} -> do             expression <- getExpression file -            let denoted :: Expr Void Import-                denoted = Dhall.Core.denote expression+            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 -            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 ()
src/Dhall/Map.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE CPP                #-}-{-# LANGUAGE DeriveAnyClass     #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE DeriveLift         #-}-{-# LANGUAGE DeriveTraversable  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE TypeFamilies       #-}+{-# LANGUAGE DeriveAnyClass        #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE DeriveLift            #-}+{-# LANGUAGE ExplicitForAll        #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}  -- | `Map` type used to represent records and unions @@ -18,6 +18,7 @@     , singleton     , fromList     , fromListWithKey+    , fromMap        -- * Constructing unordered 'Map's     , unorderedSingleton@@ -34,6 +35,7 @@       -- * Deletion/Update     , delete     , filter+    , partition     , restrictKeys     , withoutKeys     , mapMaybe@@ -68,18 +70,20 @@     , elems     ) where -import Control.Applicative ((<|>))-import Control.DeepSeq (NFData)-import Data.Data (Data)-import Data.Semigroup-import GHC.Generics (Generic)-import Instances.TH.Lift ()+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 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+import qualified Data.Map.Strict import qualified Data.Set+import qualified Data.Traversable.WithIndex as Traversable.WithIndex import qualified GHC.Exts import qualified Prelude @@ -90,7 +94,7 @@     This is done primarily to avoid a dependency on @insert-ordered-containers@     and also to improve performance -}-data Map k v = Map (Data.Map.Map k v) (Keys k)+data Map k v = Map (Data.Map.Strict.Map k v) (Keys k)     deriving (Data, Generic, Lift, NFData)  data Keys a@@ -100,7 +104,7 @@  instance (Ord k, Eq v) => Eq (Map k v) where   m1 == m2 =-      Data.Map.size (toMap m1) == Data.Map.size (toMap m2)+      Data.Map.Strict.size (toMap m1) == Data.Map.Strict.size (toMap m2)       && toList m1 == toList m2   {-# INLINABLE (==) #-} @@ -134,7 +138,7 @@ {-| prop> \x y z -> x <> (y <> z) == (x <> y) <> (z :: Map Int Int) -}-instance Ord k => Data.Semigroup.Semigroup (Map k v) where+instance Ord k => Semigroup (Map k v) where     (<>) = union     {-# INLINABLE (<>) #-} @@ -143,14 +147,9 @@ prop> \x -> mempty <> x == (x :: Map Int Int) -} instance Ord k => Monoid (Map k v) where-    mempty = Map Data.Map.empty (Original [])+    mempty = Map Data.Map.Strict.empty (Original [])     {-# INLINABLE mempty #-} -#if !(MIN_VERSION_base(4,11,0))-    mappend = (<>)-    {-# INLINABLE mappend #-}-#endif- instance (Show k, Show v, Ord k) => Show (Map k v) where     showsPrec d m =         showParen (d > 10) (showString "fromList " . showsPrec 11 kvs)@@ -164,6 +163,18 @@      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@@ -176,7 +187,7 @@ singleton :: k -> v -> Map k v singleton k v = Map m ks   where-    m = Data.Map.singleton k v+    m = Data.Map.Strict.singleton k v      ks = Original [k] {-# INLINABLE singleton #-}@@ -200,7 +211,7 @@ fromList :: Ord k => [(k, v)] -> Map k v fromList kvs = Map m ks   where-    m = Data.Map.fromList kvs+    m = Data.Map.Strict.fromList kvs      ks = Original (nubOrd (map fst kvs)) {-# INLINABLE fromList #-}@@ -213,11 +224,15 @@ fromListWithKey :: Ord k => (k -> v -> v -> v) -> [(k, v)] -> Map k v fromListWithKey f kvs = Map m ks   where-    m = Data.Map.fromListWithKey f kvs+    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]@@ -244,7 +259,7 @@ unorderedSingleton :: k -> v -> Map k v unorderedSingleton k v = Map m Sorted   where-    m = Data.Map.singleton k v+    m = Data.Map.Strict.singleton k v {-# INLINABLE unorderedSingleton #-}  {-| Create a `Map` from a list of key-value pairs@@ -261,7 +276,7 @@ unorderedFromList :: Ord k => [(k, v)] -> Map k v unorderedFromList kvs = Map m Sorted   where-    m = Data.Map.fromList kvs+    m = Data.Map.Strict.fromList kvs {-# INLINABLE unorderedFromList #-}  {-| Sort the keys of a `Map`, forgetting the original ordering@@ -286,7 +301,7 @@ -} isSorted :: Eq k => Map k v -> Bool isSorted (Map _ Sorted)        = True-isSorted (Map m (Original ks)) = Data.Map.keys m == ks -- Or shortcut to False here?+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@@ -300,10 +315,10 @@ 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.insert k v m) Sorted+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.insertLookupWithKey (\_k new _old -> new) k v m+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new _old -> new) k v m      ks' | Just _ <- mayOldV = ks         | otherwise         = k : ks@@ -318,10 +333,10 @@ 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.insertWith f k v m) Sorted+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.insertLookupWithKey (\_k new old -> f new old) k v m+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new old -> f new old) k v m      ks' | Just _ <- mayOldV = ks         | otherwise         = k : ks@@ -337,7 +352,7 @@ delete :: Ord k => k -> Map k v -> Map k v delete k (Map m ks) = Map m' ks'   where-    m' = Data.Map.delete k m+    m' = Data.Map.Strict.delete k m      ks' = case ks of         Sorted        -> Sorted@@ -354,29 +369,40 @@ filter :: Ord k => (a -> Bool) -> Map k a -> Map k a filter predicate (Map m ks) = Map m' ks'   where-    m' = Data.Map.filter predicate m+    m' = Data.Map.Strict.filter predicate m -    ks' = filterKeys (\k -> Data.Map.member k m') ks+    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE filter #-} -{-| Restrict a 'Map' to only those keys found in a @"Data.Set".'Set'@.+{-| 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-#if MIN_VERSION_containers(0,5,8)-    m' = Data.Map.restrictKeys m s-#else-    m' = Data.Map.filterWithKey (\k _ -> Data.Set.member k s) m-#endif+    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".'Set'@ from a 'Map'+{-| 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)]@@ -384,11 +410,7 @@ withoutKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a withoutKeys (Map m ks) s = Map m' ks'   where-#if MIN_VERSION_containers(0,5,8)-    m' = Data.Map.withoutKeys m s-#else-    m' = Data.Map.filterWithKey (\k _ -> Data.Set.notMember k s) m-#endif+    m' = Data.Map.Strict.withoutKeys m s      ks' = filterKeys (\k -> Data.Set.notMember k s) ks {-# INLINABLE withoutKeys #-}@@ -402,9 +424,9 @@ mapMaybe :: Ord k => (a -> Maybe b) -> Map k a -> Map k b mapMaybe f (Map m ks) = Map m' ks'   where-    m' = Data.Map.mapMaybe f m+    m' = Data.Map.Strict.mapMaybe f m -    ks' = filterKeys (\k -> Data.Map.member k m') ks+    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE mapMaybe #-}  {-| Retrieve a key from a `Map`@@ -419,7 +441,7 @@ Nothing -} lookup :: Ord k => k -> Map k v -> Maybe v-lookup k (Map m _) = Data.Map.lookup k m+lookup k (Map m _) = Data.Map.Strict.lookup k m {-# INLINABLE lookup #-}  {-| Retrieve the first key, value of the 'Map', if present,@@ -437,9 +459,9 @@ 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.! k, Map (Data.Map.delete k m) (Original 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.minViewWithKey m = Just (k, v, Map m' Sorted)+  | Just ((k, v), m') <- Data.Map.Strict.minViewWithKey m = Just (k, v, Map m' Sorted)   | otherwise                                      = Nothing {-# INLINABLE uncons #-} @@ -455,7 +477,7 @@ False -} member :: Ord k => k -> Map k v -> Bool-member k (Map m _) = Data.Map.member k m+member k (Map m _) = Data.Map.Strict.member k m {-# INLINABLE member #-}  {-|@@ -463,7 +485,7 @@ 1 -} size :: Map k v -> Int-size (Map m _) = Data.Map.size m+size (Map m _) = Data.Map.Strict.size m {-# INLINABLE size #-}  {-| Combine two `Map`s, preferring keys from the first `Map`@@ -478,11 +500,11 @@ 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.union mL mR+    m = Data.Map.Strict.union mL mR      ks = case (ksL, ksR) of         (Original l, Original r) -> Original $-            l <|> Prelude.filter (\k -> Data.Map.notMember k mL) r+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r         _                        -> Sorted {-# INLINABLE union #-} @@ -496,11 +518,11 @@ 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.unionWith combine mL mR+    m = Data.Map.Strict.unionWith combine mL mR      ks = case (ksL, ksR) of         (Original l, Original r) -> Original $-            l <|> Prelude.filter (\k -> Data.Map.notMember k mL) r+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r         _                        -> Sorted {-# INLINABLE unionWith #-} @@ -521,7 +543,7 @@     -> Map k c outerJoin fa fb fab (Map ma ksA) (Map mb ksB) = Map m ks   where-    m = Data.Map.mergeWithKey+    m = Data.Map.Strict.mergeWithKey             (\k a b -> Just (fab k a b))             (fmap fa)             (fmap fb)@@ -530,7 +552,7 @@      ks = case (ksA, ksB) of         (Original l, Original r) -> Original $-            l <|> Prelude.filter (\k -> Data.Map.notMember k ma) r+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k ma) r         _                        -> Sorted {-# INLINABLE outerJoin #-} @@ -545,10 +567,10 @@ 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.intersection mL mR+    m = Data.Map.Strict.intersection mL mR      -- Or forget order unless both maps are ordered?!-    ks = filterKeys (\k -> Data.Map.member k m) ksL+    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@@ -560,10 +582,10 @@ 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.intersectionWith combine mL mR+    m = Data.Map.Strict.intersectionWith combine mL mR      -- Or forget order unless both maps are ordered?!-    ks = filterKeys (\k -> Data.Map.member k m) ksL+    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@@ -575,9 +597,9 @@ 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.difference mL mR+    m = Data.Map.Strict.difference mL mR -    ks = filterKeys (\k -> Data.Map.notMember k mR) ksL+    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@@ -586,7 +608,7 @@ ("BA",[1,2]) -} foldMapWithKey :: (Monoid m, Ord k) => (k -> a -> m) -> Map k a -> m-foldMapWithKey f (Map m Sorted) = Data.Map.foldMapWithKey f m+foldMapWithKey f (Map m Sorted) = Data.Map.Strict.foldMapWithKey f m foldMapWithKey f m              = foldMap (uncurry f) (toList m) {-# INLINABLE foldMapWithKey #-} @@ -606,7 +628,7 @@ mapWithKey :: (k -> a -> b) -> Map k a -> Map k b mapWithKey f (Map m ks) = Map m' ks   where-    m' = Data.Map.mapWithKey f m+    m' = Data.Map.Strict.mapWithKey f m {-# INLINABLE mapWithKey #-}  {-| Traverse all of the key-value pairs in a `Map`, in their original order@@ -617,9 +639,9 @@ 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.traverseWithKey f m)-traverseWithKey f m =-    fmap fromList (traverse f' (toList m))+    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 #-}@@ -630,7 +652,7 @@ 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.traverseWithKey f m)+    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@@ -642,7 +664,7 @@ unorderedTraverseWithKey_     :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f () unorderedTraverseWithKey_ f (Map m _) =-    Data.Map.foldlWithKey' (\acc k v -> acc *> f k v) (pure ()) 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@@ -651,22 +673,22 @@ [("B",1),("A",2)] -} toList :: Ord k => Map k v -> [(k, v)]-toList (Map m Sorted)        = Data.Map.toList m-toList (Map m (Original ks)) = fmap (\k -> (k, m Data.Map.! k)) ks+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.toAscList m+toAscList (Map m _) = Data.Map.Strict.toAscList m {-# INLINABLE toAscList #-} -{-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map".`Data.Map.Map`@+{-| 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.Map k v+toMap :: Map k v -> Data.Map.Strict.Map k v toMap (Map m _) = m {-# INLINABLE toMap #-} @@ -676,7 +698,7 @@ ["B","A"] -} keys :: Map k v -> [k]-keys (Map m Sorted)        = Data.Map.keys m+keys (Map m Sorted)        = Data.Map.Strict.keys m keys (Map _ (Original ks)) = ks {-# INLINABLE keys #-} @@ -686,23 +708,30 @@ [1,2] -} elems :: Ord k => Map k v -> [v]-elems (Map m Sorted)        = Data.Map.elems m-elems (Map m (Original ks)) = fmap (\k -> m Data.Map.! k) ks+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".'Set'@ of the keys+{-| 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.keysSet m+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)
+ 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
@@ -1,953 +1,1037 @@-{-# LANGUAGE BangPatterns       #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RankNTypes         #-}--module Dhall.Normalize (-      alphaNormalize-    , normalize-    , normalizeWith-    , normalizeWithM-    , Normalizer-    , NormalizerM-    , ReifiedNormalizer (..)-    , judgmentallyEqual-    , subst-    , shift-    , isNormalized-    , isNormalizedWith-    , freeIn-    ) where--import Control.Applicative (empty)-import Data.Foldable-import Data.Functor.Identity (Identity(..))-import Data.Semigroup (Semigroup(..))-import Data.Sequence (ViewL(..), ViewR(..))-import Data.Traversable-import Instances.TH.Lift ()-import Prelude hiding (succ)--import Dhall.Syntax-    ( Expr(..)-    , Var(..)-    , Binding(Binding)-    , Chunks(..)-    , DhallDouble(..)-    , Const(..)-    , PreferAnnotation(..)-    )--import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text-import qualified Dhall.Eval    as Eval-import qualified Dhall.Map-import qualified Dhall.Set-import qualified Dhall.Syntax  as Syntax-import qualified Lens.Family   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 #-}--{-| `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 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 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 Syntax.subExpressions (shift d v) expression--{-| 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 (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') (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 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-->>> alphaNormalize (Lam "a" (Const Type) (Lam "b" (Const Type) (Lam "x" "a" (Lam "y" "b" "x"))))-Lam "_" (Const Type) (Lam "_" (Const Type) (Lam "_" (Var (V "_" 1)) (Lam "_" (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 `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` 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--{-| 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 =  case e of-    Const k -> pure (Const k)-    Var v -> pure (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 -> do-      res <- ctx (App f a)-      case res of-          Just e1 -> loop e1-          Nothing -> do-              f' <- loop f-              a' <- loop a-              case f' of-                Lam x _A b₀ -> do--                    let a₂ = shift 1 (V x 0) a'-                    let b₁ = subst (V x 0) a₂ b₀-                    let b₂ = shift (-1) (V x 0) b₁--                    loop b₂-                _ -> do-                  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 !0 = loop zero-                        strictLoop !n = App succ' <$> strictLoop (n - 1) >>= loop--                        lazyLoop !0 = zero-                        lazyLoop !n = App succ' (lazyLoop (n - 1))-                    App NaturalBuild g -> loop (App (App (App g Natural) succ) zero)-                      where-                        succ = Lam "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 [] (Data.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 [] ("+" <> Data.Text.pack (show n))))-                        | otherwise -> pure (TextLit (Chunks [] (Data.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 [] (Data.Text.pack (show n))))-                    App (App OptionalBuild _A₀) g ->-                        loop (App (App (App g optional) just) nothing)-                      where-                        optional = App Optional _A₀--                        just = Lam "a" _A₀ (Some "a")--                        nothing = App None _A₀-                    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 (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 = do-                          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", Natural)-                                  , ("value", _A₀)-                                  ]--                        t | null as₀  = Just (App List _A₂)-                          | otherwise = Nothing--                        adapt n a_ =-                            RecordLit (Dhall.Map.fromList kvs)-                          where-                            kvs = [ ("index", NaturalLit (fromIntegral n))-                                  , ("value", a_)-                                  ]-                    App (App ListReverse _) (ListLit t xs) ->-                        loop (ListLit t (Data.Sequence.reverse xs))--                    App (App OptionalFold t0) x0 -> do-                        t1 <- loop t0-                        let optional = Var (V "optional" 0)-                        let lam term = (Lam "optional"-                                           (Const Type)-                                           (Lam "some"-                                               (Pi "_" t1 optional)-                                               (Lam "none" optional term)))-                        x1 <- loop x0-                        pure $ case x1 of-                            App None _ -> lam (Var (V "none" 0))-                            Some x'    -> lam (App (Var (V "some" 0)) x')-                            _          -> App (App OptionalFold t1) x1--                    App TextShow (TextLit (Chunks [] oldText)) ->-                        loop (TextLit (Chunks [] newText))-                      where-                        newText = Eval.textShow oldText-                    _ -> 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'  = 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 -> 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-    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)] ""))-    TextShow -> pure TextShow-    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-    OptionalFold -> pure OptionalFold-    OptionalBuild -> pure OptionalBuild-    Record kts -> Record . Dhall.Map.sort <$> kts'-      where-        kts' = traverse loop kts-    RecordLit kvs -> RecordLit . Dhall.Map.sort <$> kvs'-      where-        kvs' = traverse loop kvs-    Union kts -> Union . Dhall.Map.sort <$> kts'-      where-        kts' = traverse (traverse loop) kts-    Combine 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 decide m n)-        decide l r =-            Combine mk l r-    CombineTypes 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 decide m n)-        decide l r =-            CombineTypes l r-    Prefer _ 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 PreferFromSource l r-    RecordCompletion x y -> do-        loop (Annot (Prefer PreferFromCompletion (Field x "default") y) (Field x "Type"))-    Merge x y t      -> do-        x' <- loop x-        y' <- loop y-        case x' of-            RecordLit kvsX ->-                case y' of-                    Field (Union ktsY) kY ->-                        case Dhall.Map.lookup kY ktsY of-                            Just Nothing ->-                                case Dhall.Map.lookup kY kvsX of-                                    Just vX -> return vX-                                    Nothing -> Merge x' y' <$> t'-                            _ ->-                                Merge x' y' <$> t'-                    App (Field (Union ktsY) kY) vY ->-                        case Dhall.Map.lookup kY ktsY of-                            Just (Just _) ->-                                case Dhall.Map.lookup kY kvsX of-                                    Just vX -> loop (App vX vY)-                                    Nothing -> Merge x' y' <$> t'-                            _ ->-                                Merge x' y' <$> t'-                    Some a ->-                        case Dhall.Map.lookup "Some" kvsX of-                            Just vX -> loop (App vX a)-                            Nothing -> Merge x' y' <$> t'-                    App None _ ->-                        case 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"  , TextLit (Chunks [] key))-                                , ("mapValue", value                  )-                                ]-                            )--                let keyValues = Data.Sequence.fromList (map entry (Dhall.Map.toList kvsX))--                let listType = case t' of-                        Just _ | null keyValues ->-                            t'-                        _ ->-                            Nothing--                return (ListLit listType keyValues)-            _ -> do-                return (ToMap x' t')-    Field r 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 v-                    Nothing -> Field <$> (RecordLit <$> traverse loop kvs) <*> pure x-            Project r_ _ -> loop (Field r_ x)-            Prefer _ (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of-                Just v -> pure (Field (Prefer PreferFromSource (singletonRecordLit v) r_) x)-                Nothing -> loop (Field r_ x)-            Prefer _ l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of-                Just v -> pure v-                Nothing -> loop (Field l x)-            Combine m (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of-                Just v -> pure (Field (Combine m (singletonRecordLit v) r_) x)-                Nothing -> loop (Field r_ x)-            Combine m l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of-                Just v -> pure (Field (Combine m l (singletonRecordLit v)) x)-                Nothing -> loop (Field l x)-            _ -> pure (Field r' x)-    Project x (Left fields)-> do-        x' <- loop x-        let fieldsSet = Dhall.Set.toSet fields-        case x' of-            RecordLit kvs ->-                pure (RecordLit (Dhall.Map.restrictKeys kvs fieldsSet))-            Project y _ ->-                loop (Project y (Left fields))-            Prefer _ l (RecordLit rKvs) -> do-                let rKs = Dhall.Map.keysSet rKvs-                let l' = Project l (Left (Dhall.Set.fromSet (Data.Set.difference fieldsSet rKs)))-                let r' = RecordLit (Dhall.Map.restrictKeys rKvs fieldsSet)-                loop (Prefer PreferFromSource l' r')-            _ | null fields -> pure (RecordLit mempty)-              | otherwise   -> pure (Project x' (Left (Dhall.Set.sort fields)))-    Project r (Right e1) -> do-        e2 <- loop e1--        case e2 of-            Record kts -> do-                loop (Project r (Left (Dhall.Set.fromSet (Dhall.Map.keysSet kts))))-            _ -> do-                r' <- loop r-                pure (Project r' (Right e2))-    Assert t -> do-        t' <- loop t--        pure (Assert t')-    Equivalent l r -> do-        l' <- loop l-        r' <- loop r--        pure (Equivalent l' r')-    With e' k v -> do-        loop (Syntax.desugarWith (With e' k 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 _ a b -> loop a && loop b-      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 (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 OptionalBuild _) _ -> 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 (App OptionalFold _) (Some _) -> False-          App (App OptionalFold _) (App None _) -> False-          App TextShow (TextLit (Chunks [] _)) ->-              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)-      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-      TextShow -> 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-      OptionalFold -> True-      OptionalBuild -> True-      Record kts -> Dhall.Map.isSorted kts && all loop kts-      RecordLit kvs -> Dhall.Map.isSorted kvs && all loop kvs-      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-      Field r k -> 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-      Project r p -> loop r &&-          case p of-              Left s -> case r of-                  RecordLit _ -> False-                  Project _ _ -> False-                  Prefer _ _ (RecordLit _) -> False-                  _ -> not (Dhall.Set.null s) && Dhall.Set.isSorted 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 "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+{-# 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
@@ -3,51 +3,83 @@     for convenience -} -module Dhall.Optics-    ( -- * Utilities-      rewriteOf+{-# 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 (WrappedMonad(..))-import Data.Profunctor.Unsafe ((#.))-import Lens.Family (ASetter, LensLike, over)+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 l f = go-  where-    go = transformOf l (\x -> maybe x go (f x))+rewriteOf = Lens.Micro.rewriteOf {-# INLINE rewriteOf #-}  -- | Identical to @"Control.Lens".`Control.Lens.transformOf`@ transformOf :: ASetter a b a b -> (b -> b) -> a -> b-transformOf l f = go-  where-    go = f . over l go+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 l f = go-  where-    go = transformMOf l (\x -> f x >>= maybe (return x) go)+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 l f = go-  where-    go t = mapMOf l go t >>= f+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 l cmd = unwrapMonad #. l (WrapMonad #. cmd)+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,4 +1,5 @@-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}  -- | This module contains Dhall's parsing logic @@ -20,23 +21,21 @@     , Parser(..)     ) where -import Control.Exception (Exception)-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-import Data.Void (Void)+import Control.Applicative (many)+import Control.Exception   (Exception)+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Src           (Src (..)) import Dhall.Syntax-import Dhall.Src (Src(..))-import Prelude hiding (const, pi)-import Text.Megaparsec (ParseErrorBundle(..), PosState(..))+import Text.Megaparsec     (ParseErrorBundle (..), PosState (..)) -import qualified Data.Char-import qualified Data.Text+import qualified Data.Text       as Text import qualified Dhall.Core      as Core import qualified Text.Megaparsec  import Dhall.Parser.Combinators-import Dhall.Parser.Token hiding (text) import Dhall.Parser.Expression+import Dhall.Parser.Token       hiding (text)  -- | Parser for a top-level Dhall expression expr :: Parser (Expr Src Import)@@ -78,7 +77,7 @@  instance Exception ParseError --- | Parse an expression from `Text` containing a Dhall program+-- | Parse an expression from `Text.Text` containing a Dhall program exprFromText   :: String -- ^ User-friendly name describing the input expression,             --   used in parsing error messages@@ -94,9 +93,16 @@  -- | Create a header with stripped leading spaces and trailing newlines createHeader :: Text -> Header-createHeader =-    Header . Data.Text.dropWhile Data.Char.isSpace . Data.Text.dropWhileEnd (/= '\n')+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 --@@ -118,7 +124,7 @@     Right (txt, r) -> Right (createHeader txt, r)   where     parser = do-        (bytes, _) <- Text.Megaparsec.match whitespace+        (bytes, _) <- Text.Megaparsec.match (many shebang *> whitespace)         r <- expr         Text.Megaparsec.eof         return (bytes, r)
src/Dhall/Parser/Combinators.hs view
@@ -1,33 +1,46 @@ {-# LANGUAGE CPP                   #-}-{-# LANGUAGE DeriveAnyClass        #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings     #-}-module Dhall.Parser.Combinators where +{-| This module contains Dhall's parser combinators+-} -import           Control.Applicative        (Alternative (..), liftA2)-import           Control.Exception          (Exception)-import           Control.Monad              (MonadPlus (..))-import           Data.Semigroup             (Semigroup (..))-import           Data.String                (IsString (..))-import           Data.Text                  (Text)-import           Data.Text.Prettyprint.Doc  (Pretty (..))-import           Data.Void                  (Void)-import           Dhall.Map                  (Map)-import           Dhall.Set                  (Set)-import           Dhall.Src                  (Src(..))-import           Prelude                    hiding (const, pi)-import           Text.Parser.Combinators    (try, (<?>))-import           Text.Parser.Token          (TokenParsing (..))+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-import qualified Data.Set+import qualified Data.Char                   as Char import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty import qualified Dhall.Map import qualified Dhall.Pretty-import qualified Dhall.Set+import qualified Prettyprinter.Render.String as Pretty import qualified Text.Megaparsec import qualified Text.Megaparsec.Char import qualified Text.Parser.Char@@ -47,9 +60,9 @@         <>  Pretty.renderString                 (Dhall.Pretty.layout (pretty source)) --- | Doesn't force the 'Text' part+-- | 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'+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@@ -123,14 +136,8 @@     -- {-# INLINE mplus #-}  instance Text.Megaparsec.MonadParsec Void Text Parser where-#if MIN_VERSION_megaparsec(8, 0, 0)     parseError e = Parser (Text.Megaparsec.parseError e)-#else-    failure u e    = Parser (Text.Megaparsec.failure u e) -    fancyFailure e = Parser (Text.Megaparsec.fancyFailure e)-#endif-     label l (Parser p) = Parser (Text.Megaparsec.label l p)      hidden (Parser p) = Parser (Text.Megaparsec.hidden p)@@ -162,16 +169,16 @@      updateParserState f = Parser (Text.Megaparsec.updateParserState f) -instance Data.Semigroup.Semigroup a => Data.Semigroup.Semigroup (Parser a) where+#if MIN_VERSION_megaparsec(9,4,0)+    mkParsec f = Parser (Text.Megaparsec.mkParsec f)+#endif++instance Semigroup a => Semigroup (Parser a) where     (<>) = liftA2 (<>) -instance (Data.Semigroup.Semigroup a, Monoid a) => Monoid (Parser a) where+instance (Semigroup a, Monoid a) => Monoid (Parser a) where     mempty = pure mempty -#if !(MIN_VERSION_base(4,11,0))-    mappend = (<>)-#endif- instance IsString a => IsString (Parser a) where     fromString x = fromString x <$ Text.Megaparsec.Char.string (fromString x) @@ -206,16 +213,18 @@ instance TokenParsing Parser where     someSpace =         Text.Parser.Token.Style.buildSomeSpaceParser-            (Parser (Text.Megaparsec.skipSome (Text.Megaparsec.satisfy Data.Char.isSpace)))+            (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@@ -223,33 +232,35 @@     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) -noDuplicates :: Ord a => [a] -> Parser (Set a)-noDuplicates = go Dhall.Set.empty-  where-    go found    []  = return found-    go found (x:xs) =-        if Data.Set.member x (Dhall.Set.toSet found)-        then fail "Duplicate key"-        else go (Dhall.Set.append x found) xs-+-- | 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@@ -258,6 +269,8 @@     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)]@@ -265,3 +278,15 @@ 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
@@ -1,47 +1,39 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE NamedFieldPuns      #-}-{-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE OverloadedLists     #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}  -- | Parsing Dhall expressions. module Dhall.Parser.Expression where -import Control.Applicative (liftA2, Alternative(..), optional)-import Data.ByteArray.Encoding (Base(..))-import Data.Foldable (foldl')-import Data.Functor (void)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)+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 Dhall.Src (Src(..))-import Prelude hiding (const, pi) 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.ByteArray.Encoding-import qualified Data.ByteString+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 position-getSourcePos :: Text.Megaparsec.MonadParsec e s m =>-                m Text.Megaparsec.SourcePos-getSourcePos =-    Text.Megaparsec.getSourcePos-{-# INLINE getSourcePos #-}- -- | Get the current source offset (in tokens) getOffset :: Text.Megaparsec.MonadParsec e s m => m Int getOffset = Text.Megaparsec.stateOffset <$> Text.Megaparsec.getParserState@@ -59,19 +51,27 @@ -} src :: Parser a -> Parser Src src parser = do-    before      <- getSourcePos+    before      <- Text.Megaparsec.getSourcePos     (tokens, _) <- Text.Megaparsec.match parser-    after       <- getSourcePos+    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      <- getSourcePos+    before      <- Text.Megaparsec.getSourcePos     (tokens, e) <- Text.Megaparsec.match parser-    after       <- getSourcePos+    after       <- Text.Megaparsec.getSourcePos     let src₀ = Src before after tokens     case e of         Note src₁ _ | laxSrcEq src₀ src₁ -> return e@@ -107,14 +107,186 @@ data Parsers a = Parsers     { completeExpression_ :: Parser (Expr Src a)     , importExpression_   :: Parser (Expr Src a)+    , letBinding          :: Parser (Binding Src a)     } --- | Given a parser for imports, -parsers :: Parser a -> Parsers a-parsers embedded = Parsers {..}+{-| 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+    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@@ -128,22 +300,22 @@             ) <?> "expression"       where         alternative0 = do-            _lambda+            cs <- _lambda             whitespace             _openParens-            whitespace+            src0 <- src whitespace             a <- label-            whitespace+            src1 <- src whitespace             _colon-            nonemptyWhitespace+            src2 <- src nonemptyWhitespace             b <- expression             whitespace             _closeParens             whitespace-            _arrow+            cs' <- _arrow             whitespace             c <- expression-            return (Lam a b c)+            return (Lam (Just (cs <> cs')) (FunctionBinding (Just src0) a (Just src1) (Just src2) b) c)          alternative1 = do             try (_if *> nonemptyWhitespace)@@ -157,35 +329,7 @@             return (BoolIf a b c)          alternative2 = do-            let binding = 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)--            as <- NonEmpty.some1 binding+            as <- NonEmpty.some1 letBinding              try (_in *> nonemptyWhitespace) @@ -211,7 +355,7 @@             return (Dhall.Syntax.wrapInLets as b)          alternative3 = do-            try (_forall *> whitespace *> _openParens)+            cs <- try (_forall <* whitespace <* _openParens)             whitespace             a <- label             whitespace@@ -221,10 +365,10 @@             whitespace             _closeParens             whitespace-            _arrow+            cs' <- _arrow             whitespace             c <- expression-            return (Pi a b c)+            return (Pi (Just (cs <> cs')) a b c)          alternative4 = do             try (_assert *> whitespace *> _colon)@@ -233,55 +377,24 @@             return (Assert a)          alternative5 = do-            a0 <- applicationExpression+            (a0Info, a0) <- applicationExpressionWithInfo              let (parseFirstOperatorExpression, parseOperatorExpression) =                     operatorExpression (pure a0) -            a <- parseFirstOperatorExpression--            let alternative4A = do-                    _arrow-                    whitespace-                    b <- expression-                    whitespace-                    return (Pi "_" a b)--            let alternative4B = do-                    _colon-                    nonemptyWhitespace-                    b <- expression-                    case shallowDenote a of-                        ListLit Nothing [] ->-                            return (ListLit (Just b) [])-                        Merge c d Nothing ->-                            return (Merge c d (Just b))-                        ToMap c Nothing ->-                            return (ToMap c (Just b))-                        _ -> return (Annot a b)+            let alternative5A = do+                    case a0Info of+                        ImportExpr -> return ()+                        _          -> empty -            let alternative4C = do-                    case shallowDenote a of-                        Equivalent{}   -> empty-                        ImportAlt{}    -> empty-                        BoolOr{}       -> empty-                        NaturalPlus{}  -> empty-                        TextAppend{}   -> empty-                        ListAppend{}   -> empty-                        BoolAnd{}      -> empty-                        Combine{}      -> empty-                        Prefer{}       -> empty-                        CombineTypes{} -> empty-                        NaturalTimes{} -> empty-                        BoolEQ{}       -> empty-                        BoolNE{}       -> empty-                        App{}          -> empty-                        _              -> return ()+                    bs <- some (do+                        try (nonemptyWhitespace *> _with *> nonemptyWhitespace) -                    bs <- many (do-                        try (whitespace *> _with *> nonemptyWhitespace)+                        let withComponent =+                                    fmap WithLabel anyLabelOrSome+                                <|> fmap (\_ -> WithQuestion) (text "?") -                        keys <- Combinators.NonEmpty.sepBy1 anyLabel (try (whitespace *> _dot) *> whitespace)+                        keys <- Combinators.NonEmpty.sepBy1 withComponent (try (whitespace *> _dot) *> whitespace)                          whitespace @@ -295,8 +408,49 @@                      return (foldl (\e f -> f e) a0 bs) -            alternative4A <|> alternative4B <|> alternative4C <|> pure a+            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@@ -314,55 +468,73 @@          nil = (firstApplicationExpression, applicationExpression) -    makeOperatorExpression firstSubExpression operatorParser subExpression =-            noted (do-                a <- firstSubExpression+    makeOperatorExpression firstSubExpression operatorParser subExpression = do+            a <- firstSubExpression -                whitespace+            bs <- Text.Megaparsec.many $ do+                (Src _ _ textOp, op0) <- srcAnd (try (whitespace *> operatorParser)) -                b <- Text.Megaparsec.many $ do-                    op <- operatorParser+                r0 <- subExpression -                    r  <- 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 -                    whitespace+                return (`op` r0) -                    return (\l -> l `op` r)-                return (foldl' (\x f -> f x) a b))+            return (foldl' (\x f -> f x) a bs)      operatorParsers :: [Parser (Expr s a -> Expr s a -> Expr s a)]     operatorParsers =-        [ Equivalent              <$ _equivalent   <* whitespace-        , ImportAlt               <$ _importAlt    <* nonemptyWhitespace-        , BoolOr                  <$ _or           <* whitespace-        , NaturalPlus             <$ _plus         <* nonemptyWhitespace-        , TextAppend              <$ _textAppend   <* whitespace-        , ListAppend              <$ _listAppend   <* whitespace-        , BoolAnd                 <$ _and          <* whitespace-        , Combine Nothing         <$ _combine      <* whitespace-        , Prefer PreferFromSource <$ _prefer       <* whitespace-        , CombineTypes            <$ _combineTypes <* whitespace-        , NaturalTimes            <$ _times        <* whitespace+        [ 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+        , BoolEQ                      <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace+        , BoolNE                      <$ _notEqual      <* whitespace         ] -    applicationExpression = do+    applicationExpression = snd <$> applicationExpressionWithInfo++    applicationExpressionWithInfo :: Parser (ApplicationExprInfo, Expr Src a)+    applicationExpressionWithInfo = do             let alternative0 = do-                    _ <- try (_Some <* nonemptyWhitespace)+                    try (_merge *> nonemptyWhitespace) -                    return (Some, Just "argument to ❰Some❱")+                    a <- importExpression_ <* nonemptyWhitespace +                    return (\b -> Merge a b Nothing, Just "second argument to ❰merge❱")+             let alternative1 = do-                    _ <- try (_toMap *> nonemptyWhitespace)+                    try (_Some *> nonemptyWhitespace) -                    return (\a -> ToMap a Nothing, Just "argument to ❰toMap❱")+                    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+            (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3 <|> alternative4              let adapt parser =                     case maybeMessage of@@ -376,7 +548,15 @@                 b <- importExpression_                 return (sep, b) -            return (foldl' app (f a) bs)+            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@@ -416,25 +596,44 @@             let projectBySet        xs e = Project e (Left  xs)             let projectByExpression xs e = Project e (Right xs) -            let alternatives =-                        fmap field               anyLabel-                    <|> fmap projectBySet        labels-                    <|> fmap projectByExpression recordType+            let alternatives = do+                    src0 <- src whitespace -            b <- Text.Megaparsec.many (try (whitespace *> _dot *> whitespace *> alternatives))+                    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-                    [ alternative00+                    [ bytesLiteral+                    , temporalLiteral+                    , alternative00                     , alternative01                     , alternative02-                    , alternative03+                    , textLiteral                     , alternative04-                    , alternative05-                    , alternative06-                    , alternative07+                    , unionType+                    , listLiteral                     , alternative37                     , alternative09                     , builtin@@ -458,34 +657,25 @@                 a <- try integerLiteral                 return (IntegerLit a) -            alternative03 = textLiteral-             alternative04 = (do                 _openBrace -                whitespace--                _ <- optional (_comma *> whitespace)+                src0 <- src whitespace+                mComma <- optional _comma -                a <- recordTypeOrLiteral+                -- `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 -                whitespace+                a <- recordTypeOrLiteral src1                  _closeBrace                  return a ) <?> "literal" -            alternative05 = unionType--            alternative06 = listLiteral--            alternative07 = do-                try (_merge *> nonemptyWhitespace)-                a <- importExpression_-                nonemptyWhitespace-                b <- importExpression_ <?> "second argument to ❰merge❱"-                return (Merge a b Nothing)-             alternative09 = do                 a <- try doubleInfinity                 return (DoubleLit (DhallDouble a))@@ -533,7 +723,9 @@                      'D' ->                         choice-                            [ DoubleShow       <$ _DoubleShow+                            [ DateShow         <$ _DateShow+                            , Date             <$ _Date+                            , DoubleShow       <$ _DoubleShow                             , Double           <$ _Double                             ]                     'L' ->@@ -547,18 +739,22 @@                             , ListReverse      <$ _ListReverse                             , List             <$ _List                             ]-                    'O' ->+                    'O' ->    Optional         <$ _Optional+                    'B' ->                         choice-                            [ OptionalFold     <$ _OptionalFold-                            , OptionalBuild    <$ _OptionalBuild-                            , Optional         <$ _Optional+                            [ Bool             <$ _Bool+                            , Bytes            <$ _Bytes                             ]-                    'B' ->    Bool             <$ _Bool                     'S' ->    Const Sort       <$ _Sort                     'T' ->                         choice-                            [ TextShow         <$ _TextShow+                            [ TextReplace      <$ _TextReplace+                            , TextShow         <$ _TextShow                             , Text             <$ _Text+                            , TimeZoneShow     <$ _TimeZoneShow+                            , TimeZone         <$ _TimeZone+                            , TimeShow         <$ _TimeShow+                            , Time             <$ _Time                             , BoolLit True     <$ _True                             , Const Type       <$ _Type                             ]@@ -647,7 +843,7 @@                      let fourCharacterEscapeSequence = do                             ns <- Control.Monad.replicateM 4 hexNumber-                            +                             let number = toNumber ns                              Control.Monad.guard (validCodepoint number)@@ -687,7 +883,7 @@                 , unescapedCharacterFast                 , unescapedCharacterSlow                 , tab-                , endOfLine+                , endOfLine_                 ]           where                 escapeSingleQuotes = do@@ -726,7 +922,7 @@                   where                     predicate c = c == '$' || c == '\'' -                endOfLine = do+                endOfLine_ = do                     a <- "\n" <|> "\r\n"                     b <- singleQuoteContinue                     return (Chunks [] a <> b)@@ -738,100 +934,140 @@      singleQuoteLiteral = do             _ <- text "''"+             _ <- endOfLine+             a <- singleQuoteContinue              return (Dhall.Syntax.toDoubleQuoted a)-          where-            endOfLine = (void (char '\n') <|> void (text "\r\n")) <?> "newline"      textLiteral = (do-            literal <- doubleQuotedLiteral <|> singleQuoteLiteral-            return (TextLit literal) ) <?> "literal"+        literal <- doubleQuotedLiteral <|> singleQuoteLiteral+        return (TextLit literal) ) <?> "literal" -    recordTypeOrLiteral =+    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-                [ alternative0-                , alternative1-                , alternative2+                [ emptyRecordLiteral+                , nonEmptyRecordTypeOrLiteral firstSrc0+                , emptyRecordType                 ]-          where-            alternative0 = do-                _equal-                return (RecordLit mempty) -            alternative1 = nonEmptyRecordTypeOrLiteral--            alternative2 = return (Record mempty)+    emptyRecordLiteral = do+        _equal -    nonEmptyRecordTypeOrLiteral = do-            let nonEmptyRecordType = do-                    a <- try (anyLabel <* whitespace <* _colon)+        _ <- optional (try (whitespace *> _comma)) -                    nonemptyWhitespace+        whitespace+        return (RecordLit mempty) -                    b <- expression+    emptyRecordType = return (Record mempty) -                    whitespace+    nonEmptyRecordTypeOrLiteral firstSrc0 = do+            let nonEmptyRecordType = do+                    (firstKeySrc1, a) <- try $ do+                        a <- anyLabelOrSome+                        s <- src whitespace+                        _colon+                        return (s, a) -                    e <- Text.Megaparsec.many (do-                        _comma+                    firstKeySrc2 <- src nonemptyWhitespace -                        whitespace+                    b <- expression -                        c <- anyLabel+                    e <- Text.Megaparsec.many $ do+                        (src0', c) <- try $ do+                            _comma+                            src0' <- src whitespace+                            c <- anyLabelOrSome+                            return (src0', c) -                        whitespace+                        src1 <- src whitespace                          _colon -                        nonemptyWhitespace+                        src2 <- src nonemptyWhitespace                          d <- expression                          whitespace -                        return (c, d) )+                        return (c, RecordField (Just src0') d (Just src1) (Just src2)) -                    m <- toMap ((a, b) : e)+                    _ <- optional (whitespace *> _comma)+                    whitespace +                    m <- toMap ((a, RecordField (Just firstSrc0) b (Just firstKeySrc1) (Just firstKeySrc2)) : e)+                     return (Record m) -            let keysValue = do-                    keys <- Combinators.NonEmpty.sepBy1 anyLabel (try (whitespace *> _dot) *> whitespace)+            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 (whitespace *> _equal)+                            try _equal -                            whitespace+                            lastSrc2 <- src whitespace                              value <- expression -                            let cons key (key', values) =-                                    (key, RecordLit [ (key', values) ])+                            let cons (s0, key, s1) (key', values) =+                                    (key, RecordField (Just s0) (RecordLit [ (key', values) ]) (Just s1) Nothing) -                            let nil = (NonEmpty.last keys, value)+                            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-                                x :| [] -> return (x, Var (V x 0))+                                (s0, x, s1) :| [] -> return (x, RecordField (Just s0) (Var (V x 0)) (Just s1) Nothing)                                 _       -> empty                      (normalRecordEntry <|> punnedEntry) <* whitespace              let nonEmptyRecordLiteral = do-                    as <- Text.Megaparsec.sepBy1 keysValue (_comma *> whitespace)+                    a <- keysValue (Just firstSrc0) -                    {- The `flip` is necessary because `toMapWith` is internally-                       based on `Data.Map.fromListWithKey` which combines keys-                       in reverse order-                    -}-                    let combine k = liftA2 (flip (Combine (Just k)))+                    as <- many (try (_comma *> keysValue Nothing)) -                    m <- toMapWith combine as+                    _ <- 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@@ -841,35 +1077,60 @@              whitespace -            _ <- optional (_bar *> whitespace)-             let unionTypeEntry = do-                    a <- anyLabel+                    a <- anyLabelOrSome+                     whitespace+                     b <- optional (_colon *> nonemptyWhitespace *> expression <* whitespace)+                     return (a, b) -            kvs <- Text.Megaparsec.sepBy unionTypeEntry (_bar *> whitespace)+            let nonEmptyUnionType = do+                    kv <- try (optional (_bar *> whitespace) *> unionTypeEntry) -            m <- toMap kvs+                    kvs <- many (try (_bar *> whitespace *> unionTypeEntry)) -            _closeAngle+                    m <- toMap (kv : kvs) -            return (Union m) ) <?> "literal"+                    _ <- 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 -            _ <- optional (_comma *> whitespace)+            let nonEmptyListLiteral = do+                    a <- try (optional (_comma *> whitespace) *> expression) -            a <- Text.Megaparsec.sepBy (expression <* whitespace) (_comma *> whitespace)+                    whitespace -            _closeBracket+                    as <- many (try (_comma *> whitespace *> expression) <* whitespace) -            return (ListLit Nothing (Data.Sequence.fromList a)) ) <?> "literal"+                    _ <- 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@@ -973,9 +1234,9 @@     _ <- text "sha256:"     t <- count 64 (satisfy hexdig <?> "hex digit")     let strictBytes16 = Data.Text.Encoding.encodeUtf8 t-    strictBytes <- case Data.ByteArray.Encoding.convertFromBase Base16 strictBytes16 of+    strictBytes <- case Base16.decode strictBytes16 of         Left  string      -> fail string-        Right strictBytes -> return (strictBytes :: Data.ByteString.ByteString)+        Right strictBytes -> return strictBytes     case Dhall.Crypto.sha256DigestFromByteString strictBytes of       Nothing -> fail "Invalid sha256 hash"       Just h  -> pure h@@ -1003,4 +1264,16 @@     alternative = do       try (whitespace *> _as *> nonemptyWhitespace) -      (_Text >> pure RawText) <|> (_Location >> pure Location)+      (_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
@@ -1,11 +1,15 @@-{-# LANGUAGE RecordWildCards #-} {-# 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,@@ -14,16 +18,25 @@     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,@@ -34,6 +47,7 @@     _using,     _merge,     _toMap,+    _showConstructor,     _assert,     _Some,     _None,@@ -57,14 +71,20 @@     _ListLast,     _ListIndexed,     _ListReverse,-    _OptionalFold,-    _OptionalBuild,     _Bool,+    _Bytes,     _Natural,     _Integer,     _Double,     _Text,+    _TextReplace,     _TextShow,+    _Date,+    _DateShow,+    _Time,+    _TimeShow,+    _TimeZone,+    _TimeZoneShow,     _List,     _True,     _False,@@ -108,19 +128,18 @@     _with,     ) where -import           Dhall.Parser.Combinators+import Dhall.Parser.Combinators -import Control.Applicative (Alternative(..), optional)-import Data.Bits ((.&.))-import Data.Functor (void, ($>))-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)+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 Dhall.Set (Set)-import Prelude hiding (const, pi) import Text.Parser.Combinators (choice, try, (<?>)) -import qualified Control.Monad+import qualified Control.Monad              as Monad import qualified Data.Char                  as Char import qualified Data.Foldable import qualified Data.HashSet@@ -128,22 +147,26 @@ import qualified Data.List.NonEmpty import qualified Data.Scientific            as Scientific import qualified Data.Text-import qualified Dhall.Set-import qualified Network.URI.Encode         as URI.Encode import qualified Text.Megaparsec import qualified Text.Megaparsec.Char.Lexer import qualified Text.Parser.Char-import qualified Text.Parser.Token import qualified Text.Parser.Combinators+import qualified Text.Parser.Token  import Numeric.Natural (Natural)-import Prelude hiding (const, pi) +-- | 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 +    not (category == Char.Surrogate+      || c .&. 0xFFFE == 0xFFFE       || c .&. 0xFFFF == 0xFFFF)   where     category = Char.generalCategory (Char.chr c)@@ -181,13 +204,14 @@     ||  ('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 `Double` literal+{-| Parse a `Dhall.Syntax.Double` literal      This corresponds to the @double-literal@ rule from the official grammar -}@@ -259,7 +283,7 @@     a <- text "Infinity" >> return (1.0/0.0)     return (sign a) ) <?> "literal" -{-| Parse an `Integer` literal+{-| Parse an `Dhall.Syntax.Integer` literal      This corresponds to the @integer-literal@ rule from the official grammar -}@@ -269,17 +293,20 @@     a    <- naturalLiteral     return (sign (fromIntegral a)) ) <?> "literal" -{-| Parse a `Natural` literal +{-| Parse a `Dhall.Syntax.Natural` literal      This corresponds to the @natural-literal@ rule from the official grammar -} naturalLiteral :: Parser Natural naturalLiteral = (do-    a <-    try (char '0' >> char 'x' >> Text.Megaparsec.Char.Lexer.hexadecimal)+    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@@ -299,7 +326,100 @@           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@@ -325,8 +445,8 @@     choice         [ void (Dhall.Parser.Combinators.takeWhile1 predicate)         , void (Text.Parser.Char.text "\r\n" <?> "newline")-        , lineComment-        , blockComment+        , void lineComment+        , void blockComment         ] <?> "whitespace"   where     predicate c = c == ' ' || c == '\t' || c == '\n'@@ -353,29 +473,31 @@       where         predicate c = 'a' <= c && c <= 'f' -lineComment :: Parser ()-lineComment = do+-- | 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' -    _ <- Dhall.Parser.Combinators.takeWhile predicate+    commentText <- Dhall.Parser.Combinators.takeWhile predicate -    endOfLine+    return ("--" <> commentText) -    return ()-  where-    endOfLine =-        (   void (Text.Parser.Char.char '\n'  )-        <|> void (Text.Parser.Char.text "\r\n")-        ) <?> "newline"+-- | 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) -blockComment :: Parser ()+-- | Parsed text doesn't include opening braces+blockComment :: Parser Text blockComment = do     _ <- text "{-"-    blockCommentContinue+    c <- blockCommentContinue+    pure ("{-" <> c <> "-}") -blockCommentChunk :: Parser ()+blockCommentChunk :: Parser Text blockCommentChunk =     choice         [ blockComment  -- Nested block comment@@ -384,36 +506,36 @@         , endOfLine         ]   where-    characters = void (Dhall.Parser.Combinators.takeWhile1 predicate)+    characters = (Dhall.Parser.Combinators.takeWhile1 predicate)       where         predicate c =                 '\x20' <= c && c <= '\x10FFFF' && c /= '-' && c /= '{'             ||  c == '\n'             ||  c == '\t' -    character = void (Text.Parser.Char.satisfy predicate)+    character = (Dhall.Parser.Combinators.satisfy predicate)       where         predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t' -    endOfLine = void (Text.Parser.Char.text "\r\n" <?> "newline")--blockCommentContinue :: Parser ()+blockCommentContinue :: Parser Text blockCommentContinue = endOfComment <|> continue   where-    endOfComment = void (text "-}")+    endOfComment = void (text "-}") *> pure ""      continue = do-        blockCommentChunk-        blockCommentContinue+        c <- blockCommentChunk+        c' <- blockCommentContinue+        pure (c <> c')  simpleLabel :: Bool -> Parser Text-simpleLabel allowReserved = try (do+simpleLabel allowReserved = try $ do     c    <- Text.Parser.Char.satisfy headCharacter     rest <- Dhall.Parser.Combinators.takeWhile tailCharacter     let t = Data.Text.cons c rest-    Control.Monad.guard (allowReserved || not (Data.HashSet.member t reservedIdentifiers))-    return t )-  where+    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 == '_'@@ -424,7 +546,7 @@ backtickLabel :: Parser Text backtickLabel = do     _ <- char '`'-    t <- takeWhile1 predicate+    t <- Dhall.Parser.Combinators.takeWhile predicate     _ <- char '`'     return t   where@@ -438,22 +560,32 @@      This corresponds to the @labels@ rule in the official grammar -}-labels :: Parser (Set Text)+labels :: Parser [Text] labels = do     _openBrace+     whitespace-    xs <- nonEmptyLabels <|> emptyLabels-    _closeBrace-    return xs++    nonEmptyLabels <|> emptyLabels   where-    emptyLabels = pure Dhall.Set.empty+    emptyLabels = do+        try (optional (_comma *> whitespace) *> _closeBrace) +        pure []+     nonEmptyLabels = do-        x  <- anyLabel+        x  <- try (optional (_comma *> whitespace) *> anyLabelOrSome)+         whitespace-        xs <- many (do _comma; whitespace; l <- anyLabel; whitespace; return l)-        noDuplicates (x : xs) +        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@)@@ -472,6 +604,14 @@     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@@ -526,7 +666,7 @@     ||  ('\x23' <= c && c <= '\x2E')     ||  ('\x30' <= c && c <= '\x10FFFF') -{-| The `pathComponent` function uses this type to distinguish whether to parse+{-| The @pathComponent@ function uses this type to distinguish whether to parse     a URL path component or a file path component -} data ComponentType = URLComponent | FileComponent@@ -538,23 +678,20 @@      let pathData =             case componentType of-                FileComponent -> do+                FileComponent ->                     Text.Megaparsec.takeWhile1P Nothing Dhall.Syntax.pathCharacter-                URLComponent -> do+                URLComponent ->                     star pchar      let quotedPathData = do             _ <- char '"'             t <- Text.Megaparsec.takeWhile1P Nothing quotedPathCharacter             _ <- char '"'--            case componentType of-              FileComponent -> do-                return t-              URLComponent -> do-                return (URI.Encode.encodeText t)+            return t -    quotedPathData <|> pathData+    case componentType of+        FileComponent -> quotedPathData <|> pathData+        URLComponent -> pathData  -- | Parse a `File` file_ :: ComponentType -> Parser File@@ -719,7 +856,7 @@ pctEncoded = "%" <> count 2 (satisfy hexdig)  subDelims :: Char -> Bool-subDelims c = c `elem` ("!$&'()*+,;=" :: String)+subDelims c = c `elem` ("!$&'*+;=" :: String)  unreserved :: Char -> Bool unreserved c =@@ -823,6 +960,13 @@ _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@@ -988,20 +1132,6 @@ _ListReverse :: Parser () _ListReverse = builtin "List/reverse" -{-| Parse the @Optional/fold@ built-in--    This corresponds to the @Optional-fold@ rule from the official grammar--}-_OptionalFold :: Parser ()-_OptionalFold = builtin "Optional/fold"--{-| Parse the @Optional/build@ built-in--    This corresponds to the @Optional-build@ rule from the official grammar--}-_OptionalBuild :: Parser ()-_OptionalBuild = builtin "Optional/build"- {-| Parse the @Bool@ built-in      This corresponds to the @Bool@ rule from the official grammar@@ -1009,6 +1139,13 @@ _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@@ -1044,6 +1181,13 @@ _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@@ -1051,6 +1195,48 @@ _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@@ -1196,8 +1382,10 @@ _at = reservedChar '@' <?> "\"@\""  -- | Parse the equivalence symbol (@===@ or @≡@)-_equivalent :: Parser ()-_equivalent = (void (char '≡' <?> "\"≡\"") <|> void (text "===")) <?> "operator"+_equivalent :: Parser CharacterSet+_equivalent =+        (Unicode <$ char '≡' <?> "\"≡\"")+    <|> (ASCII <$ text "===" <?> "===")  -- | Parse the @missing@ keyword _missing :: Parser ()@@ -1210,32 +1398,40 @@ _importAlt = operatorChar '?'  -- | Parse the record combine operator (@/\\@ or @∧@)-_combine :: Parser ()-_combine = (void (char '∧' <?> "\"∧\"") <|> void (text "/\\")) <?> "operator"+_combine :: Parser CharacterSet+_combine =+        (Unicode <$ char '∧' <?> "\"∧\"")+    <|> (ASCII <$ text "/\\" <?> "/\\")  -- | Parse the record type combine operator (@//\\\\@ or @⩓@)-_combineTypes :: Parser ()-_combineTypes = (void (char '⩓' <?> "\"⩓\"") <|> void (text "//\\\\")) <?> "operator"+_combineTypes :: Parser CharacterSet+_combineTypes =+        (Unicode <$ char '⩓' <?> "\"⩓\"")+    <|> (ASCII <$ text "//\\\\" <?> "//\\\\")  -- | Parse the record \"prefer\" operator (@//@ or @⫽@)-_prefer :: Parser ()-_prefer = (void (char '⫽' <?> "\"⫽\"") <|> void (text "//")) <?> "operator"+_prefer :: Parser CharacterSet+_prefer =+        (Unicode <$ char '⫽' <?> "\"⫽\"")+    <|> (ASCII <$ text "//" <?> "//")  -- | Parse a lambda (@\\@ or @λ@)-_lambda :: Parser ()-_lambda = void (Text.Parser.Char.satisfy predicate) <?> "\\"-  where-    predicate 'λ'  = True-    predicate '\\' = True-    predicate _    = False+_lambda :: Parser CharacterSet+_lambda =+        (Unicode <$ char 'λ' <?> "\"λ\"")+    <|> (ASCII <$ char '\\' <?> "\\")  -- | Parse a forall (@forall@ or @∀@)-_forall :: Parser ()-_forall = (void (char '∀' <?> "\"∀\"") <|> void (text "forall")) <?> "forall"+_forall :: Parser CharacterSet+_forall =+        (Unicode <$ char '∀' <?> "\"∀\"")+    <|> (ASCII <$ text "forall" <?> "forall")  -- | Parse a right arrow (@->@ or @→@)-_arrow :: Parser ()-_arrow = (void (char '→' <?> "\"→\"") <|> void (text "->")) <?> "->"+_arrow :: Parser CharacterSet+_arrow =+        (Unicode <$ char '→' <?> "\"→\"")+    <|> (ASCII <$ text "->" <?> "->")  -- | Parse a double colon (@::@) _doubleColon :: Parser ()
src/Dhall/Pretty.hs view
@@ -8,13 +8,18 @@     , 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,6 +1,11 @@-{-# LANGUAGE LambdaCase        #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE LambdaCase         #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE ViewPatterns       #-}  {-# OPTIONS_GHC -Wall #-} @@ -15,7 +20,10 @@     , prettySrcExpr      , CharacterSet(..)+    , defaultCharacterSet+    , detectCharacterSet     , prettyCharacterSet+    , prettyImportExpression      , prettyVar     , pretty_@@ -24,6 +32,7 @@     , prettyEnvironmentVariable      , prettyConst+    , UnescapedLabel(..)     , escapeLabel     , prettyLabel     , prettyAnyLabel@@ -34,6 +43,7 @@     , prettyDouble     , prettyToStrictText     , prettyToString+    , prettyBase16     , layout     , layoutOpts @@ -48,7 +58,7 @@     , comma     , dot     , equals-    , forall+    , forall_     , label     , lambda     , langle@@ -61,32 +71,48 @@     , rbrace     , rbracket     , rparen++    , temporalToText     ) where -import Data.Foldable-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty, space)-import Dhall.Map (Map)-import Dhall.Set (Set)-import Dhall.Src (Src(..))-import Dhall.Syntax-import Numeric.Natural (Natural)-import Prelude hiding (succ)-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Terminal+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-import qualified Data.List.NonEmpty                      as NonEmpty-import qualified Data.Set-import qualified Data.Text                               as Text-import qualified Data.Text.Prettyprint.Doc               as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text   as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Dhall.Map                               as Map-import qualified Dhall.Set+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@@ -112,14 +138,51 @@ annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green  -- | This type determines whether to render code as `ASCII` or `Unicode`-data CharacterSet = ASCII | Unicode deriving Show+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 Unicode+prettySrcExpr = prettyCharacterSet defaultCharacterSet  {-| Internal utility for pretty-printing, used when generating element lists     to supply to `enclose` or `enclose'`.  This utility indicates that the@@ -159,18 +222,29 @@     -> Doc Ann renderSrc strip (Just (Src {..}))     | not (Text.all isWhitespace srcText) =-        Pretty.align (Pretty.concatWith f newLines <> suffix)+        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' -    strippedText = strip srcText-     suffix =-        if Text.null strippedText+        if Text.null text || Text.last text == '\n'         then mempty-        else if Text.last strippedText == '\n' then mempty else " "+        else " " -    oldLines = Text.splitOn "\n" strippedText+    oldLines = Text.splitOn "\n" text      spacePrefix = Text.takeWhile horizontalSpace @@ -199,9 +273,27 @@                 in  Pretty.pretty l0 : map perLine ls      f x y = x <> Pretty.hardline <> y-renderSrc _ _ =-    mempty +{-| 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@@ -231,9 +323,9 @@ lambda Unicode = syntax "λ" lambda ASCII   = syntax "\\" -forall :: CharacterSet -> Doc Ann-forall Unicode = syntax "∀"-forall ASCII   = syntax "forall "+forall_ :: CharacterSet -> Doc Ann+forall_ Unicode = syntax "∀"+forall_ ASCII   = syntax "forall "  rarrow :: CharacterSet -> Doc Ann rarrow Unicode = syntax "→"@@ -290,7 +382,7 @@             (  lbrace             <> Pretty.hardline             <> Pretty.indent n-               ( mconcat (zipWith combineLong (repeat separator) docsLong)+               ( mconcat (map (combineLong separator) docsLong)                <> rbrace                )             )@@ -318,7 +410,7 @@ arrows :: CharacterSet -> [ Doc Ann ] -> Doc Ann arrows characterSet docs = Pretty.group (Pretty.flatAlt long short)   where-    long = Pretty.align (mconcat (Data.List.intersperse Pretty.hardline docs'))+    long = Pretty.align (mconcat (List.intersperse Pretty.hardline docs'))       where         docs' = case unsnoc docs of             Nothing -> docs@@ -331,7 +423,7 @@                   last' = space <> space <> last_ -    short = mconcat (Data.List.intersperse separator docs)+    short = mconcat (List.intersperse separator docs)       where         separator = space <> rarrow characterSet <> space @@ -372,7 +464,6 @@     -> Doc ann enclose beginShort _         _        _       endShort _       []   =     beginShort <> endShort-  where enclose beginShort beginLong sepShort sepLong endShort endLong docs =     Pretty.group         (Pretty.flatAlt@@ -391,7 +482,7 @@     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+    trailing document such as nested @let@, nested lambdas, or nested @forall@s -} enclose'     :: Doc ann@@ -411,7 +502,7 @@     longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong      long =-        Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))+        Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))      short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort) @@ -434,34 +525,78 @@ 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 :: Bool -> Text -> Text-escapeLabel allowReserved l =+escapeLabel :: UnescapedLabel -> Text -> Text+escapeLabel allowedLabel l =     case Text.uncons l of         Just (h, t)-            | headCharacter h && Text.all tailCharacter t && (allowReserved || not (Data.HashSet.member l reservedIdentifiers))+            | headCharacter h && Text.all tailCharacter t && allowed && l /= "?"                 -> l         _       -> "`" <> l <> "`"+  where+    allowed = case allowedLabel of+        NonReservedLabel -> notReservedIdentifier+        AnyLabel         -> notReservedKeyword+        AnyLabelOrSome   -> notReservedKeyword || l == "Some" -prettyLabelShared :: Bool -> Text -> Doc Ann+    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 False+prettyLabel = prettyLabelShared NonReservedLabel  prettyAnyLabel :: Text -> Doc Ann-prettyAnyLabel = prettyLabelShared True+prettyAnyLabel = prettyLabelShared AnyLabel -prettyAnyLabels :: Foldable list => list Text -> Doc Ann-prettyAnyLabels =-    mconcat . Pretty.punctuate dot . fmap prettyAnyLabel . toList+prettyAnyLabelOrSome :: Text -> Doc Ann+prettyAnyLabelOrSome = prettyLabelShared AnyLabelOrSome -prettyLabels :: Set Text -> Doc Ann+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-    | Data.Set.null (Dhall.Set.toSet a) =-        lbrace <> rbrace-    | otherwise =-        braces (map (duplicate . prettyAnyLabel) (Dhall.Set.toList a))+    | null a    = lbrace <> rbrace+    | otherwise = braces (map (duplicate . prettyAnyLabelOrSome) a)  prettyNumber :: Integer -> Doc Ann prettyNumber = literal . Pretty.pretty@@ -530,13 +665,33 @@ This means the structure of parsed let-blocks is preserved. -} prettyCharacterSet :: Pretty a => CharacterSet -> Expr Src a -> Doc Ann-prettyCharacterSet characterSet expression =-    Pretty.group (prettyExpression expression)+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 a b c) = Pretty.group (Pretty.flatAlt long short) : docs c+        docs (Lam _ (FunctionBinding { functionBindingVariable = a, functionBindingAnnotation = b }) c) =+            Pretty.group (Pretty.flatAlt long short) : docs c           where             long =  (lambda characterSet <> space)                 <>  Pretty.align@@ -581,7 +736,7 @@         longLines = zipWith (<>) prefixesLong (docsLong True a0)          long =-            Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))+            Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))          short = mconcat (zipWith (<>) prefixesShort (docsShort a0)) @@ -620,11 +775,16 @@                 [ prettyExpression c ]     prettyExpression (Let a0 b0) =         enclose' "" "" space Pretty.hardline-            (fmap duplicate (fmap docA (toList as)) ++ [ docB ])+            (fmap (duplicate . docA) (toList as) ++ [ docB ])       where         MultiLet as b = multiLet a0 b0 -        stripSpaces = Text.dropAround (\c -> c == ' ' || c == '\t')+        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.@@ -663,13 +823,13 @@             ( keyword "in" <> " " <> prettyExpression b             , keyword "in" <> "  "  <> prettyExpression b             )-    prettyExpression a0@(Pi _ _ _) =+    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+        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+            long =  forall_ characterSet <> space                 <>  Pretty.align                     (   lparen <> space                     <>  prettyLabel a@@ -680,7 +840,7 @@                     <>  rparen                     ) -            short = forall characterSet <> lparen+            short = forall_ characterSet <> lparen                 <>  prettyLabel a                 <>  space <> colon <> space                 <>  prettyExpression b@@ -692,8 +852,13 @@                 docs d             | otherwise =                 [ prettyExpression c ]-    prettyExpression (With a b c) =-            prettyExpression a+    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@@ -703,7 +868,11 @@             <>  Pretty.align (keyword "with" <> " " <> update)          (update, _) =-            prettyKeyValue prettyAnyLabels prettyOperatorExpression equals (b, c)+            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@@ -730,20 +899,20 @@             Pretty.align                 (   keyword "merge"                 <>  Pretty.hardline-                <>  Pretty.indent 2 (prettyImportExpression a)+                <>  Pretty.indent 2 (prettyImportExpression_ a)                 <>  Pretty.hardline-                <>  Pretty.indent 2 (prettyImportExpression b)+                <>  Pretty.indent 2 (prettyImportExpression_ b)                 <>  Pretty.hardline                 <>  colon <> space-                <>  prettyApplicationExpression c+                <>  prettyExpression c                 )          short = keyword "merge" <> space-            <>  prettyImportExpression a+            <>  prettyImportExpression_ a             <>  " "-            <>  prettyImportExpression b+            <>  prettyImportExpression_ b             <>  space <> colon <> space-            <>  prettyApplicationExpression c+            <>  prettyExpression c     prettyAnnotatedExpression (ToMap a (Just b)) =         Pretty.group (Pretty.flatAlt long short)       where@@ -751,16 +920,16 @@             Pretty.align                 (   keyword "toMap"                 <>  Pretty.hardline-                <>  Pretty.indent 2 (prettyImportExpression a)+                <>  Pretty.indent 2 (prettyImportExpression_ a)                 <>  Pretty.hardline                 <>  colon <> space-                <>  prettyApplicationExpression b+                <>  prettyExpression b                 )          short = keyword "toMap" <> space-            <>  prettyImportExpression a+            <>  prettyImportExpression_ a             <>  space <> colon <> space-            <>  prettyApplicationExpression b+            <>  prettyExpression b     prettyAnnotatedExpression a0@(Annot _ _) =         enclose'             ""@@ -780,7 +949,7 @@     prettyAnnotatedExpression (ListLit (Just a) b) =             list (map prettyExpression (Data.Foldable.toList b))         <>  " : "-        <>  prettyApplicationExpression a+        <>  prettyExpression a     prettyAnnotatedExpression a         | Just doc <- preserveSource a =             doc@@ -806,10 +975,10 @@         spacer = if Text.length op == 1 then " "  else "  "      prettyEquivalentExpression :: Pretty a => Expr Src a -> Doc Ann-    prettyEquivalentExpression a0@(Equivalent _ _) =+    prettyEquivalentExpression a0@(Equivalent _ _ _) =         prettyOperator (equivalent characterSet) (docs a0)       where-        docs (Equivalent a b) = prettyImportAltExpression b : docs a+        docs (Equivalent _ a b) = prettyImportAltExpression b : docs a         docs a             | Just doc <- preserveSource a =                 [ doc ]@@ -946,10 +1115,10 @@             prettyCombineExpression a      prettyCombineExpression :: Pretty a => Expr Src a -> Doc Ann-    prettyCombineExpression a0@(Combine _ _ _) =+    prettyCombineExpression a0@(Combine _ _ _ _) =         prettyOperator (combine characterSet) (docs a0)       where-        docs (Combine _ a b) = prettyPreferExpression b : docs a+        docs (Combine _ _ a b) = prettyPreferExpression b : docs a         docs a             | Just doc <- preserveSource a =                 [ doc ]@@ -969,7 +1138,7 @@     prettyPreferExpression a0@(Prefer {}) =         prettyOperator (prefer characterSet) (docs a0)       where-        docs (Prefer _ a b) = prettyCombineTypesExpression b : docs a+        docs (Prefer _ _ a b) = prettyCombineTypesExpression b : docs a         docs a             | Just doc <- preserveSource a =                 [ doc ]@@ -986,10 +1155,10 @@             prettyCombineTypesExpression a      prettyCombineTypesExpression :: Pretty a => Expr Src a -> Doc Ann-    prettyCombineTypesExpression a0@(CombineTypes _ _) =+    prettyCombineTypesExpression a0@(CombineTypes _ _ _) =         prettyOperator (combineTypes characterSet) (docs a0)       where-        docs (CombineTypes a b) = prettyTimesExpression b : docs a+        docs (CombineTypes _ a b) = prettyTimesExpression b : docs a         docs a             | Just doc <- preserveSource a =                 [ doc ]@@ -1073,30 +1242,31 @@             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+                  prettyImportExpression_ e -- just a performance optimization               | Just doc <- preserveSource e ->                   app doc args               | otherwise ->-                  app (prettyImportExpression e) args+                  app (prettyImportExpression_ e) args          app f args =             enclose'                 "" "" " " ""                 ( duplicate f-                : map (fmap (Pretty.indent 2) . duplicate . prettyImportExpression) args+                : map (fmap (Pretty.indent 2) . duplicate . prettyImportExpression_) args                 ) -    prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann-    prettyImportExpression (Embed a) =+    prettyImportExpression_ :: Pretty a => Expr Src a -> Doc Ann+    prettyImportExpression_ (Embed a) =         Pretty.pretty a-    prettyImportExpression a+    prettyImportExpression_ a         | Just doc <- preserveSource a =             doc         | Note _ b <- a =-            prettyImportExpression b+            prettyImportExpression_ b         | otherwise =             prettyCompletionExpression a @@ -1121,7 +1291,7 @@             prettySelectorExpression a      prettySelectorExpression :: Pretty a => Expr Src a -> Doc Ann-    prettySelectorExpression (Field a b) =+    prettySelectorExpression (Field a (Dhall.Syntax.fieldSelectionLabel -> b)) =         prettySelectorExpression a <> dot <> prettyAnyLabel b     prettySelectorExpression (Project a (Left b)) =         prettySelectorExpression a <> dot <> prettyLabels b@@ -1146,6 +1316,8 @@         prettyConst k     prettyPrimitiveExpression Bool =         builtin "Bool"+    prettyPrimitiveExpression Bytes =+        builtin "Bytes"     prettyPrimitiveExpression Natural =         builtin "Natural"     prettyPrimitiveExpression NaturalFold =@@ -1180,8 +1352,61 @@         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 =@@ -1202,10 +1427,6 @@         builtin "Optional"     prettyPrimitiveExpression None =         builtin "None"-    prettyPrimitiveExpression OptionalFold =-        builtin "Optional/fold"-    prettyPrimitiveExpression OptionalBuild =-        builtin "Optional/build"     prettyPrimitiveExpression (BoolLit True) =         builtin "True"     prettyPrimitiveExpression (BoolLit False) =@@ -1219,6 +1440,8 @@         prettyDouble a     prettyPrimitiveExpression (TextLit a) =         prettyChunks a+    prettyPrimitiveExpression (BytesLit a) =+        prettyBytes a     prettyPrimitiveExpression (Record a) =         prettyRecord a     prettyPrimitiveExpression (RecordLit a) =@@ -1243,17 +1466,16 @@      prettyKeyValue         :: Pretty a-        => (k -> Doc Ann)+        => (key -> Doc Ann)         -> (Expr Src a -> Doc Ann)         -> Doc Ann-        -> (k, Expr Src a)+        -> KeyValue key Src a         -> (Doc Ann, Doc Ann)-    prettyKeyValue prettyKey prettyValue separator (key, val) =+    prettyKeyValue prettyKey prettyValue separator (KeyValue key mSrc val) =         duplicate (Pretty.group (Pretty.flatAlt long short))       where         completion _T r =-                " "-            <>  prettySelectorExpression _T+                prettySelectorExpression _T             <>  doubleColon             <>  case shallowDenote r of                     RecordLit kvs ->@@ -1261,104 +1483,180 @@                     _ ->                         prettySelectorExpression r -        short = prettyKey key+        short = prettyKeys prettyKey key             <>  " "             <>  separator             <>  " "+            <>  case renderSrcMaybe mSrc of+                    Nothing  -> mempty+                    Just doc -> doc <> Pretty.hardline             <>  prettyValue val -        long =-                prettyKey key-            <>  " "+        long =  Pretty.align+                    (   prettyKeys prettyKey key+                    <>  preSeparator+                    )             <>  separator-            <>  case shallowDenote val of-                    Some val' ->-                            " " <> builtin "Some"-                        <>  case shallowDenote val' of-                                RecordCompletion _T r ->-                                    completion _T r+            <>  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'+                                        RecordLit _ ->+                                                Pretty.hardline+                                            <>  "  "+                                            <>  prettyImportExpression_ val' -                                ListLit _ xs-                                    | not (null xs) ->-                                            Pretty.hardline-                                        <>  "  "-                                        <>  prettyImportExpression val'+                                        ListLit _ xs+                                            | not (null xs) ->+                                                    Pretty.hardline+                                                <>  "  "+                                                <>  prettyImportExpression_ val' -                                _ ->    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'+                            ToMap val' Nothing ->+                                    " "+                                <>  keyword "toMap"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val' -                    RecordCompletion _T r ->-                        completion _T r+                            ShowConstructor val' ->+                                    " "+                                <>  keyword "showConstructor"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val' -                    RecordLit _ ->-                            Pretty.hardline-                        <>  "  "-                        <>  prettyValue val+                            RecordCompletion _T r ->+                                " " <> completion _T r -                    ListLit _ xs-                        | not (null xs) ->-                                Pretty.hardline-                            <>  "  "-                            <>  prettyValue val+                            RecordLit _ ->+                                    Pretty.hardline+                                <>  "  "+                                <>  prettyValue val -                    _ -> -                            Pretty.hardline-                        <>  "    "-                        <>  prettyValue val+                            ListLit _ xs+                                | not (null xs) ->+                                        Pretty.hardline+                                    <>  "  "+                                    <>  prettyValue val -    prettyRecord :: Pretty a => Map Text (Expr Src a) -> Doc Ann+                            _ ->+                                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 prettyAnyLabel prettyExpression colon)+        ( 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 (Expr Src a) -> Doc Ann-    prettyRecordLit = prettyRecordLike braces+    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 (Expr Src a) -> Doc Ann+    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 (Map.toList consolidated))+            braceStyle (map prettyRecordEntry (consolidateRecordLiteral a))       where-        consolidated = consolidateRecordLiteral a--        prettyRecordEntry (keys, value) =+        prettyRecordEntry kv@(KeyValue keys mSrc2 val) =             case keys of-                key :| []-                    | Var (V key' 0) <- Dhall.Syntax.shallowDenote value-                    , key == key' ->-                        duplicate (prettyAnyLabel key)+                (mSrc0, key, mSrc1) :| []+                    | Var (V key' 0) <- Dhall.Syntax.shallowDenote val+                    , key == key'+                    , not (containsComment mSrc2) ->+                        duplicate (prettyKeys prettyAnyLabelOrSome [(mSrc0, key, mSrc1)])                 _ ->-                    prettyKeyValue prettyAnyLabels prettyExpression equals (keys, value)+                    prettyKeyValue prettyAnyLabelOrSome prettyExpression equals kv      prettyAlternative (key, Just val) =-        prettyKeyValue prettyAnyLabel prettyExpression colon (key, val)+        prettyKeyValue prettyAnyLabelOrSome prettyExpression colon (makeKeyValue (pure key) val)     prettyAlternative (key, Nothing) =-        duplicate (prettyAnyLabel key)+        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') =@@ -1392,7 +1690,7 @@          prettyMultilineText text = mconcat docs           where-            lines_ = Text.splitOn "\n" (escapeSingleQuotedText text)+            lines_ = Text.splitOn "\n" text              -- Annotate only non-empty lines so trailing whitespace can be             -- removed on empty ones.@@ -1400,8 +1698,7 @@                 (if Text.null line then id else literal)                     (Pretty.pretty line) -            docs =-                Data.List.intersperse Pretty.hardline (map prettyLine lines_)+            docs = List.intersperse Pretty.hardline (map prettyLine lines_)          prettyChunk (c, d) =                 prettyText c@@ -1421,8 +1718,10 @@ -- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t" multilineChunks :: Chunks s a -> Chunks s a multilineChunks =-     escapeTrailingSingleQuote+     escapeSingleQuotedText+   . escapeTrailingSingleQuote    . escapeControlCharacters+   . escapeSingleQuoteBeforeInterpolation    . escapeSharedWhitespacePrefix  -- | Escape any leading whitespace shared by all lines@@ -1469,37 +1768,68 @@ -- >>> escapeControlCharacters (Chunks [] "\n\NUL\b\f\t") -- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t" escapeControlCharacters :: Chunks s a -> Chunks s a-escapeControlCharacters (Chunks as0 b0) = Chunks as1 b1+escapeControlCharacters = splitWith (splitOnPredicate predicate)   where-    as1 = foldr f (map toChunk bs) as0+    predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n' -    (bs, b1) = splitOnPredicate predicate b0+-- | 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 -    f (t0, e) chunks = map toChunk ts1 ++ (t1, e) : chunks-      where-        (ts1, t1) = splitOnPredicate predicate t0+    loop head_ tail_ =+        case tail_ of+            [] ->+                Chunks [] head_+            newHead : newTail ->+                    Chunks [ (head_, TextLit (Chunks [] "'")) ] "${"+                <>  loop newHead newTail -    predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n'+{-| You can think of this as sort of like `concatMap` for `Chunks` -    toChunk (t0, t1) = (t0, TextLit (Chunks [] t1))+    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 --- | Split `Text` on a predicate, preserving all parts of the original string.+        [ 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 "--- ([(" ","xx")]," ")+-- Chunks [(" ",TextLit (Chunks [] "xx"))] " " -- >>> splitOnPredicate (== 'x') "xx"--- ([("","xx")],"")+-- Chunks [("",TextLit (Chunks [] "xx"))] "" ----- prop> \(Fun _ p) s -> let {t = Text.pack s; (as, b) = splitOnPredicate p t} in foldMap (uncurry (<>)) as <> b == t-splitOnPredicate :: (Char -> Bool) -> Text -> ([(Text, Text)], Text)-splitOnPredicate p t = case Text.break p t of-    (a, "") -> ([], a)-    (a, b)  -> case Text.span p b of-        (c, d) -> case splitOnPredicate p d of-            (e, f) -> ((a, c) : e, f)+-- 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@@ -1517,35 +1847,49 @@ 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 }`+   `{ x = { y = { z = 1 } } }` to `{ x.y.z = 1 }` -} consolidateRecordLiteral-    :: Map Text (Expr s a) -> Map (NonEmpty Text) (Expr s a)-consolidateRecordLiteral = Map.fromList . fmap adapt . Map.toList+    :: Map Text (RecordField Src a) -> [KeyValue Text Src a]+consolidateRecordLiteral = concatMap adapt . Map.toList   where-    adapt :: (Text, Expr s a) -> (NonEmpty Text, Expr s a)-    adapt (key, expression) =-        case shallowDenote expression of-            RecordLit m ->-                case fmap adapt (Map.toList m) of-                    [ (keys, expression') ] ->-                        (NonEmpty.cons key keys, expression')-                    _ ->-                        (pure key, RecordLit m)-            _ ->-                (pure key, expression)+    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' ] --- | Escape a `Text` literal using Dhall's escaping rules for single-quoted---   @Text@-escapeSingleQuotedText :: Text -> Text-escapeSingleQuotedText inputText = outputText-  where-    outputText = substitute "${" "''${" (substitute "''" "'''" inputText)+        | 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 -    substitute before after = Text.intercalate after . Text.splitOn before+-- | 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 `Text` literal using Dhall's escaping rules+{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules      Note that the result does not include surrounding quotes -}@@ -1604,6 +1948,43 @@ 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,12 +1,29 @@ module Dhall.Pretty.Internal where -import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty, Doc)+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.Syntax+import                Dhall.Syntax.Const+import {-# SOURCE #-} Dhall.Syntax.Expr+import                Dhall.Syntax.Var  data Ann +data CharacterSet = ASCII | Unicode++instance Eq CharacterSet+instance Ord CharacterSet+instance Show CharacterSet+instance Data CharacterSet+instance Lift CharacterSet+instance NFData CharacterSet+instance Semigroup CharacterSet+instance Monoid CharacterSet+ prettyVar :: Var -> Doc Ann  prettyConst :: Const -> Doc Ann@@ -14,3 +31,5 @@ prettyExpr :: Pretty a => Expr s a -> Doc Ann  prettyEnvironmentVariable :: Text -> Doc ann++prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann
src/Dhall/Repl.hs view
@@ -1,64 +1,80 @@ -- | This module contains the implementation of the @dhall repl@ subcommand -{-# language CPP               #-}-{-# language FlexibleContexts  #-}-{-# language NamedFieldPuns    #-}-{-# language OverloadedStrings #-}-{-# language RecordWildCards   #-}+{-# 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_ )-import Control.Monad.Fail ( MonadFail )-import Control.Monad.IO.Class ( MonadIO, liftIO )-import Control.Monad.State.Class ( MonadState, get, modify )-import Control.Monad.State.Strict ( evalStateT )--- For the MonadFail instance for StateT.-import Control.Monad.Trans.Instances ()-import Data.List ( isPrefixOf, nub )-import Data.Maybe ( mapMaybe )-import Data.Semigroup ((<>))-import Data.Text ( Text )-import Data.Void (Void)-import Dhall.Context (Context)-import Dhall.Import (hashExpressionToCode)-import Dhall.Parser (Parser(..))-import Dhall.Src (Src)-import Dhall.Pretty (CharacterSet(..))-import System.Console.Haskeline (Interrupt(..))-import System.Console.Haskeline.Completion ( Completion, simpleCompletion )-import System.Directory ( getDirectoryContents )-import System.Environment ( getEnvironment )+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 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 Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty ( renderIO )+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 ( Var(V), Expr, normalize )-import qualified Dhall.Parser.Token                      as Parser.Token+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.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.TypeCheck                         as Dhall-import qualified Dhall.Version                           as Meta+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.Console.Haskeline.Completion as Haskeline+import qualified System.Console.Repline              as Repline import qualified System.IO-import qualified Text.Megaparsec                         as Megaparsec+import qualified Text.Megaparsec                     as Megaparsec  #if MIN_VERSION_haskeline(0,8,0) import qualified Control.Monad.Catch@@ -76,15 +92,21 @@     io =       evalStateT         ( Repline.evalRepl-            ( pure $ turnstile ++ " " )+            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 -> "⊢"@@ -159,12 +181,10 @@   -typeOf :: ( MonadFail m, MonadIO m, MonadState Env m ) => [String] -> m ()-typeOf [] = Fail.fail ":type requires an argument to check the type of"--typeOf srcs = do+typeOf :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+typeOf src = do   loaded <--    parseAndLoad ( unwords srcs )+    parseAndLoad src    exprType <-     typeCheck loaded@@ -207,62 +227,75 @@     Left  e -> liftIO ( wrap (throwIO e) )     Right a -> return a --- Separate the equal sign to be its own word in order to simplify parsing--- This is intended to be used with the options that require assignment-separateEqual :: [String] -> [String]-separateEqual [] =-    []-separateEqual (str₀ : ('=' : str₁) : strs) =-    str₀ : "=" : str₁ : strs-separateEqual (str : strs)-    | (str₀, '=' : str₁) <- break (== '=') str =-        str₀ : "=" : str₁ : strs-    | otherwise =-        str : strs+-- 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 (k : "=" : srcs) = do-  varName <- case Megaparsec.parse (unParser Parser.Token.label) "(input)" (Text.pack k) of-      Left   _      -> Fail.fail "Invalid variable name"-      Right varName -> return varName+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_)+              ) -  loaded <- parseAndLoad ( unwords srcs )+  let input = "let " <> Text.pack string -  t <- typeCheck loaded+  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 -  expr <- normalize loaded+  (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-                varName-                Binding { bindingType = t, bindingExpr = expr }+                variable+                Binding{ bindingType, bindingExpr }                 ( envBindings e )           }     ) -  output ( Expr.Annot ( Expr.Var ( Dhall.V varName 0 ) ) t )--addBinding _ = Fail.fail ":let should be of the form `:let x = y`"+  output (Expr.Annot (Expr.Var (Dhall.V variable 0)) bindingType) -clearBindings :: (MonadFail m, MonadState Env m) => [String] -> m ()-clearBindings [] = modify adapt+clearBindings :: (MonadFail m, MonadState Env m) => String -> m ()+clearBindings _ = modify adapt   where     adapt (Env {..}) = Env { envBindings = Dhall.Context.empty, ..} -clearBindings _ = Fail.fail ":clear takes no arguments"--hashBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => [String] -> m ()-hashBinding [] = Fail.fail ":hash should be of the form `:hash expr"-hashBinding tokens = do-  loadedExpression <- parseAndLoad (unwords tokens)+hashBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+hashBinding src = do+  loadedExpression <- parseAndLoad src    _ <- typeCheck loadedExpression    normalizedExpression <- normalize loadedExpression -  writeOutputHandle $ hashExpressionToCode normalizedExpression+  writeOutputHandle+    (hashExpressionToCode (Dhall.Core.alphaNormalize normalizedExpression))  saveFilePrefix :: FilePath saveFilePrefix = ".dhall-repl"@@ -299,25 +332,33 @@    pure $ saveFilePrefix <> "-" <> show nextIndex -loadBinding :: [String] -> Repl ()-loadBinding [] = do+loadBinding :: String -> Repl ()+loadBinding "" = do   mFile <- currentSaveFile    case mFile of-    Just file -> loadBinding [file]+    Just file -> loadBinding file     Nothing   ->       Fail.fail $ ":load couldn't find any `" <> saveFilePrefix <> "-*` files" -loadBinding [file] = do+loadBinding file = do   -- Read commands from the save file-  replLines <- map words . lines <$> liftIO (readFile file)+  -- Some commands can span multiple lines, only the first line will start with+  -- the optionsPrefix+  loadedLines <- lines <$> liftIO (readFile file) -  let runCommand ((c:cmd):opts)+  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-        , Just action <- lookup cmd options-        = action opts+        = 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 one command per line"+        ":load expects `" <> file <> "` to contain a command"    -- Keep current handle in scope   Env { outputHandle } <- get@@ -326,24 +367,22 @@   modify (\e -> e { outputHandle = Nothing })    -- Run all the commands-  forM_ replLines runCommand+  forM_ commands (runCommand . unlines)    -- Restore the previous handle   modify (\e -> e { outputHandle = outputHandle })    writeOutputHandle $ "Loaded `" <> Text.pack file <> "`\n" -loadBinding _ = Fail.fail ":load should be of the form `:load` or `:load file`"--saveBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => [String] -> m ()+saveBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => Either String (String, String) -> m () -- Save all the bindings into a context save file-saveBinding [] = do+saveBinding (Left "") = do   file <- nextSaveFile -  saveBinding [file]+  saveBinding (Left file)  -- Save all the bindings into `file`-saveBinding [file] = do+saveBinding (Left file) = do   env <- get    let bindings@@ -368,8 +407,8 @@   writeOutputHandle $ "Context saved to `" <> Text.pack file <> "`\n"  -- Save a single expression to `file`-saveBinding (file : "=" : tokens) = do-  loadedExpression <- parseAndLoad (unwords tokens)+saveBinding (Right (file, src)) = do+  loadedExpression <- parseAndLoad src    _ <- typeCheck loadedExpression @@ -386,28 +425,29 @@    writeOutputHandle $ "Expression saved to `" <> Text.pack file <> "`\n" -saveBinding _ = Fail.fail ":save should be of the form `:save`, `:save file`, or `:save file = expr`"--setOption :: ( MonadIO m, MonadState Env m ) => [String] -> m ()-setOption [ "--explain" ] = do+setOption :: ( MonadIO m, MonadState Env m ) => String -> m ()+setOption "--explain" =   modify (\e -> e { explain = True })-setOption _ = do+setOption _ =   writeOutputHandle ":set should be of the form `:set <command line option>`" -unsetOption :: ( MonadIO m, MonadState Env m ) => [String] -> m ()-unsetOption [ "--explain" ] = do+unsetOption :: ( MonadIO m, MonadState Env m ) => String -> m ()+unsetOption "--explain" =   modify (\e -> e { explain = False })-unsetOption _ = do+unsetOption _ =   writeOutputHandle ":unset should be of the form `:unset <command line option>`" -cmdQuit :: ( MonadIO m, MonadState Env m ) => [String] -> m ()+quitMessage :: String+quitMessage = "Goodbye."++cmdQuit :: ( MonadIO m, MonadState Env m ) => String -> m () cmdQuit _ = do-  liftIO (putStrLn "Goodbye.")+  liftIO (putStrLn quitMessage)   liftIO (throwIO Interrupt)  help   :: ( MonadFail m, MonadIO m, MonadState Env m )-  => HelpOptions m -> [String] -> 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@@ -420,6 +460,9 @@ optionsPrefix :: Char optionsPrefix = ':' +trim :: String -> String+trim = dropWhile isSpace . dropWhileEnd isSpace+ data HelpOption m = HelpOption   { helpOptionName :: String   , helpOptionSyntax :: String@@ -437,6 +480,11 @@       "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"@@ -450,7 +498,7 @@       "let"       "IDENTIFIER = EXPRESSION"       "Assign an expression to a variable"-      (dontCrash . addBinding . separateEqual)+      (dontCrash . addBinding)   , HelpOption       "clear"       ""@@ -460,22 +508,22 @@       "load"       "[FILENAME]"       "Load bound variables from a file"-      (dontCrash . loadBinding)+      (dontCrash . loadBinding . trim)   , HelpOption       "save"       "[FILENAME | FILENAME = EXPRESSION]"       "Save bound variables or a given expression to a file"-      (dontCrash . saveBinding . separateEqual)+      (dontCrash . saveBinding . parseAssignment)   , HelpOption       "set"       "OPTION"       "Set an option. Currently supported: --explain"-      (dontCrash . setOption)+      (dontCrash . setOption . trim)   , HelpOption       "unset"       "OPTION"       "Unset an option"-      (dontCrash . unsetOption)+      (dontCrash . unsetOption . trim)   , HelpOption       "quit"       ""@@ -567,7 +615,7 @@                               fmap (("." <> f) <>) (algebraicComplete fs e)        in  case expr of-            Dhall.Core.RecordLit    m -> withMap (fmap Just m)+            Dhall.Core.RecordLit    m -> withMap (fmap (Just . Dhall.Core.recordFieldValue) m)             Dhall.Core.Union        m -> withMap m             _                         -> [] @@ -578,6 +626,10 @@       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 =
+ 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
@@ -1,7 +1,7 @@+{-# LANGUAGE DeriveAnyClass     #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}  -- | This module only exports ways of constructing a Set, -- retrieving List, Set, and Seq representations of the same data,@@ -25,18 +25,18 @@     , size     ) where -import Prelude hiding (null)-import Control.DeepSeq (NFData)-import Data.List (foldl')-import Data.Sequence (Seq, (|>))-import Data.Data (Data)-import GHC.Generics (Generic)-import Instances.TH.Lift ()+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.Set-import qualified Data.Sequence 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@@ -75,33 +75,35 @@ toSeq :: Set a -> Seq a toSeq (Set _ xs) = xs --- | Convert a `Set` to a list, preserving the original order of the elements+{-| 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 `Set` to a list of ascending elements+-- | 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 `Set`, remembering the element order+-- | 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 `Set`+-- | 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 `Set`+-- | 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 `Set`+-- | The empty `Dhall.Set.Set` empty :: Set a empty = Set Data.Set.empty Data.Sequence.empty 
src/Dhall/Src.hs view
@@ -12,15 +12,14 @@       Src(..)     ) where -import Control.DeepSeq (NFData)-import Data.Data (Data)-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc  (Pretty (..))-import GHC.Generics (Generic)-import Instances.TH.Lift ()-import Language.Haskell.TH.Syntax (Lift(..))-import Text.Megaparsec (SourcePos (SourcePos), mkPos, unPos)+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 
src/Dhall/Substitution.hs view
@@ -4,9 +4,9 @@  module Dhall.Substitution where -import Data.Text (Text)+import Data.Text       (Text) import Dhall.Normalize (subst)-import Dhall.Syntax (Expr, Var(..))+import Dhall.Syntax    (Expr, Var (..))  import qualified Dhall.Map 
src/Dhall/Syntax.hs view
@@ -1,1141 +1,31 @@-{-# LANGUAGE BangPatterns       #-}-{-# LANGUAGE CPP                #-}-{-# LANGUAGE DeriveAnyClass     #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE DeriveLift         #-}-{-# LANGUAGE DeriveTraversable  #-}-{-# LANGUAGE LambdaCase         #-}-{-# LANGUAGE OverloadedLists    #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RankNTypes         #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE UnicodeSyntax      #-}--{-| This module contains the core syntax types and optics for them.--'reservedIdentifiers', 'denote' and friends are included because they are-involved in a dependency circle with "Dhall.Pretty.Internal".--}--module Dhall.Syntax (-    -- * 'Expr'-      Const(..)-    , Var(..)-    , Binding(..)-    , makeBinding-    , Chunks(..)-    , DhallDouble(..)-    , PreferAnnotation(..)-    , Expr(..)--    -- ** 'Let'-blocks-    , MultiLet(..)-    , multiLet-    , wrapInLets--    -- ** Optics-    , subExpressions-    , unsafeSubExpressions-    , chunkExprs-    , bindingExprs--    -- ** Handling 'Note's-    , denote-    , renote-    , shallowDenote--    -- * 'Import'-    , Directory(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , URL(..)-    , Scheme(..)-    , pathCharacter--    -- * Reserved identifiers-    , reservedIdentifiers--    -- * `Text` manipulation-    , toDoubleQuoted-    , longestSharedWhitespacePrefix-    , linesLiteral-    , unlinesLiteral--    -- * Desugaring-    , desugarWith--    -- * Utilities-    , internalError-    ) where--import Control.DeepSeq (NFData)-import Data.Bifunctor (Bifunctor(..))-import Data.Bits (xor)-import Data.Data (Data)-import Data.Foldable-import Data.HashSet (HashSet)-import Data.List.NonEmpty (NonEmpty(..))-import Data.String (IsString(..))-import Data.Semigroup (Semigroup(..))-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Traversable-import Data.Void (Void)-import Dhall.Map (Map)-import Dhall.Set (Set)-import Dhall.Src (Src(..))-import {-# SOURCE #-} Dhall.Pretty.Internal-import GHC.Generics (Generic)-import Instances.TH.Lift ()-import Language.Haskell.TH.Syntax (Lift)-import Numeric.Natural (Natural)-import Prelude hiding (succ)-import Unsafe.Coerce (unsafeCoerce)--import qualified Control.Monad-import qualified Data.HashSet-import qualified Data.List.NonEmpty         as NonEmpty-import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc  as Pretty-import qualified Dhall.Crypto-import qualified Dhall.Optics               as Optics-import qualified Lens.Family                as Lens-import qualified Network.URI                as URI--{-| 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 (Show, Eq, Ord, Data, Bounded, Enum, Generic, Lift, NFData)--instance Pretty Const where-    pretty = Pretty.unAnnotate . prettyConst--{-| 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 !Int-    deriving (Data, Generic, Eq, Ord, Show, Lift, NFData)--instance IsString Var where-    fromString str = V (fromString str) 0--instance Pretty Var where-    pretty = Pretty.unAnnotate . prettyVar--{- | 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 (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)--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--{-| 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---- | 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 (Show, Data, Lift, NFData, Generic)---- | 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---- | 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'---- | The body of an interpolated @Text@ literal-data Chunks s a = Chunks [(Text, Expr s a)] Text-    deriving (Functor, Foldable, Generic, Traversable, Show, Eq, Ord, Data, Lift, NFData)--instance Data.Semigroup.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--#if !(MIN_VERSION_base(4,11,0))-    mappend = (<>)-#endif--instance IsString (Chunks s a) where-    fromString str = Chunks [] (fromString str)---- | Used to record the origin of a @//@ operator (i.e. from source code or a--- product of desugaring)-data PreferAnnotation s a-    = PreferFromSource-    | PreferFromWith (Expr s a)-      -- ^ Stores the original @with@ expression-    | PreferFromCompletion-    deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)--instance Bifunctor PreferAnnotation where-    first _  PreferFromSource      = PreferFromSource-    first f (PreferFromWith e    ) = PreferFromWith (first f e)-    first _  PreferFromCompletion  = PreferFromCompletion--    second = fmap--{-| Syntax tree for expressions--    The @s@ type parameter is used to track the presence or absence of `Src`-    spans:--    * If @s = `Src`@ then the code may contains `Src` spans (either in a `Noted`-      constructor or inline within another constructor, like `Let`)-    * If @s = `Void`@ then the code has no `Src` spans--    The @a@ type parameter is used to track the presence or absence of imports--    * If @a = `Import`@ then the code may contain unresolved `Import`s-    * If @a = `Void`@ then the code has no `Import`s--}-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 (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 '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)-    -- | > 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)-    -- | > TextShow                                 ~  Text/show-    | TextShow-    -- | > 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-    -- | > OptionalFold                             ~  Optional/fold-    | OptionalFold-    -- | > OptionalBuild                            ~  Optional/build-    | OptionalBuild-    -- | > Record       [(k1, t1), (k2, t2)]        ~  { k1 : t1, k2 : t1 }-    | Record    (Map Text (Expr s a))-    -- | > RecordLit    [(k1, v1), (k2, v2)]        ~  { k1 = v1, k2 = v2 }-    | RecordLit (Map Text (Expr 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, Combine (Just k) x y) ]  ~ { k = x, k = y }-    | Combine (Maybe Text) (Expr s a) (Expr s a)-    -- | > CombineTypes x y                         ~  x ⩓ y-    | CombineTypes (Expr s a) (Expr s a)-    -- | > Prefer False x y                         ~  x ⫽ y-    ---    -- The first field is a `True` when the `Prefer` operator is introduced as a-    -- result of desugaring a @with@ expression-    | Prefer (PreferAnnotation s a) (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))-    -- | > Field e x                                ~  e.x-    | Field (Expr s a) Text-    -- | > Project e (Left xs)                      ~  e.{ xs }-    --   > Project e (Right t)                      ~  e.(t)-    | Project (Expr s a) (Either (Set Text) (Expr s a))-    -- | > Assert e                                 ~  assert : e-    | Assert (Expr s a)-    -- | > Equivalent x y                           ~  x ≡ y-    | Equivalent (Expr s a) (Expr s a)-    -- | > With x y                                 ~  x with y-    | With (Expr s a) (NonEmpty Text) (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 (Foldable, Generic, Traversable, Show, Data, Lift, NFData)--- NB: If you add a constructor to Expr, please also update the Arbitrary--- instance in Dhall.Test.QuickCheck.---- | 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)---- | Note that this 'Ord' instance inherits `DhallDouble`'s defects.-deriving instance (Ord s, Ord a) => Ord (Expr s a)---- 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 expression = Lens.over unsafeSubExpressions (fmap f) expression-  {-# INLINABLE fmap #-}--instance Applicative (Expr s) where-    pure = Embed--    (<*>) = Control.Monad.ap--instance Monad (Expr s) where-    return = pure--    Embed a    >>= k = k a-    Let a b    >>= k = Let (adapt0 a) (b >>= k)-      where-        adapt0 (Binding src0 c src1 d src2 e) =-            Binding src0 c src1 (fmap adapt1 d) src2 (e >>= k)--        adapt1 (src3, f) = (src3, f >>= k)-    Note a b   >>= k = Note a (b >>= k)-    expression >>= k = Lens.over unsafeSubExpressions (>>= k) expression--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  expression  = Lens.over unsafeSubExpressions (first k) expression--    second = fmap--instance IsString (Expr s a) where-    fromString str = Var (fromString str)---- | Generates a syntactically valid Dhall program-instance Pretty a => Pretty (Expr s a) where-    pretty = Pretty.unAnnotate . prettyExpr--{--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.--}--{-| 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)---- | 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 _ (Embed a) = pure (Embed a)-subExpressions f (Note a b) = Note a <$> f b-subExpressions f (Let a b) = Let <$> bindingExprs f a <*> f b-subExpressions f expression = unsafeSubExpressions f expression-{-# INLINABLE subExpressions #-}--{-| 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 (Lam a b c) = Lam a <$> f b <*> f c-unsafeSubExpressions f (Pi a b c) = Pi 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 _ 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 _ TextShow = pure TextShow-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 _ OptionalFold = pure OptionalFold-unsafeSubExpressions _ OptionalBuild = pure OptionalBuild-unsafeSubExpressions f (Record a) = Record <$> traverse f a-unsafeSubExpressions f ( RecordLit a ) = RecordLit <$> traverse f a-unsafeSubExpressions f (Union a) = Union <$> traverse (traverse f) a-unsafeSubExpressions f (Combine a b c) = Combine a <$> f b <*> f c-unsafeSubExpressions f (CombineTypes a b) = CombineTypes <$> f a <*> f b-unsafeSubExpressions f (Prefer a b c) = Prefer <$> a' <*> f b <*> f c-  where-    a' = case a of-        PreferFromSource     -> pure PreferFromSource-        PreferFromWith d     -> PreferFromWith <$> f d-        PreferFromCompletion -> pure PreferFromCompletion-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 (Field a b) = Field <$> f a <*> pure b-unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b-unsafeSubExpressions f (Assert a) = Assert <$> f a-unsafeSubExpressions f (Equivalent a b) = Equivalent <$> 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"-{-# INLINABLE unsafeSubExpressions #-}--unhandledConstructor :: Text -> a-unhandledConstructor constructor =-    internalError-        (   "Dhall.Syntax.unsafeSubExpressions: Unhandled "-        <>  constructor-        <>  " construtor"-        )--{-| 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 #-}---- | 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 #-}--{-| 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 (Eq, Generic, Ord, Show, NFData)--instance Semigroup Directory where-    Directory components₀ <> Directory components₁ =-        Directory (components₁ <> components₀)--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 <> "\""--{-| A `File` is a `directory` followed by one additional path component-    representing the `file` name--}-data File = File-    { directory :: Directory-    , file      :: Text-    } deriving (Eq, Generic, Ord, Show, NFData)--instance Pretty File where-    pretty (File {..}) =-            Pretty.pretty directory-        <>  prettyPathComponent file--instance Semigroup File where-    File directory₀ _ <> File directory₁ file =-        File (directory₀ <> directory₁) file---- | 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 (Eq, Generic, Ord, Show, NFData)--instance Pretty FilePrefix where-    pretty Absolute = ""-    pretty Here     = "."-    pretty Parent   = ".."-    pretty Home     = "~"---- | The URI scheme-data Scheme = HTTP | HTTPS deriving (Eq, Generic, Ord, Show, NFData)---- | 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 (Eq, Generic, Ord, Show, NFData)--instance Pretty URL where-    pretty (URL {..}) =-            schemeDoc-        <>  "://"-        <>  Pretty.pretty authority-        <>  pathDoc-        <>  queryDoc-        <>  foldMap prettyHeaders headers-      where-        prettyHeaders h = " using " <> 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---- | 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 (Eq, Generic, Ord, Show, NFData)--parent :: File-parent = File { directory = Directory { components = [ ".." ] }, file = "" }--instance Semigroup ImportType where-    Local prefix file₀ <> Local Here file₁ = Local prefix (file₀ <> file₁)--    Remote (URL { path = path₀, ..}) <> Local Here path₁ =-        Remote (URL { path = path₀ <> path₁, ..})--    Local prefix file₀ <> Local Parent file₁ =-        Local prefix (file₀ <> parent <> file₁)--    Remote (URL { path = path₀, .. }) <> Local Parent path₁ =-        Remote (URL { path = path₀ <> parent <> path₁, .. })--    import₀ <> Remote (URL { headers = headers₀, .. }) =-        Remote (URL { headers = headers₁, .. })-      where-        importHashed₀ = Import (ImportHashed Nothing import₀) Code--        headers₁ = fmap (fmap (importHashed₀ <>)) headers₀--    _ <> import₁ =-        import₁--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"---- | How to interpret the import's contents (i.e. as Dhall code or raw text)-data ImportMode = Code | RawText | Location-  deriving (Eq, Generic, Ord, Show, NFData)---- | A `ImportType` extended with an optional hash for semantic integrity checks-data ImportHashed = ImportHashed-    { hash       :: Maybe Dhall.Crypto.SHA256Digest-    , importType :: ImportType-    } deriving (Eq, Generic, Ord, Show, NFData)--instance Semigroup ImportHashed where-    ImportHashed _ importType₀ <> ImportHashed hash importType₁ =-        ImportHashed hash (importType₀ <> importType₁)--instance Pretty ImportHashed where-    pretty (ImportHashed  Nothing p) =-      Pretty.pretty p-    pretty (ImportHashed (Just h) p) =-      Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)---- | Reference to an external resource-data Import = Import-    { importHashed :: ImportHashed-    , importMode   :: ImportMode-    } deriving (Eq, Generic, Ord, Show, NFData)--instance Semigroup Import where-    Import importHashed₀ _ <> Import importHashed₁ code =-        Import (importHashed₀ <> importHashed₁) code--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     -> ""--{-| 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'---- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)-denote :: Expr s a -> Expr t a-denote (Note _ b     ) = denote b-denote (Let a b      ) = Let (adapt0 a) (denote b)-  where-    adapt0 (Binding _ c _ d _ e) =-        Binding Nothing c Nothing (fmap adapt1 d) Nothing (denote e)--    adapt1 (_, f) = (Nothing, denote f)-denote (Embed a      ) = Embed a-denote (Combine _ b c) = Combine Nothing (denote b) (denote c)-denote  expression     = Lens.over unsafeSubExpressions denote expression---- | 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 identifiers for the Dhall language-reservedIdentifiers :: HashSet Text-reservedIdentifiers =-    Data.HashSet.fromList-        [ -- Keywords according to the `keyword` rule in the grammar-          "if"-        , "then"-        , "else"-        , "let"-        , "in"-        , "using"-        , "missing"-        , "as"-        , "Infinity"-        , "NaN"-        , "merge"-        , "Some"-        , "toMap"-        , "assert"-        , "forall"-        , "with"--          -- 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"-        , "Optional/fold"-        , "Optional/build"-        , "Text/show"-        , "Bool"-        , "True"-        , "False"-        , "Optional"-        , "None"-        , "Natural"-        , "Integer"-        , "Double"-        , "Text"-        , "List"-        , "Type"-        , "Kind"-        , "Sort"-        ]---- | 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---- | Desugar all @with@ expressions-desugarWith :: Expr s a -> Expr s a-desugarWith = Optics.rewriteOf subExpressions rewrite-  where-    rewrite e@(With record (key :| []) value) =-        Just (Prefer (PreferFromWith e) record (RecordLit [ (key, value) ]))-    rewrite e@(With record (key0 :| key1 : keys) value) =-        Just-            (Prefer (PreferFromWith e) record-                (RecordLit-                    [ (key0, With (Field record key0) (key1 :| keys) value) ]-                )-            )-    rewrite _ = Nothing--_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 <> "                                                       "-    , "```                                                                             "-    ] )+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.hs-boot
@@ -1,7 +0,0 @@-module Dhall.Syntax where--data Var--data Const--data Expr s a
+ 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
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP               #-} {-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards     #-} {-# LANGUAGE RecordWildCards   #-}@@ -7,52 +8,63 @@  -- | Template Haskell utilities module Dhall.TH-    ( -- * Template Haskell+    ( -- * Embedding Dhall in Haskell       staticDhallExpression+    , dhall+      -- * Generating Haskell from Dhall expressions     , makeHaskellTypeFromUnion     , makeHaskellTypes+    , makeHaskellTypesWith     , HaskellType(..)+    , GenerateOptions(..)+    , defaultGenerateOptions     ) where -import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)-import Dhall.Syntax (Expr(..))-import Dhall (FromDhall, ToDhall)-import GHC.Generics (Generic)-import Language.Haskell.TH.Quote (dataToExpQ) -- 7.10 compatibility.+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-    ( Con(..)-    , Dec(..)-    , Exp(..)+    ( Bang (..)+    , Body (..)+    , Con (..)+    , Dec (..)+    , Exp (..)+    , Match (..)+    , Pat (..)     , Q-    , Type(..)-    , Bang(..)-    , SourceStrictness(..)-    , SourceUnpackedness(..)-#if MIN_VERSION_template_haskell(2,12,0)-    , DerivClause(..)-    , DerivStrategy(..)-#else-    , Pred-#endif+    , SourceStrictness (..)+    , SourceUnpackedness (..)+    , Type (..)     ) -import qualified Data.List                               as List-import qualified Data.Text                               as Text-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Data.Typeable                           as Typeable+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.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-import qualified Language.Haskell.TH.Syntax              as Syntax + {-| This fully resolves, type checks, and normalizes the expression, so the     resulting AST is self-contained. @@ -64,8 +76,8 @@      > < This : Natural | Other : ../Other/Type.dhall > -    ... rather than duplicating the AST manually in a Haskell `Type`, you can-    do:+    ... rather than duplicating the AST manually in a Haskell `Dhall.Type`, you+    can do:      > Dhall.Type     > (\case@@ -79,23 +91,61 @@ -} staticDhallExpression :: Text -> Q Exp staticDhallExpression text = do-    Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)+    TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8) -    expression <- Syntax.runIO (Dhall.inputExpr text)+    (expression, status) <- TH.runIO $ do+        parsed <- Dhall.parseWithSettings Dhall.defaultInputSettings text -    dataToExpQ (\a -> liftText <$> Typeable.cast a) expression+        (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)) . Syntax.lift . Text.unpack+    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)-    => [HaskellType (Expr s a)]+    => [Var]+    -> [HaskellType (Expr s a)]     -- ^ All Dhall-derived data declarations     --     -- Used to replace complex types with references to one of these@@ -103,24 +153,65 @@     -> Expr s a     -- ^ Dhall expression to convert to a simple Haskell type     -> Q Type-toNestedHaskellType haskellTypes = loop+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 -> do+        Bool ->             return (ConT ''Bool) -        Double -> do+        Double ->             return (ConT ''Double) -        Integer -> do+        Integer ->             return (ConT ''Integer) -        Natural -> do+        Natural ->             return (ConT ''Numeric.Natural.Natural) -        Text -> do+        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 @@ -131,146 +222,195 @@              return (AppT (ConT ''Maybe) haskellElementType) -        _   | Just haskellType <- List.find predicate haskellTypes -> do-                let name = Syntax.mkName (Text.unpack (typeName haskellType))+        App dhallAppType dhallElementType -> do+            haskellAppType <- loop dhallAppType+            haskellElementType <- loop dhallElementType -                return (ConT name) -            | otherwise -> do-            let document =-                    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"-                    , "• ❰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"-                    , "                                                                                \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."-                    ]+            return (AppT haskellAppType haskellElementType) -            let message = Pretty.renderString (Dhall.Pretty.layout document)+        Var v+            | Just (V param index) <- List.find (v ==) typeParams -> do+                let name = TH.mkName $ (Text.unpack param) ++ (show index) -            fail message-          where-            predicate haskellType =-                Core.judgmentallyEqual (code haskellType) dhallType+                return (VarT name) -#if MIN_VERSION_template_haskell(2,12,0)-derivingClauses :: [DerivClause]-derivingClauses =-    [ DerivClause (Just StockStrategy) [ ConT ''Generic ]-    , DerivClause (Just AnyclassStrategy) [ ConT ''FromDhall, ConT ''ToDhall ]-    ]-#else-derivingClauses :: [Pred]-derivingClauses = [ ConT ''Generic, ConT ''FromDhall, ConT ''ToDhall ]-#endif+            | 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)-    => [HaskellType (Expr s a)]+    => GenerateOptions+    -> [HaskellType (Expr s a)]     -> HaskellType (Expr s a)-    -> Q Dec-toDeclaration haskellTypes MultipleConstructors{..} = do-    case code of-        Union kts -> do-            let name = Syntax.mkName (Text.unpack typeName)+    -> 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_ [] -            constructors <- traverse (toConstructor haskellTypes) (Dhall.Map.toList kts )+        getTypeParams_ acc (Lam _ (FunctionBinding _ v _ _ _) rest) = getTypeParams_ (v:acc) rest+        getTypeParams_ acc rest = (acc, rest) -            return (DataD [] name [] Nothing constructors derivingClauses)+        derivingClauses = [ derivingGenericClause | generateFromDhallInstance || generateToDhallInstance ] -        _ -> do-            let document =-                    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 code <> "\n"-                    , "                                                                                \n"-                    , "... which is not a union type."-                    ]+        interpretOptions = generateToInterpretOptions generateOptions typ -            let message = Pretty.renderString (Dhall.Pretty.layout document)+#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 -            fail message-toDeclaration haskellTypes SingleConstructor{..} = do-    let name = Syntax.mkName (Text.unpack typeName)+        toDataD typeName typeParams constructors = do+            let name = TH.mkName (Text.unpack typeName) -    constructor <- toConstructor haskellTypes (constructorName, Just code)+            let params = fmap toTypeVar typeParams -    return (DataD [] name [] Nothing [constructor] derivingClauses)+            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)-    => [HaskellType (Expr s a)]+    => [Var]+    -> GenerateOptions+    -> [HaskellType (Expr s a)]+    -> Text+    -- ^ typeName     -> (Text, Maybe (Expr s a))     -- ^ @(constructorName, fieldType)@     -> Q Con-toConstructor haskellTypes (constructorName, maybeAlternativeType) = do-    let name = Syntax.mkName (Text.unpack constructorName)+toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do+    let name = TH.mkName (Text.unpack $ constructorModifier constructorName) -    let bang = Bang NoSourceUnpackedness NoSourceStrictness+    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 haskellTypes dhallFieldType+                    haskellFieldType <- toNestedHaskellType typeParams haskellTypes dhallFieldType -                    return (Syntax.mkName (Text.unpack key), bang, haskellFieldType)+                    return (TH.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType) -            varBangTypes <- traverse process (Dhall.Map.toList kts)+            varBangTypes <- traverse process (Dhall.Map.toList $ Core.recordFieldValue <$> kts)              return (RecC name varBangTypes)          Just dhallAlternativeType -> do-            haskellAlternativeType <- toNestedHaskellType haskellTypes dhallAlternativeType+            haskellAlternativeType <- toNestedHaskellType typeParams haskellTypes dhallAlternativeType              return (NormalC name [ (bang, haskellAlternativeType) ]) -        Nothing -> do+        Nothing ->             return (NormalC name [])  -- | Generate a Haskell datatype declaration from a Dhall union type where@@ -297,17 +437,18 @@ makeHaskellTypeFromUnion typeName code =     makeHaskellTypes [ MultipleConstructors{..} ] --- | Used by `makeHaskellTypes` to specify how to generate Haskell types+-- | 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+    -- 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+    -- | 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.@@ -321,8 +462,88 @@         }     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+-- 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@@ -374,7 +595,7 @@ -- -- 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+-- as `Eq`\/`Ord`\/`Show`), you can use the @StandaloneDeriving@ language -- extension, like this: -- -- > {-# LANGUAGE DeriveAnyClass     #-}@@ -397,9 +618,18 @@ -- > deriving instance Ord  Employee -- > deriving instance Show Employee makeHaskellTypes :: [HaskellType Text] -> Q [Dec]-makeHaskellTypes haskellTypes = do-    Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)+makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions -    haskellTypes' <- traverse (traverse (Syntax.runIO . Dhall.inputExpr)) haskellTypes+-- | 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) -    traverse (toDeclaration haskellTypes') haskellTypes'+    haskellTypes' <- traverse (traverse (TH.runIO . Dhall.inputExpr)) haskellTypes++    concat <$> traverse (toDeclaration generateOptions haskellTypes') haskellTypes'
src/Dhall/Tags.hs view
@@ -1,5 +1,5 @@+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-}  -- | This module contains the implementation of the @dhall tags@ command @@ -7,27 +7,26 @@     ( generate     ) where -import Control.Exception (handle, SomeException(..))-import Data.List (isSuffixOf, foldl')-import Data.Maybe (fromMaybe)-import Data.Semigroup (Semigroup(..))-import Dhall.Map (foldMapWithKey)-import Data.Text (Text)+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.Util (Input(..))-import Dhall.Syntax (Expr(..), Binding(..))-import Dhall.Src (Src(srcStart))-import Dhall.Parser (exprFromText)-import System.FilePath ((</>), takeFileName)-import Text.Megaparsec (sourceLine, sourceColumn, unPos)+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 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@@ -35,14 +34,14 @@     http://cvs.savannah.gnu.org/viewvc/vtags/vtags/vtags.el?view=markup -} -data LineColumn = LC +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 +data LineOffset = LO     { loLine :: Int       -- ^ line number, starting from 1, where to find the tag     , loOffset :: Int@@ -56,7 +55,6 @@  instance Monoid Tags where     mempty = Tags M.empty-    mappend = (<>)  {-| For example, for the line: @let foo = \"foo\"@ the tag is:     > Tag "let " "foo"@@ -113,11 +111,11 @@     _ -> 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.+    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+    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\""@@ -138,7 +136,7 @@              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) +    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"")@@ -163,10 +161,10 @@           lengthInBytes = BS.length . encodeUtf8            {-| get information about term from map of lines-              In most cases, `LineColumn` after `getTagsFromExpr` points to byte before term.+              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@@ -191,8 +189,8 @@     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 mr-              (RecordLit mr) -> mts <> tagsFromDhallMap lpos mr+              (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
src/Dhall/Tutorial.hs view
@@ -1,8 +1,13 @@ {-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# 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@@ -80,6 +85,9 @@     -- * Prelude     -- $prelude +    -- * Limitations+    -- $limitations+     -- * Conclusion     -- $conclusion @@ -99,35 +107,37 @@ -- 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]} --@@ -139,8 +149,8 @@ -- >>> input auto "True" :: IO Bool -- True ----- The `input` function can decode any value if we specify the value's expected--- `Type`:+-- The `Dhall.input` function can decode any value if we specify the value's+-- expected `Dhall.Type`: -- -- > input -- >     :: Type a  -- Expected type@@ -150,7 +160,7 @@ -- ... and we can either specify an explicit type like `bool`: -- -- > bool :: Type Bool--- > +-- > -- > input bool :: Text -> IO Bool -- > -- > input bool "True" :: IO Bool@@ -171,7 +181,7 @@ -- 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 `Bool`:+-- @Bool@ into a Haskell `Prelude.Bool`: -- -- > instance FromDhall Bool --@@ -189,8 +199,8 @@ -- >>> 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:+-- 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]@@ -201,12 +211,12 @@ -- > {-# 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"@@ -216,12 +226,12 @@ -- decode: -- -- > {-# LANGUAGE OverloadedStrings #-}--- > +-- > -- > import Data.Functor.Identity -- > import Dhall--- > +-- > -- > instance FromDhall a => FromDhall (Identity a)--- > +-- > -- > main :: IO () -- > main = do -- >     x <- input auto "./config.dhall"@@ -244,7 +254,7 @@ -- ... -- -- The interpreter complains because the string @\"1\"@ cannot be decoded into a--- Haskell value of type `Bool`.  This part of the type error:+-- Haskell value of type `Prelude.Bool`.  This part of the type error: -- -- > - Bool -- > + Natural@@ -307,13 +317,13 @@ -- 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] --@@ -349,7 +359,7 @@ -- ... then the interpreter will reject the import: -- -- >>> input auto "./file1" :: IO Natural--- *** Exception: +-- *** Exception: -- ↳ ./file1 --   ↳ ./file2 -- ...@@ -366,13 +376,23 @@ -- -- ... 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,@@ -404,8 +424,8 @@ -- -- >>> writeFile "baz" "2.0" -- >>> input auto "./baz: Double" :: IO Double--- *** Exception: --- ↳ ./baz: +-- *** Exception:+-- ↳ ./baz: -- ... -- ...Error...: Missing file ...baz: -- ...@@ -438,15 +458,18 @@ -- -- 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:+-- parse error if you provide an empty list without a type annotation: -- -- >>> input auto "[]" :: IO (Vector Natural) -- *** Exception:--- ...Error...: An empty list requires a type annotation+-- ...Error...: Invalid input -- ...--- 1│ []+-- (input):1:3:+--   |+-- 1 | []+--   |   ^+-- Empty list literal without annotation -- ...--- (input):1:1 -- -- 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:@@ -582,7 +605,7 @@ -- 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:+-- using the @toMap@ keyword.  For example: -- -- > $ dhall <<< 'toMap { foo = 1, bar = 2 }' -- > [ { mapKey = "bar", mapValue = 2 }, { mapKey = "foo", mapValue = 1 } ]@@ -602,14 +625,17 @@ -- >     [ 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):+-- 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@.@@ -632,7 +658,7 @@ -- 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 <- input auto "\\(x : Bool) -> \\(y : Bool) -> x && y" :: IO (Bool -> Bool -> Bool) -- >>> dhallAnd True False -- False --@@ -645,16 +671,16 @@ -- > {-# 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"+-- >     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) --@@ -674,6 +700,12 @@ -- > $ 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@@ -681,17 +713,17 @@ -- @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+-- > ∀(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+-- > 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@).@@ -721,8 +753,8 @@ -- -- 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'+--+-- > $ 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@@ -730,9 +762,9 @@ -- -- >    Bound variable -- >    ⇩--- > (λ(n : Bool) → ...) True--- >                     ⇧--- >                     Function argument+-- > (\(n : Bool) -> ...) True+-- >                      ⇧+-- >                      Function argument -- -- So in our above example, we would replace all occurrences of @n@ with @True@, -- like this:@@ -755,7 +787,7 @@ -- __Exercise__: Create a file named @getFoo@ that is a function of the following -- type: ----- > ∀(r : { foo : Bool, bar : Text }) → Bool+-- > 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.@@ -779,7 +811,7 @@ -- > $ dhall -- > '' -- >     #!/bin/bash--- >     +-- > -- >     echo "Hi!" -- > '' -- > <Ctrl-D>@@ -866,14 +898,14 @@ -- ... but fails with a type error if either shared field is not a record: -- -- > $ dhall--- > { foo = 1, bar = "ABC" } ∧ { foo = True }+-- > { 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@@ -882,7 +914,7 @@ -- You can analogously combine record types using the @//\\\\@ operator (or @(⩓)@ U+2A53): -- -- > $ dhall--- > { foo : Natural } ⩓ { bar : Text }+-- > { foo : Natural } //\\ { bar : Text } -- > <Ctrl-D> -- > { foo : Natural, bar : Text } --@@ -890,7 +922,7 @@ -- operator descends recursively into record types: -- -- > $ dhall--- > { foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Natural }+-- > { foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Natural } -- > <Ctrl-D> -- > { foo : { bar : Text, baz : Bool }, qux : Natural } @@ -929,7 +961,7 @@ -- function: -- -- > $ dhall--- > let twice = λ(x : Text) → x ++ x in twice "ha"+-- > let twice = \(x : Text) -> x ++ x in twice "ha" -- > <Ctrl-D> -- > "haha" --@@ -940,7 +972,7 @@ -- > 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"@@ -964,7 +996,7 @@ -- -- > $ 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?@@ -994,12 +1026,12 @@ -- > 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" }}@@ -1050,7 +1082,7 @@ -- 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@@ -1080,10 +1112,10 @@ -- would write: -- -- > $ cat > process <<EOF--- >     λ(union : < Left : Natural | Right : Bool >)--- > →   let handlers =+-- >   \(union : < Left : Natural | Right : Bool >) ->+-- >     let handlers = -- >             { Left  = Natural/even  -- Natural/even is a built-in function--- >             , Right = λ(b : Bool) → b+-- >             , Right = \(b : Bool) -> b -- >             } -- > in  merge handlers union -- > EOF@@ -1100,7 +1132,7 @@ -- -- > merge handlers union [ : type ] ----- ... where: +-- ... where: -- -- * @union@ is the union you want to consume -- * @handlers@ is a record with one function per alternative of the union@@ -1113,14 +1145,14 @@ -- -- So, for example: ----- > merge { Left = Natural/even, Right = λ(b : Bool) → b } (< Left : Natural | Right : Bool >.Left 3)+-- > 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+-- > 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@@ -1144,7 +1176,7 @@ -- 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 }@@ -1153,13 +1185,13 @@ -- ... 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 a `λ`+-- > \(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}"+-- >     , Person =+-- >         \(person : { name : Text, age : Natural }) ->+-- >           "Name: ${person.name}, Age: ${Natural/show person.age}" -- >     } -- >     x --@@ -1191,18 +1223,18 @@ -- -- The equivalent function in Dhall is: ----- > λ(a : Type) → λ(x : a) → x+-- > \(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+-- > $ 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 --@@ -1268,7 +1300,7 @@ -- argument type then that means that the name of the argument is @"_"@.  This -- is true even for user-defined functions: ----- > $ dhall type <<< 'λ(_ : Text) → 1'+-- > $ dhall type <<< '\\(_ : Text) -> 1' -- > Text → Natural -- -- The type @Text → Natural@ is the same as @∀(_ : Text) → Natural@@@ -1301,8 +1333,8 @@ -- 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]+-- > 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] --@@ -1336,13 +1368,13 @@ -- code.  For example, we can add some tests to our @not@ function like this: -- -- > let not--- >     : Bool → Bool--- >     = λ(b : Bool) → b == False--- > +-- >     : 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@@ -1354,8 +1386,8 @@ -- > -- ./test.dhall -- > -- > let not--- >     : Bool → Bool--- >     = λ(b : Bool) → b == False+-- >     : Bool -> Bool+-- >     = \(b : Bool) -> b == False -- > -- > let example0 = assert : not False === True -- >@@ -1365,22 +1397,22 @@ -- -- The type-checker then rejects the assertion with the following error message: ----- > $ dhall <<< './test.dhall' --- > +-- > $ dhall <<< './test.dhall'+-- > -- > ↳ ./test.dhall--- > +-- > -- > Error: Assertion failed--- > +-- > -- > - False -- > + True--- > +-- > -- > 7│                assert : not True === True -- Oops!--- > 8│ --- > +-- > 8│+-- > -- > ./test.dhall:7:16--- > +-- > -- > 1│ ./test.dhall--- > +-- > -- > (input):1:1 -- -- You can compare expressions that contain variables, too, which is equivalent@@ -1398,18 +1430,18 @@ -- 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)@@@ -1456,9 +1488,9 @@ -- 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. @@ -1492,7 +1524,7 @@ -- -- > $ dhall <<< './foo' -- > Natural--- > +-- > -- > 1 -- -- Any import protected by a semantic integrity check is automatically cached@@ -1516,12 +1548,12 @@ -- 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+-- 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@@ -1539,10 +1571,10 @@ -- -- > $ 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 +-- You can compute the Hash for any import by using the hash subcommand -- of this package.  For example: -- -- > $ dhall hash <<< './bar'@@ -1557,15 +1589,15 @@ -- 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@@ -1598,21 +1630,21 @@ -- > let replicate = https://prelude.dhall-lang.org/List/replicate -- > in  replicate 5 -- > $--- > $ dhall freeze --inplace ./foo.dhall+-- > $ 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 `Text`.  For example, one of the fields of a record might be--- the contents of a software license:+-- 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  = "Gabriel Gonzalez"+-- > , author  = "Gabriella Gonzalez" -- > , license = ./LICENSE -- > } --@@ -1621,9 +1653,9 @@ -- -- > $ cat LICENSE -- > ''--- > Copyright (c) 2017 Gabriel Gonzalez+-- > 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.@@ -1636,66 +1668,66 @@ -- end of the import, like this: -- -- > { package = "dhall"--- > , author  = "Gabriel Gonzalez"+-- > , author  = "Gabriella Gonzalez" -- > , license = ./LICENSE as Text -- > } -- -- ... and then you can use the original text file unmodified: -- -- > $ cat LICENSE--- > Copyright (c) 2017 Gabriel Gonzalez+-- > 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 +-- 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 = +-- > λ(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+-- > λ(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 : 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 =+-- >             ( λ(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+-- >                     λ(n : Natural) →+-- >                       List/fold -- >                         { index : Natural, value : a } -- >                         kvs -- >                         list--- >                         (   λ(kvOld : { index : Natural, value : a })--- >                           → λ(z : list)--- >                           → cons+-- >                         ( λ(kvOld : { index : Natural, value : a }) →+-- >                           λ(z : list) →+-- >                             cons -- >                               { index = kvOld.index + n, value = kvOld.value } -- >                               z -- >                         )@@ -1713,20 +1745,19 @@ -- normalizing them: -- -- > $ dhall format--- > let replicate = https://prelude.dhall-lang.org/List/replicate +-- > 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 using the--- @--inplace@ flag (i.e. for formatting source code):+-- You can also use the formatter to modify files in place: ----- > $ dhall format --inplace ./unformatted+-- > $ dhall format ./unformatted -- -- Carefully note that the code formatter does not preserve all comments. -- Currently, the formatter only preserves two types of comments:@@ -1752,7 +1783,7 @@ -- >     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@@ -1760,7 +1791,7 @@ -- multi-line expressions, too: -- -- > $ dhall--- > let replicate = https://prelude.dhall-lang.org/List/replicate +-- > 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 ]@@ -1826,7 +1857,7 @@ -- You can find an up-to-date list of available built-in functions and operators -- here: ----- <https://github.com/dhall-lang/dhall-lang/wiki/Built-in-types%2C-functions%2C-and-operators Built-in types, functions, and operators>+-- <https://docs.dhall-lang.org/references/Built-in-types.html>  -- $caveats --@@ -1844,16 +1875,20 @@ -- > +2 + +2 -- > <Ctrl-D> -- > Use "dhall --explain" for detailed errors--- > +-- > -- > Error: ❰+❱ only works on ❰Natural❱s--- > +-- > -- > +2 + +2--- > +-- > -- > (input):1:1 ----- In fact, there are no built-in functions for @Integer@s (or @Double@s) other--- than @Integer/show@ and @Double/show@.  As far as the language is concerned--- they are opaque values that can only be shuffled around but not used in any+-- 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@@ -1868,52 +1903,52 @@ -- 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+-- > 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:@@ -1925,22 +1960,22 @@ -- 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 --- > +-- >+-- > 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)@@ -1948,6 +1983,7 @@ -- $substitutions -- -- Substitutions are another way to extend the language.+-- -- Suppose we have the following Haskell datatype: -- -- > data Result = Failure Integer | Success String@@ -1959,28 +1995,15 @@ -- -- > -- example.dhall -- >--- > let Result = < Failure : Integer | Success Text >--- > in Result.Failure 1+-- > 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?--- Maintaining the code will get tedious. Luckily we can extract the correct Dhall type from the Haskell definition: ----- > resultDecoder :: Dhall.Decoder Result--- > resultDecoder = Dhall.auto--- >--- > resultType :: Expr Src Void--- > resultType = Dhall.expected resultDecoder--- >--- > resultTypeString :: String--- > resultTypeString = show $ pretty resultType------ Now we just have to inject that type into the Dhall code and we are done. One common way to do that is to wrap the import of example.dhall in a let expression:------ > Dhall.input (Dhall.auto :: Dhall.Decoder Result) ("let Result = " ++ Data.Text.pack resultTypeString ++ " in ./example.dhall")------ Now we can omit the definition of Result in our example.dhall file. While this will work perfectly Dhall provides a cleaner solution for our \"injection problem\":+-- We can override the interpreter's @evaluateSettings@ with a custom set of+-- substitutions, like this: -- -- > {-# LANGUAGE OverloadedStrings #-} -- >@@ -2018,17 +2041,17 @@ -- 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'+-- > $ dhall <<< 'https://prelude.dhall-lang.org/Bool/not as Text' -- > '' -- > {---- > Flip the value of a `Bool`+-- > 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 -- > '' --@@ -2073,11 +2096,11 @@ -- > 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 -- > '' --@@ -2225,10 +2248,10 @@ -- convenience: -- -- > $ dhall--- >     let Prelude = https://prelude.dhall-lang.org/package.dhall+-- > let Prelude = https://prelude.dhall-lang.org/package.dhall -- >--- > in    λ(x : Text)--- >     → Prelude.List.length Text (Prelude.List.replicate 10 Text x)+-- > in  \(x : Text) ->+-- >       Prelude.List.length Text (Prelude.List.replicate 10 Text x) -- > <Ctrl-D> -- > ∀(x : Text) → Natural -- >@@ -2242,6 +2265,35 @@ -- -- > $ 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@@ -2250,6 +2302,11 @@ -- -- <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. --@@ -2259,4 +2316,4 @@  -- $faq ----- <https://github.com/dhall-lang/dhall-lang/wiki/Frequently-Asked-Questions-(FAQ) Frequently Asked Questions (FAQ)>+-- <https://docs.dhall-lang.org/howtos/FAQ.html>
src/Dhall/TypeCheck.hs view
@@ -3,4747 +3,4849 @@ {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}--{-# 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.Monoid (Endo(..))-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup (Max(..), Semigroup(..))-import Data.Sequence (Seq, ViewL(..))-import Data.Set (Set)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty(..))-import Data.Typeable (Typeable)-import Data.Void (Void, absurd)-import Dhall.Context (Context)-import Dhall.Eval (Environment(..), Names(..), Val(..), (~>))-import Dhall.Pretty (Ann)-import Dhall.Src (Src)-import Lens.Family (over)--import Dhall.Syntax-    ( Binding(..)-    , Const(..)-    , Chunks(..)-    , Expr(..)-    , PreferAnnotation(..)-    , Var(..)-    )--import qualified Data.Foldable                           as Foldable-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.Text.Prettyprint.Doc               as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-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.Set-import qualified Dhall.Syntax                            as Syntax-import qualified Dhall.Util-import qualified Lens.Family--{-| 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" #-}--traverseWithIndex_ :: Applicative f => (Int -> a -> f b) -> Seq a -> f ()-traverseWithIndex_ k xs = Foldable.sequenceA_ (Data.Sequence.mapWithIndex k xs)--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 `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 -> do-            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 x _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 -> do-                    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 do-                            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 do-                    return _T₁'--                else do-                    let _T₀'' = quote names _T₀'-                    let _T₁'' = quote names _T₁'-                    die (AnnotMismatch t _T₀'' _T₁'')--        Bool -> do-            return (VConst Type)--        BoolLit _ -> do-            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--            tL' <- loop ctx (quote names _L')--            let _L'' = quote names _L'--            case tL' of-                VConst Type -> do-                    return ()-                _  -> do-                    let tL'' = quote names tL'-                    die (IfBranchMustBeTerm True l _L'' tL'')--            tR' <- loop ctx (quote names _R')--            let _R'' = quote names _R'--            case tR' of-                VConst Type -> do-                    return ()-                _ -> do-                    let tR'' = quote names tR'-                    die (IfBranchMustBeTerm True r _R'' tR'')--            if Eval.conv values _L' _R'-                then return ()-                else die (IfBranchMismatch l r _L'' _R'')--            return _L'--        Natural -> do-            return (VConst Type)--        NaturalLit _ -> do-            return VNatural--        NaturalFold -> do-            return-                (   VNatural-                ~>  VHPi "natural" (VConst Type) (\natural ->-                        VHPi "succ" (natural ~> natural) (\_succ ->-                            VHPi "zero" natural (\_zero ->-                                natural-                            )-                        )-                    )-                )--        NaturalBuild -> do-            return-                (   VHPi "natural" (VConst Type) (\natural ->-                        VHPi "succ" (natural ~> natural) (\_succ ->-                            VHPi "zero" natural (\_zero ->-                                natural-                            )-                        )-                    )-                ~>  VNatural-                )--        NaturalIsZero -> do-            return (VNatural ~> VBool)--        NaturalEven -> do-            return (VNatural ~> VBool)--        NaturalOdd -> do-            return (VNatural ~> VBool)--        NaturalToInteger -> do-            return (VNatural ~> VInteger)--        NaturalShow -> do-            return (VNatural ~> VText)--        NaturalSubtract -> do-            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 -> do-            return (VConst Type)--        IntegerLit _ -> do-            return VInteger--        IntegerClamp -> do-            return (VInteger ~> VNatural)--        IntegerNegate -> do-            return (VInteger ~> VInteger)--        IntegerShow -> do-            return (VInteger ~> VText)--        IntegerToDouble -> do-            return (VInteger ~> VDouble)--        Double -> do-            return (VConst Type)--        DoubleLit _ -> do-            return VDouble--        DoubleShow -> do-            return (VDouble ~> VText)--        Text -> do-            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--        TextShow -> do-            return (VText ~> VText)--        List -> do-            return (VConst Type ~> VConst Type)--        ListLit Nothing ts₀ -> do-            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 do-                                    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)--                    traverseWithIndex_ process ts₁--                    return (VList _T₀')--                _ -> do-                    die MissingListType--        ListLit (Just _T₀) ts -> do-            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 -> do-            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 -> do-            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 -> do-            return (VHPi "a" (VConst Type) (\a -> VList a ~> VNatural))--        ListHead -> do-            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))--        ListLast -> do-            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))--        ListIndexed -> do-            return-                (   VHPi "a" (VConst Type) (\a ->-                            VList a-                        ~>  VList-                                (VRecord-                                    (Dhall.Map.unorderedFromList-                                        [ ("index", VNatural)-                                        , ("value", a       )-                                        ]-                                    )-                                )-                    )-                )-        ListReverse -> do-            return (VHPi "a" (VConst Type) (\a -> VList a ~> VList a))--        Optional -> do-            return (VConst Type ~> VConst Type)--        None -> do-            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')--        OptionalFold -> do-            return-                (   VHPi "a" (VConst Type) (\a ->-                            VOptional a-                        ~>  VHPi "optional" (VConst Type) (\optional ->-                                VHPi "just" (a ~> optional) (\_just ->-                                    VHPi "nothing" optional (\_nothing ->-                                        optional-                                    )-                                )-                            )-                    )-                )--        OptionalBuild -> do-            return-                (   VHPi "a" (VConst Type) (\a ->-                            VHPi "optional" (VConst Type) (\optional ->-                                VHPi "just" (a ~> optional) (\_just ->-                                    VHPi "nothing" optional (\_nothing ->-                                        optional-                                    )-                                )-                            )-                        ~>  VOptional a-                    )-                )--        Record xTs -> do-            let process x _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 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 = do-                    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 l)--            xLs' <- case _L' of-                VRecord xLs' -> do-                    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' -> do-                    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 _ _ = do-                            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 a 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)--                    case a of-                        PreferFromWith withExpression ->-                            die (MustUpdateARecord withExpression l'' _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 PreferFromCompletion (Field l "default") r) (Field l "Type"))-                _ -> die (CompletionSchemaMustBeARecord l (quote names _L'))--        Merge t u mT₁ -> do-            _T' <- loop ctx t--            yTs' <- case _T' of-                VRecord yTs' -> do-                    return yTs'--                _ -> do-                    let _T'' = quote names _T'--                    die (MustMergeARecord t _T'')--            _U' <- loop ctx u--            yUs' <- case _U' of-                VUnion yUs' -> do-                    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₀') -> do-                            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 =-                                            Lens.Family.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₁') -> do-                    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) -> do-                    die MissingToMapType-                (Just err@(Left _), _) -> do-                    err-                (Just (Right _T'), Nothing) -> do-                    pure (mapType _T')-                (Nothing, Just _T₁'@(VList (VRecord itemTypes)))-                   | Just _T' <- Dhall.Map.lookup "mapValue" itemTypes-                   , Eval.conv values (mapType _T') _T₁' -> do-                       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₁' -> do-                       pure (mapType _T')-                   | otherwise -> do-                       let _T₁'' = quote names _T₁'--                       die (MapTypeMismatch (quote names (mapType _T')) _T₁'')--        Field e x -> do-            _E' <- loop ctx e--            let _E'' = quote names _E'--            case _E' of-                VRecord xTs' -> do-                    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' -> do-                            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-            _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 (Dhall.Set.toAscList 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 -> do-                                            die (MissingField x _E'')--                                        Just _E' -> do-                                            if Eval.conv values _E' _S'-                                                then return ()-                                                else die (ProjectionTypeMismatch x _E'' _S'' expectedSubset actualSubset)--                            Dhall.Map.unorderedTraverseWithKey_ process xSs'--                            return s'--                        _ -> do-                            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'')--                _ -> do-                    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)--        e@With{} -> do-            loop ctx (Syntax.desugarWith e)--        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 -> do-            loop ctx l--        Embed p -> do-            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)-    | InvalidListElement 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)-    | IfBranchMustBeTerm Bool (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)-    | MustUpdateARecord (Expr s a) (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)-    | RecordTypeMismatch Const Const (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)-    | InvalidHandlerOutputType Text (Expr s a) (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)-    | 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)-    | 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)-    deriving (Show)--shortTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann-shortTypeMessage msg =-    "\ESC[1;31mError\ESC[0m: " <> short <> "\n"-  where-    ErrorMessages {..} = prettyTypeMessage msg--longTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann-longTypeMessage msg =-        "\ESC[1;31mError\ESC[0m: " <> short <> "\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-    , 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---- | 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--    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"--    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"--    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"--    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)--    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)-    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"--    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)--    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 (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 : Natural : Type │  ❰1❱ is a term with a type (❰Natural❱) 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 = insert expr0-        txt2 = insert expr1-        txt3 = insert expr2--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)--    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"--    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❱"--    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 = 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 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)--    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 (InvalidListElement i expr0 _expr1 expr2) =-    ErrorMessages {..}-  where-    short = "List element has the wrong type\n"-        <>  "\n"-        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr2)--    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 Natural │  Every element in this ❰List❱ is an ❰Natural❱  \n\-        \    └──────────────────────────┘                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \.. but this is " <> _NOT <> " a valid ❰List❱:                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ [1, \"ABC\", 3] : List Natural │  The second element is not an ❰Natural❱  \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 = insert expr0-        txt1 = pretty i-        txt3 = insert expr2--prettyTypeMessage (InvalidSome expr0 expr1 expr2) = ErrorMessages {..}-  where-    short = "❰Some❱ argument has the wrong type"--    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"--    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"--    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)--    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" --   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--   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 (MustUpdateARecord withExpression expression typeExpression) =-    ErrorMessages {..}-  where-    short = "You can only update records"--    long =-        "Explanation: You can update records using the ❰with❱ keyword, like this:        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ { x = { y = 1 } } with x.y = 2 │                                          \n\-        \    └────────────────────────────────┘                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────────────────────────┐              \n\-        \    │ λ(r : { foo : { bar : Bool } }) → r with foo.bar = False } │              \n\-        \    └────────────────────────────────────────────────────────────┘              \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot update values that are not records.                          \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ 1 with x = True │                                                         \n\-        \    └─────────────────┘                                                         \n\-        \      ⇧                                                                         \n\-        \      Invalid: Not a record                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \The following expression is not permitted:                                      \n\-        \                                                                                \n\-        \" <> insert withExpression' <> "\n\-        \                                                                                \n\-        \... because the left argument to ❰with❱:                                        \n\-        \                                                                                \n\-        \" <> insert expression <> "\n\-        \                                                                                \n\-        \... is not a record, but is actually a:                                         \n\-        \                                                                                \n\-        \" <> insert typeExpression <> "\n"-      where-        withExpression' = case withExpression of-            With record keys value -> With (Dhall.Core.normalize record) keys value-            _                      -> withExpression--prettyTypeMessage (MustCombineARecord c expression typeExpression) =-    ErrorMessages {..}-  where-    action = case c of-        '∧' -> "combine"-        _   -> "override"--    short = "You can only " <> action <> " records"--    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--    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 True k)-        txt1 = insert expr0-        txt2 = insert expr1--prettyTypeMessage (CombineTypesRequiresRecordType expr0 expr1) =-    ErrorMessages {..}-  where-    short = "❰⩓❱ requires arguments that are record types"--    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 (RecordTypeMismatch const0 const1 expr0 expr1) =-    ErrorMessages {..}-  where-    short = "Record type mismatch"--    long =-        "Explanation: You can only use the ❰⩓❱ operator on record types if they are both \n\-        \ ❰Type❱s or ❰Kind❱s:                                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────┐                                     \n\-        \    │ { age : Natural } ⩓ { name : Text } │  Valid: Both arguments are ❰Type❱s  \n\-        \    └─────────────────────────────────────┘                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────┐                                    \n\-        \    │ { Input : Type } ⩓ { Output : Type } │  Valid: Both arguments are ❰Kind❱s \n\-        \    └──────────────────────────────────────┘                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot combine a ❰Type❱ and a ❰Kind❱:                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────┐                                      \n\-        \    │ { Input : Type } ⩓ { name : Text } │  Invalid: The arguments do not match \n\-        \    └────────────────────────────────────┘                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to combine the following record type:                                 \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... with this record types:                                                     \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... but the former record type is a:                                            \n\-        \                                                                                \n\-        \" <> txt2 <> "\n\-        \                                                                                \n\-        \... but the latter record type is a:                                            \n\-        \                                                                                \n\-        \" <> txt3 <> "\n"-      where-        txt0 = insert expr0-        txt1 = insert expr1-        txt2 = insert const0-        txt3 = insert const1--prettyTypeMessage (DuplicateFieldCannotBeMerged ks) = ErrorMessages {..}-  where-    short = "Duplicate field cannot be merged: " <> pretty (toPath ks)--    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 True (NonEmpty.head ks))--        txt1 = insert (toPath ks)--prettyTypeMessage (FieldCollision ks) = ErrorMessages {..}-  where-    short = "Field collision on: " <> pretty (toPath ks)--    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)--    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"--    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❱"--    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"--    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)--    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"--    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)--    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"--    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 (InvalidHandlerOutputType expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "Wrong handler output type\n"-        <>  "\n"-        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)--    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 : Bool                                 │         \n\-        \    └─────────────────────────────────────────────────────────────────┘         \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the output type of each handler function matches the declared    \n\-        \type 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 : Natural | Right : Bool >.Left 2          │        \n\-        \    │ 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 = insert expr0-        txt1 = insert expr1-        txt2 = insert expr2--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)--    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"--    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 _expr0 _expr1) = ErrorMessages {..}-  where-    short = "❰toMap❱ expects a record value"--    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❱"--    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"--    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)--    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--    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"--    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"--    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"--    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"--    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 (MissingField k expr0) = ErrorMessages {..}-  where-    short = "Missing record field: " <> Dhall.Pretty.Internal.prettyLabel k--    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--    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)--    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)--    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"--    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"--    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"--    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 (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: ${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❱"--    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"--    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--buildBooleanOperator :: Pretty 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 = 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"--    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-    `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-    InvalidListElement a b c d ->-        InvalidListElement <$> 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-    IfBranchMustBeTerm a b c d ->-        IfBranchMustBeTerm <$> pure 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-    MustUpdateARecord a b c ->-        MustUpdateARecord <$> f 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-    RecordTypeMismatch a b c d ->-        RecordTypeMismatch <$> pure a <*> pure b <*> f c <*> f d-    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-    InvalidHandlerOutputType a b c ->-        InvalidHandlerOutputType <$> pure a <*> f b <*> f c-    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-    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-    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--{-| 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 -> 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 ()--toPath :: (Functor list, Foldable list) => list Text -> Text-toPath ks =-    Text.intercalate "."-        (Foldable.toList (fmap (Dhall.Pretty.Internal.escapeLabel True) ks))+{-# 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
@@ -3,20 +3,12 @@  module Dhall.URL where -import Data.Monoid ((<>)) import Data.Text (Text) -import Dhall.Syntax-    ( Scheme(..)-    , URL(..)-    , File(..)-    , Directory(..)-    )--import qualified Network.URI.Encode as URI.Encode+import Dhall.Syntax (Directory (..), File (..), Scheme (..), URL (..))  renderComponent :: Text -> Text-renderComponent component = "/" <> URI.Encode.encodeText component+renderComponent component = "/" <> component  renderQuery :: Text -> Text renderQuery query = "?" <> query
src/Dhall/Util.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-} @@ -8,8 +9,11 @@     , snipDoc     , insert     , _ERROR+    , _WARNING+    , printWarning     , Censor(..)     , Input(..)+    , Transitivity(..)     , OutputMode(..)     , Output(..)     , getExpression@@ -17,27 +21,35 @@     , getExpressionAndHeaderFromStdinText     , Header(..)     , CheckFailed(..)+    , MultipleCheckFailed(..)+    , handleMultipleChecksFailed+    , renderExpression     ) where -import Control.Exception (Exception(..))-import Control.Monad.IO.Class (MonadIO(..))-import Data.Bifunctor (first)-import Data.Monoid ((<>))-import Data.String (IsString)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Dhall.Parser (ParseError, Header(..))-import Dhall.Pretty (Ann)-import Dhall.Syntax (Expr, Import)-import Dhall.Src (Src)+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 Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal 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@@ -101,23 +113,38 @@ _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 <- do+    inText <-         case input of             Input_ (InputFile file) -> Data.Text.IO.readFile file             Input_ StandardInput    -> Data.Text.IO.getContents-            StdinText text          -> pure text+            StdinText _ text        -> pure text      let name =             case input of                 Input_ (InputFile file) -> file                 Input_ StandardInput    -> "(input)"-                StdinText _             -> "(input)"+                StdinText inputName _   -> inputName      let result = parser name inText @@ -139,11 +166,24 @@ data Censor = NoCensor | Censor  -- | Path to input-data Input = StandardInput | InputFile FilePath+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 Text+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 @@ -153,15 +193,25 @@ -} 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 CheckFailed = CheckFailed { command :: Text, modified :: Text }+data MultipleCheckFailed = MultipleCheckFailed+  { command :: Text+  , modified :: Text+  , inputs :: NonEmpty Input+  } -instance Exception CheckFailed+instance Exception MultipleCheckFailed -instance Show CheckFailed where-    show CheckFailed{..} =-         _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed\n\-        \\n\+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"@@ -170,6 +220,32 @@          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_@@ -181,6 +257,35 @@  -- | Convenient utility for retrieving an expression along with its header from -- | text already read from STDIN (so it's not re-read)-getExpressionAndHeaderFromStdinText :: Censor -> Text -> IO (Header, Expr Src Import)-getExpressionAndHeaderFromStdinText censor =-    get Dhall.Parser.exprAndHeaderFromText censor . StdinText+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/Version.hs view
@@ -8,7 +8,7 @@ import qualified Data.Version as V import qualified Paths_dhall  as P --- | The current `Version` of the Haskell implementation+-- | The current `V.Version` of the Haskell implementation dhallVersion :: V.Version dhallVersion = P.version 
tests/Dhall/Test/Dhall.hs view
@@ -1,36 +1,38 @@+{-# LANGUAGE BangPatterns        #-} {-# LANGUAGE DeriveAnyClass      #-}-{-# LANGUAGE DeriveFoldable      #-} {-# LANGUAGE DeriveFunctor       #-} {-# LANGUAGE DeriveGeneric       #-}-{-# LANGUAGE DeriveTraversable   #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE OverloadedLists     #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TemplateHaskell     #-} {-# LANGUAGE TypeFamilies        #-}  {-# OPTIONS_GHC -fno-warn-orphans #-}  module Dhall.Test.Dhall where -import Control.Exception (SomeException, try)-import Data.Fix (Fix(..))-import Data.List.NonEmpty (NonEmpty (..))-import Data.Sequence (Seq)-import Data.Scientific (Scientific)-import Data.Text (Text)-import Data.Vector (Vector)-import Data.Void (Void)-import Dhall (ToDhall, FromDhall)-import Dhall.Core (Expr(..))-import GHC.Generics (Generic, Rep)-import Numeric.Natural (Natural)+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@@ -42,8 +44,19 @@    = LitF Natural    | AddF expr expr    | MulF expr expr-   deriving (Eq, Functor, Generic, FromDhall, Show)+   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"@@ -61,12 +74,12 @@ data MyType = MyType { foo :: String , bar :: Natural }  wrongDhallType :: Dhall.Decoder MyType-wrongDhallType = Dhall.Decoder { .. }-  where expected =+wrongDhallType = Dhall.Decoder {..}+  where expected = pure $           Dhall.Core.Record             ( Dhall.Map.fromList-              [ ( "bar", Dhall.Core.Natural)-              , ( "foo", Dhall.Core.Text )+              [ ( "bar", Dhall.Core.makeRecordField Dhall.Core.Natural)+              , ( "foo", Dhall.Core.makeRecordField Dhall.Core.Text )               ]             )         extract expr = Dhall.typeError expected expr@@ -79,14 +92,15 @@   let expectedMsg =         "\ESC[1;31mError\ESC[0m: Invalid Dhall.Decoder                                               \n\         \                                                                                \n\-        \Every Decoder must provide an extract function that succeeds if an expression   \n\-        \matches the expected type.  You provided a Decoder that disobeys this contract  \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 couldn't extract a value from the well-typed expression:                 \n\+        \and it threw a type error during extraction from the well-typed expression:     \n\         \                                                                                \n\         \↳ { bar = 0, foo = \"foo\" }\n\         \                                                                                \n"@@ -117,18 +131,39 @@     let exampleEncoder :: Dhall.Encoder ()         exampleEncoder = Dhall.unionEncoder (Dhall.encodeConstructor "A") -    Dhall.embed exampleEncoder () @=? Field (Union (Dhall.Map.singleton "A" Nothing)) "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 =@@ -318,7 +353,7 @@       :: ( Generic a          , Dhall.GenericToDhall (Rep a)          , Generic b-         , Dhall.GenericFromDhall (Rep b)+         , Dhall.GenericFromDhall b (Rep b)          )       => Dhall.InterpretOptions -> Dhall.Decoder (a -> b)     functionWithOptions options =@@ -454,9 +489,10 @@     let assertMsg = "The exception message did not match the expected output"      case inputEx of-      Left (Dhall.ExtractErrors errs) -> case errs 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
@@ -2,22 +2,19 @@  module Dhall.Test.Diff where -import Data.Monoid ((<>))-import Data.Text (Text)-import Prelude hiding (FilePath)+import Data.Text  (Text) import Test.Tasty (TestTree)-import Turtle (FilePath) -import qualified Data.Text                             as Text-import qualified Data.Text.IO                          as Text.IO-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text-import qualified Dhall.Core                            as Core-import qualified Dhall.Diff                            as Diff-import qualified Dhall.Parser                          as Parser+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 Test.Tasty                            as Tasty-import qualified Test.Tasty.HUnit                      as Tasty.HUnit+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
+ 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
@@ -2,23 +2,21 @@  module Dhall.Test.Format where -import Data.Monoid (mempty, (<>))-import Data.Text (Text)-import Dhall.Parser (Header(..))-import Dhall.Pretty (CharacterSet(..))-import Test.Tasty (TestTree)+import Data.Text    (Text)+import Dhall.Parser (Header (..))+import Dhall.Pretty (CharacterSet (..))+import Test.Tasty   (TestTree) -import qualified Control.Monad                         as Monad-import qualified Data.Text                             as Text-import qualified Data.Text.IO                          as Text.IO-import qualified Data.Text.Prettyprint.Doc             as Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text as Doc.Render.Text-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 Test.Tasty                            as Tasty-import qualified Test.Tasty.HUnit                      as Tasty.HUnit+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@@ -28,7 +26,7 @@              let skip = [ "./tests/format/asciiA.dhall" ] -            Monad.guard (path `notElem` skip)+            path `Test.Util.pathNotIn` skip              return path @@ -56,22 +54,14 @@  formatTest :: CharacterSet -> Text -> TestTree formatTest characterSet 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--        headerAndExpr <- Core.throws (Parser.exprAndHeaderFromText mempty inputText)+    let inputFile  = Text.unpack (prefix <> "A.dhall")+        outputFile = Text.unpack (prefix <> "B.dhall") -        let actualText = format characterSet headerAndExpr-        expectedText <- Text.IO.readFile outputFile+        action = do+            inputText <- Text.IO.readFile inputFile -        let message =-                   "The formatted expression did not match the expected output\n"-                <> "Expected:\n\n" <> Text.unpack expectedText <> "\n\n"-                <> "Actual:\n\n" <> Text.unpack actualText <> "\n\n"-                <> "Expected (show): " <> show expectedText <> "\n"-                <> "Actual   (show): " <> show actualText <> "\n"+            headerAndExpr <- Core.throws (Parser.exprAndHeaderFromText mempty inputText) -        Tasty.HUnit.assertBool message (actualText == expectedText)+            return (format characterSet headerAndExpr)+    in+        Tasty.Silver.goldenVsAction (Text.unpack prefix) outputFile action id
tests/Dhall/Test/Freeze.hs view
@@ -2,11 +2,9 @@  module Dhall.Test.Freeze where -import Data.Text (Text)-import Dhall.Freeze (Intent(..), Scope(..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+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@@ -18,19 +16,30 @@ import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle -freezeDirectory :: FilePath-freezeDirectory = "./tests/freeze"+freezeDirectoryCached :: FilePath+freezeDirectoryCached = "./tests/freeze/cached" +freezeDirectorySecure :: FilePath+freezeDirectorySecure = "./tests/freeze/secure"+ getTests :: IO TestTree getTests = do-    freezeTests <- Test.Util.discover (Turtle.chars <* "A.dhall") freezeTest (Turtle.lstree freezeDirectory)+    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" [ freezeTests ]+    let testTree = Tasty.testGroup "freeze tests"+            [ Tasty.testGroup "cached" [freezeCachedTests]+            , Tasty.testGroup "secure" [freezeSecureTests]+            ]      return testTree -freezeTest :: Text -> TestTree-freezeTest prefix = do+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")@@ -39,7 +48,7 @@          parsedInput <- Core.throws (Parser.exprFromText mempty inputText) -        actualExpression <- Freeze.freezeExpression (Turtle.encodeString freezeDirectory) AllImports Cache parsedInput+        actualExpression <- Freeze.freezeExpression dir AllImports intent parsedInput          let actualText = Core.pretty actualExpression <> "\n" 
tests/Dhall/Test/Import.hs view
@@ -1,18 +1,16 @@+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}  module Dhall.Test.Import where  import Control.Exception (SomeException)-import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall.Import (MissingImports(..))-import Dhall.Parser (SourcedException(..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+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                    as Monad import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text                        as Text import qualified Data.Text.IO                     as Text.IO@@ -21,10 +19,17 @@ 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" @@ -37,17 +42,64 @@               --               --     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+    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest (do         path <- Turtle.lstree (importDirectory </> "success") -        Monad.guard (path `notElem` flakyTests)+        path `Test.Util.pathNotIn` flakyTests          return path ) -    failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest (Turtle.lstree (importDirectory </> "failure"))+    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@@ -57,60 +109,131 @@     return testTree  successTest :: Text -> TestTree-successTest path = do-    let pathString = Text.unpack path+successTest prefix = do+    let inputPath = Text.unpack (prefix <> "A.dhall") -    let directoryString = FilePath.takeDirectory pathString+    let expectedPath = Text.unpack (prefix <> "B.dhall") +    let directoryString = FilePath.takeDirectory inputPath+     let expectedFailures =-            [ importDirectory </> "success/unit/asLocation/HashA.dhall"+            [+              -- 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 path expectedFailures (do+    Test.Util.testCase prefix expectedFailures (do -        text <- Text.IO.readFile pathString+        text <- Text.IO.readFile inputPath +        expectedText <- Text.IO.readFile expectedPath+         actualExpr <- Core.throws (Parser.exprFromText mempty text) -        let setCache =-                Turtle.export "XDG_CACHE_HOME" "dhall-lang/tests/import/cache"+        expectedExpr <- Core.throws (Parser.exprFromText mempty expectedText) -        let unsetCache = Turtle.unset "XDG_CACHE_HOME"+        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) (Import.emptyStatus directoryString)+                State.evalStateT+                    (Test.Util.loadWith actualExpr)+                    status -        let runTest = do-                if Turtle.filename (Turtle.fromText path) `elem`-                     [ "hashFromCacheA.dhall"-                     , "unit/asLocation/HashA.dhall"-                     ]+        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-                        setCache-                        _ <- load-                        unsetCache-                    else do-                        _ <- load+                        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 handler :: SomeException -> IO ()+        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) -        Exception.handle handler runTest+        actualResolved <- Exception.handle handler resolve -        return () )+        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 path = do+failureTest prefix = do+    let path = prefix <> ".dhall"+     let pathString = Text.unpack path      Tasty.HUnit.testCase pathString (do-        text <- Text.IO.readFile pathString+        actualExpr <- do+          Core.throws (Parser.exprFromText mempty (Test.Util.toDhallPath path)) -        actualExpr <- Core.throws (Parser.exprFromText mempty text)+        let setup = Test.Util.managedTestEnvironment prefix -        Exception.catch-          (do _ <- Test.Util.load actualExpr+        let run = Exception.catch @SomeException+              (Test.Util.load actualExpr >> return True)+              (\_ -> return False) -              fail "Import should have failed, but it succeeds")-          (\(SourcedException _ (MissingImports _)) -> pure ()) )+        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
@@ -2,24 +2,21 @@  module Dhall.Test.Lint where -import Data.Monoid (mempty, (<>))-import Data.Text (Text)-import Dhall.Parser (Header(..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+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 Data.Text.Prettyprint.Doc as Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text as Doc.Render.Text-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 Test.Tasty       as Tasty-import qualified Test.Tasty.HUnit as Tasty.HUnit+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
tests/Dhall/Test/Main.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} module Main where  import System.FilePath ((</>))@@ -5,17 +6,22 @@  import qualified Dhall.Test.Dhall import qualified Dhall.Test.Diff-import qualified Dhall.Test.Tags+import qualified Dhall.Test.DirectoryTree import qualified Dhall.Test.Format import qualified Dhall.Test.Freeze-import qualified Dhall.Test.SemanticHash 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@@ -46,6 +52,8 @@      freezeTests <- Dhall.Test.Freeze.getTests +    schemaTests <- Dhall.Test.Schemas.getTests+     let testTree =             Test.Tasty.testGroup "Dhall Tests"                 [ normalizationTests@@ -58,11 +66,16 @@                 , 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@@ -76,6 +89,10 @@     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 
tests/Dhall/Test/Normalization.hs view
@@ -2,13 +2,11 @@  module Dhall.Test.Normalization where -import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Void (Void)-import Dhall.Core (Expr(..), Var(..), throws)-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+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@@ -18,6 +16,7 @@ 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@@ -25,32 +24,41 @@ 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 <- Turtle.lstree normalizationDirectory+            path <- FilePath.normalise <$> Turtle.lstree normalizationDirectory -            Nothing <- return (Turtle.stripPrefix (normalizationDirectory </> "unit/") path)+            unitDirectory `Test.Util.pathNotPrefixOf` path              return path      betaNormalizationTests <- Test.Util.discover pattern betaNormalizationTest normalizationFiles -    alphaNormalizationTests <- do+    alphaNormalizationTests <-         Test.Util.discover pattern alphaNormalizationTest             (Turtle.lstree "./dhall-lang/tests/alpha-normalization/success/") -    let unitTestFiles = Turtle.lstree (normalizationDirectory </> "unit/")+    let unitTestFiles = Turtle.lstree unitDirectory      unitTests <- Test.Util.discover pattern unitTest unitTestFiles      let testTree =             Tasty.testGroup "normalization"-                [ betaNormalizationTests-                , unitTests-                , alphaNormalizationTests+                [ Tasty.testGroup "beta-normalization"+                    [ betaNormalizationTests+                    ]+                , Tasty.testGroup "unit tests"+                    [ unitTests+                    ]+                , Tasty.testGroup "alpha-normalization"+                    [ alphaNormalizationTests+                    ]                 , customization                 ] @@ -68,7 +76,7 @@     let tyCtx =             Context.insert                 "min"-                (Pi "_" Natural (Pi "_" Natural Natural))+                (Pi mempty "_" Natural (Pi mempty "_" Natural Natural))                 Context.empty          valCtx e =@@ -129,7 +137,7 @@         let expectedNormalized = Core.denote expectedResolved :: Expr Void Void          let message =-                "The normalized expression did not match the expected output"+                "The alpha-normalized expression did not match the expected output"          Tasty.HUnit.assertEqual message expectedNormalized actualNormalized @@ -201,6 +209,6 @@                 Core.alphaNormalize (Core.denote expectedResolved)          let message =-                "The normalized expression did not match the expected output"+                "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
@@ -2,21 +2,19 @@  module Dhall.Test.Parser where -import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Void (Void)-import Dhall.Core (Binding(..), Expr(..), Import, Var(..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+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.IO         as Text.IO 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@@ -36,23 +34,23 @@ getTests = do     let successFiles = Turtle.lstree (parseDirectory </> "success") -    successTests <- do+    successTests <-         Test.Util.discover (Turtle.chars <* "A.dhall") shouldParse successFiles      let failureFiles = Turtle.lstree (parseDirectory </> "failure") -    failureTests <- do+    failureTests <-         Test.Util.discover (Turtle.chars <> ".dhall") shouldNotParse failureFiles      let binaryDecodeSuccessFiles =             Turtle.lstree (binaryDecodeDirectory </> "success") -    binaryDecodeSuccessTests <- do+    binaryDecodeSuccessTests <-         Test.Util.discover (Turtle.chars <* "A.dhallb") shouldDecode binaryDecodeSuccessFiles      let binaryDecodeFailureFiles = Turtle.lstree (binaryDecodeDirectory </> "failure") -    binaryDecodeFailureTests <- do+    binaryDecodeFailureTests <-         Test.Util.discover (Turtle.chars <* ".dhallb") shouldNotDecode binaryDecodeFailureFiles      let testTree =@@ -72,7 +70,7 @@         [ notesInLetInLet ]  notesInLetInLet :: TestTree-notesInLetInLet = do+notesInLetInLet =     Tasty.HUnit.testCase "Notes in let-in-let" $ do         let code = "let x = 0 let y = 1 in let z = 2 in x" @@ -124,11 +122,7 @@  shouldParse :: Text -> TestTree shouldParse path = do-    let expectedFailures =-            -- This is a bug created by a parsing performance-            -- improvement-            [ parseDirectory </> "success/unit/MergeParenAnnotation"-            ]+    let expectedFailures = []      let pathString = Text.unpack path @@ -158,16 +152,7 @@ shouldNotParse :: Text -> TestTree shouldNotParse path = do     let expectedFailures =-            [ -- For parsing performance reasons the implementation-              -- treats a missing type annotation on an empty list as-              -- as a type-checking failure instead of a parse failure,-              -- but this might be fixable.-              parseDirectory </> "failure/unit/ListLitEmptyMissingAnnotation.dhall"-            , parseDirectory </> "failure/unit/ListLitEmptyAnnotation.dhall"--              -- The same performance improvements also broke the-              -- precedence of parsing empty list literals-            , parseDirectory </> "failure/unit/ListLitEmptyPrecedence.dhall"+            [ parseDirectory </> "failure/spacing/LetNoSpace4.dhall"             ]      let pathString = Text.unpack path@@ -177,7 +162,7 @@          case Text.Encoding.decodeUtf8' bytes of             Left _ -> return ()-            Right text -> do+            Right text ->                 case Parser.exprFromText mempty text of                     Left  _ -> return ()                     Right _ -> Tasty.HUnit.assertFailure "Unexpected successful parse" )
tests/Dhall/Test/QuickCheck.hs view
@@ -1,77 +1,110 @@+-- 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 #-}+{-# 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.Monoid ((<>))-import Data.Void (Void)-import Dhall (ToDhall(..), FromDhall(..), auto, extract, inject, embed, Vector)-import Dhall.Map (Map)+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(..)-    , Directory(..)-    , DhallDouble(..)-    , Expr(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , PreferAnnotation(..)-    , Scheme(..)-    , URL(..)-    , Var(..)+    ( 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.Typeable (Typeable, typeRep)-import Data.Proxy (Proxy(..))-import Dhall.Set (Set)-import Dhall.Parser (Header(..), createHeader)-import Dhall.Pretty (CharacterSet(..))-import Dhall.Src (Src(..))-import Dhall.Test.Format (format)-import Dhall.TypeCheck (Typer, TypeError)-import Generic.Random (Weights, W, (%), (:+)(..))+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, Positive(..), Property, NonNegative(..)-    , genericShrink, suchThat, (===), (==>))+    ( Arbitrary (..)+    , Gen+    , NonNegative (..)+    , Positive (..)+    , Property+    , genericShrink+    , suchThat+    , (===)+    , (==>)+    ) import Test.QuickCheck.Instances ()-import Test.Tasty (TestTree)-import Test.Tasty.QuickCheck (QuickCheckTests(..))-import Text.Megaparsec (SourcePos(..), Pos)+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.SpecialValues-import qualified Data.HashSet import qualified Data.Set-import qualified Data.Text as Text-import qualified Data.Map-import qualified Data.HashMap.Strict as HashMap+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.Parser          as Parser import qualified Dhall.Set import qualified Dhall.TypeCheck import qualified Generic.Random-import qualified Numeric.Natural as Nat+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@@ -138,19 +171,22 @@         , (1, fmap (\x -> x - (2 ^ (64 :: Int))) arbitrary)         ] -instance Arbitrary CharacterSet where-    arbitrary = Test.QuickCheck.elements [ ASCII, Unicode ]--instance Arbitrary Header where-    arbitrary = do+whitespace :: Gen Text+whitespace = do       let commentChar =               Test.QuickCheck.frequency                   [ (20, Test.QuickCheck.elements [' ' .. '\DEL'])                   , ( 1, arbitrary)                   ] -          commentText = Text.pack <$> Test.QuickCheck.listOf commentChar+          noInteriorBlockComments text =+              not (Text.isInfixOf "{-" text || Text.isInfixOf "-}" text) +          commentText =+              suchThat+                  (Text.pack <$> Test.QuickCheck.listOf commentChar)+                  noInteriorBlockComments+           multiline = do               txt <- commentText               pure $ "{-" <> txt <> "-}"@@ -170,14 +206,24 @@               , newlines               ] -      pure . createHeader $ Text.unlines comments+      pure $ Text.unlines comments -    shrink (Header txt) = createHeader . Text.pack <$> shrink (Text.unpack txt)+shrinkWhitespace :: Text -> [Text]+shrinkWhitespace "" = []+shrinkWhitespace _  = [""] -instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where+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 ((,) <$> arbitrary <*> arbitrary)+        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)) @@ -187,13 +233,21 @@         .   Dhall.Map.toList  instance (Arbitrary s, Arbitrary a) => Arbitrary (Binding s a) where-    arbitrary =-        let adapt = fmap ((,) Nothing)-            f a b   = Binding Nothing "_" Nothing (adapt a) Nothing b-            g a b c = Binding Nothing a   Nothing (adapt b) Nothing c+    arbitrary = do+        bindingSrc0 <- arbitrary -        in  Test.QuickCheck.oneof [ lift2 f, lift3 g ]+        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@@ -220,13 +274,34 @@      shrink = genericShrink -instance (Arbitrary s, Arbitrary a) => Arbitrary (PreferAnnotation s a) where+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 PreferFromSource-            , PreferFromWith <$> arbitrary-            , pure PreferFromCompletion-            ]+        Test.QuickCheck.oneof [ pure WithQuestion, WithLabel <$> arbitrary ]  instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where     arbitrary =@@ -238,17 +313,31 @@             standardizedExpression       where         customGens-            :: Gen Integer    -- Generates all Integer fields in Expr-            :+ Gen Text.Text  -- Generates all Text fields in Expr+            :: 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 =-               integer+               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@@ -269,6 +358,8 @@             % (1 :: W "BoolEQ")             % (1 :: W "BoolNE")             % (1 :: W "BoolIf")+            % (1 :: W "Bytes")+            % (1 :: W "BytesLit")             % (1 :: W "Natural")             % (7 :: W "NaturalLit")             % (1 :: W "NaturalFold")@@ -293,7 +384,17 @@             % (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")@@ -307,8 +408,6 @@             % (1 :: W "Optional")             % (7 :: W "Some")             % (1 :: W "None")-            % (1 :: W "OptionalFold")-            % (1 :: W "OptionalBuild")             % (1 :: W "Record")             % (7 :: W "RecordLit")             % (1 :: W "Union")@@ -318,6 +417,7 @@             % (7 :: W "RecordCompletion")             % (1 :: W "Merge")             % (1 :: W "ToMap")+            % (1 :: W "ShowConstructor")             % (7 :: W "Field")             % (7 :: W "Project")             % (1 :: W "Assert")@@ -337,17 +437,35 @@     Data.Sequence.null xs standardizedExpression (Note _ _) =     False-standardizedExpression (Combine (Just _) _ _) =+standardizedExpression (Combine _ (Just _) _ _) =     False standardizedExpression With{} =     False-standardizedExpression (Prefer PreferFromCompletion _ _) =+standardizedExpression (Prefer _ PreferFromCompletion _ _) =     False-standardizedExpression (Prefer (PreferFromWith _) _ _) =+-- 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 @@ -359,9 +477,13 @@     shrink = genericShrink  instance Arbitrary Src where-    arbitrary = lift3 Src+    arbitrary = do+        lift2 Src <*> whitespace -    shrink = genericShrink+    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@@ -374,8 +496,21 @@ instance Arbitrary ImportType where     arbitrary =         Test.QuickCheck.oneof-            [ lift2 Local-            , lift5 (\a b c d e -> Remote (URL a b c d e))+            [ 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             ]@@ -394,7 +529,7 @@ -- 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 ]+    arbitrary = Test.QuickCheck.elements [ Code, RawText, Location, RawBytes ]      shrink = genericShrink @@ -409,28 +544,89 @@     shrink = genericShrink  instance Arbitrary URL where-    arbitrary = lift5 URL+    arbitrary = do+        scheme <- arbitrary -    shrink = genericShrink+        -- 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)-            , lift1 (\t -> V t 0)-            , lift1 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 = Dhall.Core.denote expression+    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)@@ -443,12 +639,17 @@ isNormalizedIsConsistentWithNormalize expression =     case maybeProp of         Nothing -> Test.QuickCheck.discard-        Just prop -> prop+        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)-          return $ isNormalized === (nf == 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 =@@ -494,6 +695,18 @@     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@@ -510,10 +723,16 @@  idempotenceTest :: CharacterSet -> Header -> Expr Src Import -> Property idempotenceTest characterSet header expr =-    let once = format characterSet (header, expr)-    in case Parser.exprAndHeaderFromText mempty once of-        Right (format characterSet -> twice) -> once === twice-        Left _ -> Test.QuickCheck.discard+        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 =@@ -547,24 +766,23 @@           , Test.QuickCheck.property normalizingAnExpressionDoesntChangeItsInferredType           , adjustQuickCheckTests 10000           )-        , embedThenExtractIsIdentity (Proxy :: Proxy (Text.Text))+        , ( "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.Text))+        , 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--            -- FIXME: While this test is flaky, we set the number of test cases-            -- to 0 by subtracting the default number of tests (100).-            -- To run the test manually, use e.g.-            --    --quickcheck-tests 1000-          , Test.Tasty.adjustOption (subtract (QuickCheckTests 100))+          , adjustQuickCheckTests 10000           )         ] 
tests/Dhall/Test/Regression.hs view
@@ -5,30 +5,33 @@  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 Data.Text.Prettyprint.Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text import qualified Dhall-import qualified Dhall.Context+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.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 -import Data.Void (Void)-import Dhall.Import (Imported, MissingImports(..))-import Dhall.Parser (Src, SourcedException(..))-import Dhall.TypeCheck (TypeError)-import Test.Tasty (TestTree)-import Test.Tasty.HUnit ((@?=))- tests :: TestTree tests =     Test.Tasty.testGroup "regression tests"@@ -45,6 +48,9 @@         , issue1584         , issue1646         , issue1732+        , issue1884+        , issue2088+        , issue2463         , parsing0         , typeChecking0         , typeChecking1@@ -60,27 +66,37 @@ unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do     let ty = Dhall.auto :: Dhall.Decoder Foo     Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty)-        (Dhall.Core.Union+        (Success (Dhall.Core.Union             (Dhall.Map.fromList-                [   ("Foo",Just (Dhall.Core.Record (Dhall.Map.fromList [-                        ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)])))-                ,   ("Bar",Just (Dhall.Core.Record (Dhall.Map.fromList [-                        ("_1",Dhall.Core.Bool),("_2",Dhall.Core.Bool),("_3",Dhall.Core.Bool)])))-                ,   ("Baz",Just (Dhall.Core.Record (Dhall.Map.fromList [-                        ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Integer)])))+                [   ("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" (Dhall.declared inj) (Dhall.expected ty)+    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) (Dhall.Core.Record (-            Dhall.Map.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.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" (Dhall.declared tu_in) (Dhall.expected tu_ty)+    Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Success $ Dhall.declared tu_in) (Dhall.expected tu_ty)      return () ) @@ -103,7 +119,7 @@                     case Control.Exception.fromException e :: Maybe (Imported (TypeError Src Void)) of                         Just _ -> return True                         Nothing -> return False-                handler _ = do+                handler _ =                     return True              let typeCheck = do@@ -149,9 +165,9 @@     -- Verify that pretty-printing preserves string interpolation     source <- Data.Text.IO.readFile "./tests/regression/issue216b.dhall"     e <- Util.code source-    let doc       = Data.Text.Prettyprint.Doc.pretty e+    let doc       = Prettyprinter.pretty e     let docStream = Dhall.Pretty.layout doc-    let text0 = Data.Text.Prettyprint.Doc.Render.Text.renderLazy docStream+    let text0 = Prettyprinter.Render.Text.renderLazy docStream      text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall" @@ -160,7 +176,7 @@ 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 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@@ -204,8 +220,40 @@     _ <- 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" (do+parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (     -- Verify that parsing should not fail     --     -- In 267093f8cddf1c2f909f2d997c31fd0a7cb2440a I broke the parser when left
+ 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
@@ -2,20 +2,17 @@  module Dhall.Test.SemanticHash where -import Data.Monoid((<>))-import Data.Text (Text)-import Prelude hiding (FilePath)+import Data.Text  (Text) import Test.Tasty (TestTree)-import Turtle (FilePath) -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 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
tests/Dhall/Test/Substitution.hs view
@@ -1,15 +1,17 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric     #-} {-# LANGUAGE OverloadedStrings #-}  module Dhall.Test.Substitution where -import Data.Void (Void)-import Dhall.Core (Expr(BoolLit, Var))-import Dhall.Src (Src)+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.Family   as Lens+import qualified Lens.Micro             as Lens  data Result = Failure Integer | Success String     deriving (Eq, Dhall.Generic, Show)@@ -17,15 +19,18 @@ instance Dhall.FromDhall Result  substituteResult :: FilePath -> IO Result-substituteResult fp = let-    evaluateSettings = Lens.over Dhall.substitutions (Dhall.Map.insert "Result" resultType) Dhall.defaultEvaluateSettings-    in Dhall.inputFileWithSettings evaluateSettings resultDecoder fp+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 :: Expr Src Void-resultType = Dhall.expected resultDecoder+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
tests/Dhall/Test/TH.hs view
@@ -1,19 +1,20 @@-{-# LANGUAGE CPP                #-} {-# LANGUAGE DeriveAnyClass     #-} {-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances  #-} {-# LANGUAGE OverloadedStrings  #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell    #-} -#if MIN_VERSION_template_haskell(2,12,0)-{-# LANGUAGE DerivingStrategies #-}-#endif- module Dhall.Test.TH where -import Dhall.TH (HaskellType(..))-import Test.Tasty (TestTree)+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@@ -27,6 +28,7 @@ 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@@ -35,6 +37,24 @@ 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 ] @@ -55,3 +75,145 @@     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
@@ -2,12 +2,10 @@  module Dhall.Test.Tags where -import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall.Util (Input(..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+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@@ -31,7 +29,9 @@ tagsTest :: Text -> TestTree tagsTest prefix =     Tasty.HUnit.testCase (Text.unpack prefix) $ do-        let inputFile  = Text.unpack (prefix <> ".dhall")+        -- 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@@ -45,7 +45,7 @@ tagsDirTest :: TestTree tagsDirTest =     Tasty.HUnit.testCase "all" $ do-        let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory Turtle.</> "all.tags"+        let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory </> "all.tags"          actualTags <- fmap fixPathSeparators                       (Tags.generate
tests/Dhall/Test/Tutorial.hs view
@@ -11,12 +11,11 @@ import qualified Test.Tasty import qualified Test.Tasty.HUnit -import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall (ToDhall)-import GHC.Generics (Generic)-import Numeric.Natural (Natural)-import Test.Tasty (TestTree)+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/Dhall/Test/TypeInference.hs view
@@ -1,14 +1,12 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}  module Dhall.Test.TypeInference where -import Control.Exception (SomeException(..))-import Data.Monoid (mempty, (<>))-import Data.Text (Text)-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+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@@ -28,8 +26,20 @@  getTests :: IO TestTree getTests = do-    let successTestFiles = Turtle.lstree (typeInferenceDirectory </> "success")+    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")@@ -47,11 +57,9 @@ successTest prefix = do     let expectedFailures =                 []--#ifdef WITH_HTTP+#if defined(WITH_HTTP) && defined(NETWORK_TESTS) #else             ++  [ typeInferenceDirectory </> "success/CacheImports"-                , typeInferenceDirectory </> "success/CacheImportsCanonicalize"                 ] #endif @@ -87,15 +95,18 @@          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 =-               [ typeInferenceDirectory </> "failure/unit/MergeEmptyNeedsDirectAnnotation1"-+               [                -- Duplicate fields are incorrectly caught during parsing:                -- https://github.com/dhall-lang/dhall-haskell/issues/772-               , typeInferenceDirectory </> "failure/unit/RecordProjectionDuplicateFields"-               , typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields"+                 typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields"                , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants1"                , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants2"                ]
tests/Dhall/Test/Util.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE ViewPatterns      #-}  module Dhall.Test.Util     ( code@@ -18,42 +20,60 @@     , 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 (Expr, Normalizer, ReifiedNormalizer(..), Import)-import Dhall.Import (Status(..), SemanticCacheMode(..))-import Data.Monoid((<>))-import Dhall.Parser (Src)-import Prelude hiding (FilePath)+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 Test.Tasty (TestTree)-import Turtle (FilePath, Pattern, Shell, fp)+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 Control.Monad.Trans.State.Strict as State import qualified System.FilePath                  as FilePath import qualified Test.Tasty                       as Tasty import qualified Test.Tasty.ExpectedFailure       as Tasty.ExpectedFailure import qualified Turtle -#ifndef WITH_HTTP-import Control.Monad.IO.Class (MonadIO(..))-import Dhall.Core (URL(..))-import Lens.Family.State.Strict (zoom)+#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@@ -90,62 +110,85 @@         (loadWith expression)         (Dhall.Import.emptyStatus rootDirectory) { _semanticCacheMode = semanticCacheMode } -#ifdef WITH_HTTP+#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-    let mockRemote' url = do-            liftIO . putStrLn $ "\nTesting without real HTTP support --"-                ++ " using mock HTTP client to resolve remote import."-            mockRemote url-    zoom Dhall.Import.remote (State.put mockRemote')+    zoom Dhall.Import.remote (State.put mockRemote)     Dhall.Import.loadWith expr  mockRemote :: Dhall.Core.URL -> StateT Status IO Data.Text.Text--- Matches anything pointing to--- `https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/`-mockRemote (URL { authority = "raw.githubusercontent.com"-                , path = Dhall.Core.File (Dhall.Core.Directory components) file })-  | take 3 (reverse components) == ["dhall-lang", "dhall-lang", "master"] = do-    let dropEnd n ls = take (length ls - n) ls-    let localDir = dropEnd 3 components ++ ["dhall-lang"]+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 (Dhall.Core.File (Dhall.Core.Directory localDir) file)-    liftIO $ Data.Text.IO.readFile localPath+    localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file) --- Matches anything pointing to--- `https://test.dhall-lang.org/Bool/package.dhall`; checks that a `test` header--- is present and redirects to the local copy of the prelude.-mockRemote (URL { authority = "test.dhall-lang.org"-                , path = Dhall.Core.File (Dhall.Core.Directory components) file-                , headers = Just headersExpr }) =-    case Data.Foldable.find ((== "test") . fst) hs of-        Nothing -> fail $ "(mock http) Tried to load an import from "-                          ++"\"test.dhall-lang.org\""-                          ++ "without setting the \"test\" header field."-        Just (_, _) -> do-            let localDir = components ++ ["Prelude", "dhall-lang"]-            localPath <- Dhall.Import.localToPath Dhall.Core.Here (Dhall.Core.File (Dhall.Core.Directory localDir) file)-            liftIO $ Data.Text.IO.readFile localPath-  where-    hs = Dhall.Import.toHeaders headersExpr+    liftIO (Data.Text.IO.readFile localPath) --- Emulates `https://httpbin.org/user-agent`-mockRemote (URL { authority = "httpbin.org"-                , path = Dhall.Core.File (Dhall.Core.Directory []) "user-agent"-                , headers = Just headersExpr }) =-    case Data.Foldable.find ((== "user-agent") . fst) hs of-        Nothing -> fail $ "(mock http) Tried to read the user agent via "-                          ++ "\"httpbin.com/user-agent\" without supplying one "-                          ++ "in the header!"-        Just (_, userAgent) -> do+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")-  where-    hs = Dhall.Import.toHeaders headersExpr+        (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)@@ -153,6 +196,57 @@         <> 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)@@ -199,7 +293,7 @@     let shell = do             path_ <- paths -            let pathText = Turtle.format fp path_+            let pathText = Turtle.format fp (FilePath.normalise path_)              prefix : _ <- return (Turtle.match pattern pathText) @@ -211,15 +305,29 @@  testCase :: Text -> [ FilePath ] -> Assertion -> TestTree testCase prefix expectedFailures assertion =-    if prefix `elem` map (Turtle.format fp) expectedFailures+    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 "\\" "/"+toDhallPath = ("./" <>) . Text.replace "\\" "/"
+ 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
@@ -18,7 +18,7 @@ , someList =     Some       [ aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccc, dddddddddddddd ]-, merge =+, merge1 =     merge       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@@ -27,7 +27,7 @@       a       b       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc-, toMap =+, toMap1 =     toMap       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }
tests/format/applicationMultilineB.dhall view
@@ -20,7 +20,7 @@   , cccccccccccccccccccccccc   , dddddddddddddd   ]-, merge =+, merge1 =     merge       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@@ -29,6 +29,6 @@       a       b       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc-, toMap = toMap+, toMap1 = toMap     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }
+ 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/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/headerA.dhall view
@@ -1,4 +1,4 @@    -{- bla -}+{- bla -}     True
tests/format/headerB.dhall view
@@ -1,3 +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/ipfsB.dhall view
@@ -11,7 +11,8 @@       labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` }  let k8s =-      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd+      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall+        sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd  let serviceName = "ipfs" 
tests/format/issue1400-1A.dhall view
@@ -1,6 +1,6 @@ { conversation =-    [ { author = "robert", content = [] }-    , { author = "robert", content = [] }+    [ { author = "robert", content = xs }+    , { author = "robert", content = xs }     , { author =           "bob"       , content =
tests/format/issue1400-1B.dhall view
@@ -1,6 +1,6 @@ { conversation =-  [ { author = "robert", content = [] }-  , { author = "robert", content = [] }+  [ { author = "robert", content = xs }+  , { author = "robert", content = xs }   , { author = "bob"     , content =       [ text
tests/format/issue1400-2B.dhall view
@@ -3,7 +3,8 @@     = λ(a : Type) →         { field : Text         , nesting :-              ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+              ./Nesting+                sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335             ? ./Nesting         , contents : a         }
+ 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/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/largeRecordA.dhall view
@@ -2,7 +2,6 @@ -- -- To exercise all options documented in https://nethackwiki.com/wiki/Options -- see `./unvalidated.dhall`- let types = ./../types.dhall  let defaults = ./../defaults.dhall
tests/format/largeRecordB.dhall view
@@ -2,7 +2,6 @@ -- -- To exercise all options documented in https://nethackwiki.com/wiki/Options -- see `./unvalidated.dhall`- let types = ./../types.dhall  let defaults = ./../defaults.dhall
+ 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/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/numericLiteralsA.dhall view
@@ -1,1 +1,1 @@-{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20 }+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
tests/format/numericLiteralsB.dhall view
@@ -1,1 +1,1 @@-{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20 }+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
+ 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/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/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/sha256PrintingB.dhall view
@@ -1,4 +1,5 @@ let replicate =-      https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c+      https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate+        sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c  in  replicate 5
+ 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/urlsA.dhall view
@@ -4,10 +4,4 @@  let reserved = http://x/y:z -let quoted = http://x/"y:z"--let quotedPercent = http://x/"y%z"--let snowman = http://x/"y☃z"- in "done"
tests/format/urlsB.dhall view
@@ -4,10 +4,4 @@  let reserved = http://x/y:z -let quoted = http://x/y%3Az--let quotedPercent = http://x/y%25z--let snowman = http://x/y%E2%98%83z- 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/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/True.dhall
@@ -1,1 +0,0 @@-True
+ 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/cachedA.dhall
@@ -1,2 +0,0 @@-  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
− tests/freeze/cachedB.dhall
@@ -1,2 +0,0 @@-  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
− tests/freeze/incorrectHashA.dhall
@@ -1,1 +0,0 @@-./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
− tests/freeze/incorrectHashB.dhall
@@ -1,2 +0,0 @@-  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
− tests/freeze/protectedA.dhall
@@ -1,1 +0,0 @@-./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
− tests/freeze/protectedB.dhall
@@ -1,2 +0,0 @@-  ./True.dhall 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/freeze/unprotectedA.dhall
@@ -1,1 +0,0 @@-./True.dhall
− tests/freeze/unprotectedB.dhall
@@ -1,2 +0,0 @@-  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
+ 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/multiletA.dhall view
@@ -1,5 +1,4 @@ -- example0.dhall- let Person     : Type     =   ∀(Person : Type)@@ -21,7 +20,7 @@  let everybody     : Person → List Text-    = let concat = http://prelude.dhall-lang.org/List/concat+    = let concat = http://prelude.dhall-lang.org/List/concat.dhall              in    λ(x : Person)           → x
tests/lint/success/multiletB.dhall view
@@ -1,5 +1,4 @@ -- example0.dhall- let Person     : Type     = ∀(Person : Type) →@@ -20,7 +19,7 @@  let everybody     : Person → List Text-    = let concat = http://prelude.dhall-lang.org/List/concat+    = let concat = http://prelude.dhall-lang.org/List/concat.dhall        in  λ(x : Person) →             x
− tests/lint/success/optionalFoldBuildA.dhall
@@ -1,4 +0,0 @@-{ example0 = Optional/fold-, example1 = Optional/build-, example2 = Optional/fold Natural (Some 1) Bool Natural/even False-}
− tests/lint/success/optionalFoldBuildB.dhall
@@ -1,18 +0,0 @@-{ example0 =-    λ(a : Type) →-    λ(o : Optional a) →-    λ(optional : Type) →-    λ(some : a → optional) →-    λ(none : optional) →-      merge { Some = some, None = none } o-, example1 =-    λ(a : Type) →-    λ ( build-      : ∀(optional : Type) →-        ∀(some : a → optional) →-        ∀(none : optional) →-          optional-      ) →-      build (Optional a) (λ(x : a) → Some x) (None a)-, example2 = merge { Some = Natural/even, None = False } (Some 1)-}
tests/lint/success/regression0A.dhall view
@@ -1,4 +1,4 @@-    let replicate = https://prelude.dhall-lang.org/List/replicate+    let replicate = https://prelude.dhall-lang.org/List/replicate.dhall  in  let Config = { name : Text, age : Natural } 
tests/lint/success/regression0B.dhall view
@@ -1,3 +1,3 @@-let replicate = https://prelude.dhall-lang.org/List/replicate+let replicate = https://prelude.dhall-lang.org/List/replicate.dhall  in  replicate 10 Text "!"
+ 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/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/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/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/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